Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2026-10-15 08:17:18

0001 #include "CalcRm.h"
0002 #include "fluct_common.h"
0003 #include "CrossingCorrect.h"    // README_Crossing: dirty-side rule + correction, shared verbatim with Finalize
0004 #include "CQResonances.h"       // README_meanpT_from_CQ: ir2=2 Q binning, shared with the C(Q) signposts
0005 #include "ZvtxAverage.h"        // README_Finalize: Zvtx average over valid bins, shared with Finalize
0006 
0007 //------------------------------------------------------------
0008 void Swap(double &a, double &b){
0009     double a0=a; a=b; b=a0;
0010 }
0011 
0012 //------------------------------------------------------------
0013 CalcRm::CalcRm(){
0014     //
0015     fDoCrossing         = false;    // set externally
0016     fDirtySide          = 0;        // set in Book()
0017     fField              = 0.;       // set externally (SetField) and in Increment()
0018     fTSepDy             = 0.;       // README_SplitTracks573 sec 11: pair cut OFF
0019     fTSepDphi           = 0.;
0020     fTSepMin            = false;
0021     fISepDphi           = 0.;       // README_SplitTracks573 sec 29: OFF
0022     for (int a=0;a<2;a++) for (int b=0;b<3;b++) nPairCut[a][b] = 0;
0023     fPairSM             = 0;
0024     fDoBaseline         = false;    // set externally
0025     fDoMinvCut          = false;    // set externally (option does not presently exist for convolution)
0026     fDoMinvCutb         = false;    // set internally (2nd parent mass for ULS Kaons)
0027     fDoMinvLLCut        = false;    // set externally (option does not presently exist for convolution)
0028     fDoQcut             = false;    // set externally
0029     fExcludeAdjTF       = 0;        // sec 18.23, OFF by default
0030     for (int iz=0;iz<NZVTXMAX;iz++){ nComb_used[iz]=0; nComb_possible[iz]=0; }
0031     fCurrentRun         = 0;        // sec 18.20, set externally each event via SetCurrentRunEvt()
0032     fCurrentNch         = 0;        // sec 34, set externally each event via SetCurrentNch()
0033     fCurrentEvt         = 0;
0034     nMixedPairs_total       = 0;
0035     nMixedPairs_sameTF      = 0;
0036     nMixedPairs_neighborTF  = 0;
0037                                     // if true, enable the calculation of dQ and Minv even if not enabled by calling routine
0038     fDistinguishable    = false;
0039     fLikeSign           = false;
0040     fUseEta1            = false;
0041     fUseEta2            = false;
0042     fFlipDy             = false;        // set externally
0043     //
0044     fQcut   = 0.15;
0045     //
0046     YNB1    = 20;
0047     YL1     = -0.5;
0048     YU1     =  0.5;
0049     YBW1    = (YU1-YL1)/YNB1;
0050     YNB2    = 20;
0051     YL2     = -0.5;
0052     YU2     =  0.5;
0053     YBW2    = (YU2-YL2)/YNB2;
0054     //
0055     DYBW    = YBW1;         // code will require that YBW1=YBW2...
0056     DYL     = YL1 - YU2 + DYBW/2.;
0057     DYU     = YU1 - YL2 - DYBW/2.;
0058     DYNB    = (DYU-DYL)/DYBW;
0059     //
0060     PHINB   =  12 ;     
0061     PHIL    =   0.;     
0062     PHIU    = 360.;     
0063     DPHINB  = PHINB;
0064     DPHIL   = -90.;
0065     DPHIU   = 270.;
0066     PTNB1   =    1;     // needed only for rho1 (saved to allow convolution in finalize) calculated in code!
0067     PTNB2   =    1;     // needed only for rho1 (saved to allow convolution in finalize) calculated in code!
0068     PTL1    =   0.2000000;
0069     PTU1    =   2.0000000;      
0070     PTL2    =   0.2000000;      
0071     PTU2    =   2.0000000;      
0072     ZVTXNB  =  30;
0073     ZVTXL   = -30.;
0074     ZVTXU   = +30.;
0075     //
0076     fPid1   = -1 ;
0077     fPid2   = -1 ;
0078     fChg1   =  0.;
0079     fChg2   =  0.;
0080     fMass1  =  0.;
0081     fMass2  =  0.;
0082     //
0083     MAXMULT = 100;
0084     //
0085     NMIX            = 5;    // can be changed via inline function SetNMIX
0086     //
0087     //npair_all_S       = 0;
0088     //npair_dylow1_S    = 0;
0089     //npair_dylow2_S    = 0;
0090     //npair_dylow3_S    = 0;
0091     //npair_qlow_S      = 0;
0092     //npair_mlow_S      = 0;
0093     //npair_all_M       = 0;
0094     //npair_dylow1_M    = 0;
0095     //npair_dylow2_M    = 0;
0096     //npair_dylow3_M    = 0;
0097     //npair_qlow_M      = 0;
0098     //npair_mlow_M      = 0;
0099     //
0100     raddeg  = 180./M_PI;
0101     //
0102 //  TimerIncrement  = new TStopwatch();
0103 //  TimerIncrement  ->Stop();
0104 //  TimerIncrement  ->Reset();
0105 //  TimerCalculate  = new TStopwatch();
0106 //  TimerCalculate  ->Stop();
0107 //  TimerCalculate  ->Reset();
0108 //  fTimeIncrement  = 0;
0109 //  fTimeCalculate  = 0;
0110     //
0111 }
0112 
0113 //------------------------------------------------------------
0114 CalcRm::~CalcRm(){
0115     //
0116     //delete[] hmult;       //hmult=0;
0117     //delete[] hrho2;       //hrho2=0;
0118     //delete[] hR2;         //hR2=0;
0119     //delete hm2D;          hm2D=0;
0120     //delete[] hR2dy;       //hR2dy=0;
0121     //delete[] hR2dye;      //hR2dye=0;
0122     //delete[] hR2dyN;      //hR2dyN=0;
0123     //
0124 }
0125 
0126 //------------------------------------------------------------
0127 void CalcRm::UpdateBinningPars(){
0128     YBW1    = (YU1-YL1)/YNB1;
0129     YBW2    = (YU2-YL2)/YNB2;
0130     YBW     = YBW1;
0131     //---- 2026-09-30 (user): the y widths of the two species need not match, and the dy width of the (dy,dphi) maps (the
0132     //---- physics CF) is set per pair type (PairTypes_Info[][3]; since 2026-10-05 the same width as y1, y2). Odd bin count, dy = 0 at a bin centre, covering
0133     //---- abs(dy) < (m+0.5) DYBW <= YU1-YL2 (the outermost half bin is dropped, as before).
0134     DYBW    = (fDYBWset>0.) ? fDYBWset : YBW1;
0135     double dyMax    = 0.5*((YU1-YL2)+(YU2-YL1));
0136     int m   = (int)floor(dyMax/DYBW - 0.5 + 1.e-6);
0137     DYNB    = 2*m+1;
0138     DYU     = (m+0.5)*DYBW;
0139     DYL     = -DYU;
0140     //cout<<"CalcRm::UpdateBinningPars .. "
0141     //  <<YL1<<" "<<YU1<<" "<<YNB1<<" bw="<<YBW1<<" \t"
0142     //  <<YL2<<" "<<YU2<<" "<<YNB2<<" bw="<<YBW2<<" \t"
0143     //  <<DYL<<" "<<DYU<<" "<<DYNB<<" bw="<<DYBW<<" \t"
0144     //  <<endl;
0145     //
0146     DPHINB  = PHINB;
0147     PHIBW   = (PHIU-PHIL)/PHINB;
0148     PTNB1   = (PTU1-PTL1)/0.1;      // used only to bin rho1 (not needed for mixing, just saving it)
0149     PTNB2   = (PTU2-PTL2)/0.1;      // used only to bin rho1 (not needed for mixing, just saving it)
0150     ZVTXBW  = (ZVTXU-ZVTXL)/ZVTXNB; 
0151     //
0152 }
0153 
0154 //------------------------------------------------------------
0155 void CalcRm::Book(){
0156     //
0157     UpdateBinningPars();
0158     //cout<<"CalcRm::Book .. Y1-limits = "<<YL1<<" "<<YU1<<endl; 
0159     //cout<<"CalcRm::Book .. Y2-limits = "<<YL2<<" "<<YU2<<endl;
0160     //cout<<"CalcRm::Book ..  f-limits = "<<PHIL<<" "<<PHIU<<endl; 
0161     //cout<<"CalcRm::Book .. DY-limits = "<<DYL<<" "<<DYU<<endl;
0162     //cout<<"CalcRm::Book .. Df-limits = "<<DPHIL<<" "<<DPHIU<<endl;
0163     //
0164     if (fPid1<0. || fPid2<0.){
0165         cout<<"CalcRm::Book .. Pid undefined! exit...."<<fPid1<<" "<<fPid2<<endl; exit(0); 
0166     }
0167     fDistinguishable                    = true; 
0168     if (fPid1==fPid2) fDistinguishable  = false;
0169     int ispe1   = GetSpecies(fPid1);
0170     int ispe2   = GetSpecies(fPid2);
0171     fUseEta1    = IsHadronParticleID(fPid1);        // h+, h-: the loop passes eta, not y (2026-10-11)
0172     fUseEta2    = IsHadronParticleID(fPid2);
0173     if (fUseEta1 || fUseEta2) cout<<"CalcRm::Book .. h+/h- leg(s): eta, not y (leg1 "<<(int)fUseEta1<<", leg2 "<<(int)fUseEta2<<"); 4-momenta with the pion mass"<<endl;
0174     fChg1       = ParticleCharge[fPid1];
0175     fChg2       = ParticleCharge[fPid2];
0176     fMass1      = Species_mass[ispe1];
0177     fMass2      = Species_mass[ispe2];
0178 //  if (fChg1==0. || fChg2==0.){
0179 //      cout<<"CalcRm::Book .. Chg undefined! exit...."<< endl; exit(0); 
0180 //  }
0181     if (fMass1==0. || fMass2==0.){
0182         cout<<"CalcRm::Book .. Masses undefined! exit...."<< endl; exit(0); 
0183     }
0184     if (fChg1*fChg2>0.) fLikeSign   = true;     // allow +e and +2e particles to be crossing corrected
0185     //
0186     //---- crossing correction: dirty side (README_Crossing sec 8, step 3)
0187     fDirtySide  = CrossingDirtySide(fField,fChg1,fChg2);
0188     cout<<"CalcRm::Book .. crossing: doCrossing="<<(int)fDoCrossing<<"  field="<<fField
0189         <<"  chg1="<<fChg1<<" chg2="<<fChg2<<"  dirty side = "<<fDirtySide
0190         <<(fDirtySide>0?" (dphi>0)":(fDirtySide<0?" (dphi<0)":" (none)"))<<endl;
0191     //
0192     //
0193     if (NMIX>NMIXMAX){ cout<<"CalcRm::Book .. NMIX too large .. "<<NMIX<<" "<<NMIXMAX<<endl; exit(0); }
0194     //
0195     //---- Minv cut setup...
0196     bool enable         = false;
0197     fMinvCut_m0         = 0;
0198     fMinvCutb_m0        = 0;
0199     fMinvCut_dm         = 0;
0200     fMinvCut_mlower     = 0;
0201     fMinvCut_mupper     = 0;
0202     fMinvCutb_mlower    = 0;
0203     fMinvCutb_mupper    = 0;
0204     if (fDoMinvCut){
0205         // Ks = pi+ + pi-
0206         if ( (fPid1==kParticleIDPionPlus    && fPid2==kParticleIDPionMinus   )
0207           || (fPid1==kParticleIDPionMinus   && fPid2==kParticleIDPionPlus    ) ){ enable=true; fMinvCut_m0=0.493677; fMinvCut_dm=0.01; } else
0208         // phi = K+ + K-
0209         if ( (fPid1==kParticleIDKaonPlus    && fPid2==kParticleIDKaonMinus   )
0210           || (fPid1==kParticleIDKaonMinus   && fPid2==kParticleIDKaonPlus    ) ){ enable=true; fMinvCut_m0=1.019461; fDoMinvCutb=true; fMinvCutb_m0=1.86484; fMinvCut_dm=0.01; } else
0211         // L = p+ + pi-
0212         if ( (fPid1==kParticleIDProton      && fPid2==kParticleIDPionMinus   )
0213           || (fPid1==kParticleIDPionMinus   && fPid2==kParticleIDProton      ) ){ enable=true; fMinvCut_m0=1.115683; fMinvCut_dm=0.01; } else
0214         // Lbar = p- + pi+
0215         if ( (fPid1==kParticleIDAntiProton  && fPid2==kParticleIDPionPlus    )
0216           || (fPid1==kParticleIDPionPlus    && fPid2==kParticleIDAntiProton  ) ){ enable=true; fMinvCut_m0=1.115683; fMinvCut_dm=0.01; }
0217     }
0218     if (!enable){   // disable flag if enabled in loop but this is not a pair that has a decay in it... 
0219         fDoMinvCut  = false;
0220         fDoMinvCutb = false;
0221     } else {
0222         //cout<<"CalcRm::Book .. Minv Cut Enabled."<<endl;
0223         fMinvCut_mlower         = fMinvCut_m0 - fMinvCut_dm;
0224         fMinvCut_mupper         = fMinvCut_m0 + fMinvCut_dm;
0225         cout<<"CalcRm::Book .. Pairs with inv Mass of "<<fMinvCut_m0<<" GeV +/- "<<1000.*fMinvCut_dm<<" MeV will be removed."<<endl;
0226         if (fDoMinvCutb){
0227             cout<<"CalcRm::Book .. Pairs with inv Mass of "<<fMinvCutb_m0<<" GeV +/- "<<1000.*fMinvCut_dm<<" MeV will ALSO be removed."<<endl;
0228             fMinvCutb_mlower    = fMinvCutb_m0 - fMinvCut_dm;
0229             fMinvCutb_mupper    = fMinvCutb_m0 + fMinvCut_dm;
0230         }
0231     } 
0232     if (fDoMinvLLCut){
0233         cout<<"CalcRm::Book .. Minv Lower Limit Cut Enabled. Pairs with inv Mass less <=4 MeV above minimum will be rejected."<<endl;
0234     } 
0235     //---- end Minv cut setup...
0236     //
0237     NCombinations2  = 0;
0238     for (int iev=0;iev<NMIX;iev++){
0239     for (int jev=iev+1;jev<NMIX;jev++){         // as defined, jev cannot equal iev... 
0240         ++NCombinations2;
0241     }
0242     }
0243     //cout<<"CalcRm::Book .. NMIX, NCombinations2 = "<<NMIX<<", "<<NCombinations2<<endl;
0244     //
0245     //
0246     //---- If mixing using combinations of events (instead of brute-force looping), set that up
0247 //  int ai2[2]  = {0,1};
0248 //  vector<int> v2(ai2,ai2+2);
0249 //  //for (int izv=0;izv<ZVTXNB;izv++){
0250 //  //  NCombinations2_Seen[izv] = 0;   // total number of equivalent mixed events seen over all events incremented to this class
0251 //  //}
0252 //  //---- calculate the number of unique k-combinations for the given value of NMIX...
0253 //  for (int kmix=2;kmix<=NMIXMAX;kmix++){
0254 //      int kcomb   = 2;
0255 //      if (kmix>=kcomb){
0256 //          //cout<<kcomb<<" of "<<kmix<<" \t ";
0257 //          if (kmix==NMIX){
0258 //              int thisval = factorial(kmix)/factorial(kcomb)/factorial(kmix-kcomb);
0259 //              if (kcomb==2)NCombinations2 = thisval;
0260 //              //cout<<thisval<<" \t ";
0261 //          }
0262 //      } else {
0263 //          //cout<<"X \t ";
0264 //      }
0265 //      //cout<<endl;
0266 //  }
0267 //  //
0268 //  //cout<<"CalcRm::Book .. NMIX="<<NMIX<<" \t NCombinations2="<<NCombinations2
0269 //  //  <<" \t DenomStatsFactor="<<((double)NCombinations2)/NMIX<<endl;
0270 //  //
0271 //  //---- find the event IDs (modulo NMIX) for all of the the unique 2-combinations of NMIX events
0272 //  int icomb   = 0;
0273 //  for (int i=0;i<NCOMBMAX;i++){
0274 //      if (i==0){ for (int j=0;j<2;j++){ Combinations2[j][icomb]=v2[j]; } ++icomb; }
0275 //      if (NextCombination(v2,2,NMIX)){
0276 //          for (int j=0;j<2;j++){ Combinations2[j][icomb]=v2[j]; } ++icomb;
0277 //      } else { break; }
0278 //  }
0279 //  if (icomb!=NCombinations2){
0280 //      cout<<"CalcR4M::UpdateBinningParameters .. Combinations indexing problem... NCOMBMAX="<<NCOMBMAX
0281 //          <<" .. NComb2: "<<NCombinations2<<" "<<icomb<<endl; 
0282 //      exit(0);
0283 //  }
0284     //
0285     //------------------------------------------
0286     //
0287     hzvtx       = new TH1D("hzvtx","hzvtx",ZVTXNB,ZVTXL,ZVTXU);
0288     axiszvtx    = hzvtx->GetXaxis();
0289     //
0290     //---- ir2=2 (Q_inv, pT_pair) axes (README_meanpT_from_CQ.md sec 11): Q variable width per species pair,
0291     //---- fine where CQResonances.h lists a peak of this pair; pT_pair uniform
0292     const std::vector<double> qedges    = QBinEdges(fPid1,fPid2);
0293     const int nqbins                    = (int)qedges.size()-1;
0294     cout<<"CalcRm::Book .. ir2=2 (Q,pT_pair): "<<nqbins<<" Q bins x "<<QPT_NPT<<" pT_pair bins; Q (GeV @ MeV): "<<QBinSummary(qedges)<<endl;
0295     int YNB1_rho1   = YNB1;     // can be integer multiples of these parameters!
0296     int YNB2_rho1   = YNB2;     // can be integer multiples of these parameters!
0297     int PHINB_rho1  = PHINB;    // can be integer multiples of these parameters!
0298     int PTNB1_rho1  = PTNB1;    // this one is calculated based on PTL and PTU!!!
0299     int PTNB2_rho1  = PTNB2;    // this one is calculated based on PTL and PTU!!!
0300     //
0301     //---- start booking...
0302     for (int izv=0;izv<ZVTXNB+1;izv++){         // note one additional histogram here
0303         //
0304         mix_nevt[izv]   = 0;
0305         //
0306         hmult[izv]      = new TH2D( Form("hmult%d"  ,izv), Form("hmult%d"  ,izv), MAXMULT+1,-0.5,((double)MAXMULT)+0.5,MAXMULT+1,-0.5,((double)MAXMULT)+0.5);
0307         //hmultc[izv]   = new TH2D( Form("hmultc%d" ,izv), Form("hmultc%d" ,izv), MAXMULT+1,-0.5,((double)MAXMULT)+0.5,MAXMULT+1,-0.5,((double)MAXMULT)+0.5);
0308         //
0309         hrho1_1[izv]    = new TH3D(Form("hrho1_1%d",izv),Form("hrho1_1%d",izv),YNB1_rho1,YL1,YU1,PHINB_rho1,PHIL,PHIU,PTNB1_rho1,PTL1,PTU1);
0310         hrho1_2[izv]    = new TH3D(Form("hrho1_2%d",izv),Form("hrho1_2%d",izv),YNB2_rho1,YL2,YU2,PHINB_rho1,PHIL,PHIU,PTNB2_rho1,PTL2,PTU2);
0311         hrho1_1[izv]    ->Sumw2();
0312         hrho1_2[izv]    ->Sumw2();
0313         //
0314         hy1_[izv]       = new TH1D(Form("hy1_%d" ,izv),Form("hy1_%d" ,izv),YNB1_rho1,YL1,YU1);
0315         hy2_[izv]       = new TH1D(Form("hy2_%d" ,izv),Form("hy2_%d" ,izv),YNB2_rho1,YL2,YU2);
0316         hyc1_[izv]      = new TH1D(Form("hyc1_%d",izv),Form("hyc1_%d",izv),YNB1_rho1,YL1,YU1);
0317         hyc2_[izv]      = new TH1D(Form("hyc2_%d",izv),Form("hyc2_%d",izv),YNB2_rho1,YL2,YU2);
0318         //
0319         for (int ir2=0;ir2<NR2TYPES;ir2++){
0320             if (ir2==0){                        //----- (y1,y2) ------
0321                 hrho2_S[ir2][izv]       = new TH2D( Form("hrho2_S%d%d",ir2,izv), Form("hrho2_S%d%d",ir2,izv),YNB1,YL1,YU1,YNB2,YL2,YU2);
0322                 hrho2_M[ir2][izv]       = new TH2D( Form("hrho2_M%d%d",ir2,izv), Form("hrho2_M%d%d",ir2,izv),YNB1,YL1,YU1,YNB2,YL2,YU2);
0323                 hC2[ir2][izv]           = new TH2D( Form("hC2%d%d"    ,ir2,izv), Form("hC2%d%d"    ,ir2,izv),YNB1,YL1,YU1,YNB2,YL2,YU2);
0324                 hR2[ir2][izv]           = new TH2D( Form("hR2%d%d"    ,ir2,izv), Form("hR2%d%d"    ,ir2,izv),YNB1,YL1,YU1,YNB2,YL2,YU2);
0325                 //if(izv==0)hm2D[ir2]       = new TH2D( Form("hm2D%d"     ,ir2    ), Form("hm2D%d"     ,ir2    ),YNB1,YL1,YU1,YNB2,YL2,YU2);
0326 //dptM              hrho2_S_dptP[ir2][izv]  = new TH2D( Form("hrho2_S_dptP%d%d",ir2,izv), Form("hrho2_S_dptP%d%d",ir2,izv),YNB1,YL1,YU1,YNB2,YL2,YU2);
0327 //dptM              hrho2_M_dptP[ir2][izv]  = new TH2D( Form("hrho2_M_dptP%d%d",ir2,izv), Form("hrho2_M_dptP%d%d",ir2,izv),YNB1,YL1,YU1,YNB2,YL2,YU2);
0328 //dptM              hrho2_S_dptN[ir2][izv]  = new TH2D( Form("hrho2_S_dptN%d%d",ir2,izv), Form("hrho2_S_dptN%d%d",ir2,izv),YNB1,YL1,YU1,YNB2,YL2,YU2);
0329 //dptM              hrho2_M_dptN[ir2][izv]  = new TH2D( Form("hrho2_M_dptN%d%d",ir2,izv), Form("hrho2_M_dptN%d%d",ir2,izv),YNB1,YL1,YU1,YNB2,YL2,YU2);
0330             } else if (ir2==1){                 //----- (dy,dphi) ------
0331                 hrho2_S[ir2][izv]   = new TH2D( Form("hrho2_S%d%d",ir2,izv), Form("hrho2_S%d%d",ir2,izv),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0332                 hrho2_M[ir2][izv]   = new TH2D( Form("hrho2_M%d%d",ir2,izv), Form("hrho2_M%d%d",ir2,izv),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0333                 hC2[ir2][izv]       = new TH2D( Form("hC2%d%d"    ,ir2,izv), Form("hC2%d%d"    ,ir2,izv),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0334                 hR2[ir2][izv]       = new TH2D( Form("hR2%d%d"    ,ir2,izv), Form("hR2%d%d"    ,ir2,izv),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0335                 //---- README_Crossing: crossing-corrected copies, (dy,dphi) only. Filled in Calculate().
0336                 hrho2C_S[izv]       = new TH2D( Form("hrho2C_S%d",izv), Form("hrho2C_S%d",izv),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0337                 hC2C[izv]           = new TH2D( Form("hC2C%d"    ,izv), Form("hC2C%d"    ,izv),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0338                 hR2C[izv]           = new TH2D( Form("hR2C%d"    ,izv), Form("hR2C%d"    ,izv),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0339                 if (izv==0) hMempty = new TH2D( "hMempty", "hMempty",DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0340                 //if(izv==0)hm2D[ir2]   = new TH2D( Form("hm2D%d"     ,ir2    ), Form("hm2D%d"     ,ir2    ),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0341 //dptM              hrho2_S_dptP[ir2][izv]  = new TH2D( Form("hrho2_S_dptP%d%d",ir2,izv), Form("hrho2_S_dptP%d%d",ir2,izv),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0342 //dptM              hrho2_M_dptP[ir2][izv]  = new TH2D( Form("hrho2_M_dptP%d%d",ir2,izv), Form("hrho2_M_dptP%d%d",ir2,izv),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0343 //dptM              hrho2_S_dptN[ir2][izv]  = new TH2D( Form("hrho2_S_dptN%d%d",ir2,izv), Form("hrho2_S_dptN%d%d",ir2,izv),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0344 //dptM              hrho2_M_dptN[ir2][izv]  = new TH2D( Form("hrho2_M_dptN%d%d",ir2,izv), Form("hrho2_M_dptN%d%d",ir2,izv),DYNB,DYL,DYU,DPHINB,DPHIL,DPHIU);
0345             } else if (ir2==2){                 //----- (Q_inv,pT_pair), README_meanpT_from_CQ.md sec 11 (was (dy,dq) with log dq until 2026-10-10) ------
0346                 hrho2_S[ir2][izv]   = new TH2D( Form("hrho2_S%d%d",ir2,izv), Form("hrho2_S%d%d",ir2,izv),nqbins,qedges.data(),QPT_NPT,0.,QPT_PTMAX);
0347                 hrho2_M[ir2][izv]   = new TH2D( Form("hrho2_M%d%d",ir2,izv), Form("hrho2_M%d%d",ir2,izv),nqbins,qedges.data(),QPT_NPT,0.,QPT_PTMAX);
0348                 hC2[ir2][izv]       = new TH2D( Form("hC2%d%d"    ,ir2,izv), Form("hC2%d%d"    ,ir2,izv),nqbins,qedges.data(),QPT_NPT,0.,QPT_PTMAX);
0349                 hR2[ir2][izv]       = new TH2D( Form("hR2%d%d"    ,ir2,izv), Form("hR2%d%d"    ,ir2,izv),nqbins,qedges.data(),QPT_NPT,0.,QPT_PTMAX);
0350             } else {
0351                 cout<<"problem!"<<endl; exit(0); 
0352             }
0353             hrho2_S[ir2][izv]->Sumw2();
0354             hrho2_M[ir2][izv]->Sumw2();
0355 //dptM          hrho2_S_dptP[ir2][izv]->Sumw2();
0356 //dptM          hrho2_M_dptP[ir2][izv]->Sumw2();
0357 //dptM          hrho2_S_dptN[ir2][izv]->Sumw2();
0358 //dptM          hrho2_M_dptN[ir2][izv]->Sumw2();
0359             //
0360             //if (izv==0){
0361             //  for (int ibin=1;ibin<=hrho2_S[ir2][izv]->GetNbinsX();ibin++){
0362             //      for (int jbin=1;jbin<=hrho2_S[ir2][izv]->GetNbinsY();jbin++){
0363             //          hm2D[ir2]->SetBinContent(ibin,jbin,-1.0);
0364             //          hm2D[ir2]->SetBinError(ibin,jbin, 0.0);
0365             //      }
0366             //  }
0367             //}
0368             //
0369         }
0370         //
0371         hR2yydy[izv]    = new TH1D( Form("hR2yydy%d" ,izv), Form("hR2yydy%d" ,izv), DYNB,DYL,DYU);
0372         hR2yydye[izv]   = new TH1D( Form("hR2yydye%d",izv), Form("hR2yydye%d",izv), DYNB,DYL,DYU);
0373         hR2yydyN[izv]   = new TH1D( Form("hR2yydyN%d",izv), Form("hR2yydyN%d",izv), DYNB,DYL,DYU);
0374         hR2dy[izv]      = new TH1D( Form("hR2dy%d"   ,izv), Form("hR2dy%d"   ,izv), DYNB,DYL,DYU);
0375         hR2dye[izv]     = new TH1D( Form("hR2dye%d"  ,izv), Form("hR2dye%d"  ,izv), DYNB,DYL,DYU);
0376         hR2dyN[izv]     = new TH1D( Form("hR2dyN%d"  ,izv), Form("hR2dyN%d"  ,izv), DYNB,DYL,DYU);
0377         hR2dphi[izv]    = new TH1D( Form("hR2dphi%d" ,izv), Form("hR2dphi%d" ,izv), DPHINB,DPHIL,DPHIU);
0378         hR2dphie[izv]   = new TH1D( Form("hR2dphie%d",izv), Form("hR2dphie%d",izv), DPHINB,DPHIL,DPHIU);
0379         hR2dphiN[izv]   = new TH1D( Form("hR2dphiN%d",izv), Form("hR2dphiN%d",izv), DPHINB,DPHIL,DPHIU);
0380         //
0381 //      hR2dyNS[izv]    = new TH1D( Form("hR2dyNS%d"   ,izv), Form("hR2dyNS%d"   ,izv), DYNB,DYL,DYU);
0382 //      hR2dyNSe[izv]   = new TH1D( Form("hR2dyNSe%d"  ,izv), Form("hR2dyNSe%d"  ,izv), DYNB,DYL,DYU);
0383 //      hR2dyNSN[izv]   = new TH1D( Form("hR2dyNSN%d"  ,izv), Form("hR2dyNSN%d"  ,izv), DYNB,DYL,DYU);
0384 //      hR2dphiNS[izv]  = new TH1D( Form("hR2dphiNS%d" ,izv), Form("hR2dphiNS%d" ,izv), DPHINB,DPHIL,DPHIU);
0385 //      hR2dphiNSe[izv] = new TH1D( Form("hR2dphiNSe%d",izv), Form("hR2dphiNSe%d",izv), DPHINB,DPHIL,DPHIU);
0386 //      hR2dphiNSN[izv] = new TH1D( Form("hR2dphiNSN%d",izv), Form("hR2dphiNSN%d",izv), DPHINB,DPHIL,DPHIU);
0387 //      hR2dqNS[izv]    = new TH1D( Form("hR2dqNS%d"   ,izv), Form("hR2dqNS%d"   ,izv), nbins,xbins);
0388 //      hR2dqNSe[izv]   = new TH1D( Form("hR2dqNSe%d"  ,izv), Form("hR2dqNSe%d"  ,izv), nbins,xbins);
0389 //      hR2dqNSN[izv]   = new TH1D( Form("hR2dqNSN%d"  ,izv), Form("hR2dqNSN%d"  ,izv), nbins,xbins);
0390         //
0391         double  xl      = fMass1 + fMass2;
0392         hMinv_S[izv]    = new TH1D( Form("hMinv_S%d",izv), Form("hMinv_S%d",izv), 2500,xl,xl+5. );  // 2 MeV Bin Width
0393         hMinv_M[izv]    = new TH1D( Form("hMinv_M%d",izv), Form("hMinv_M%d",izv), 2500,xl,xl+5. );  // 2 MeV Bin Width
0394         hMinv[izv]      = new TH1D( Form("hMinv%d"  ,izv), Form("hMinv%d"  ,izv), 2500,xl,xl+5. );  // 2 MeV Bin Width
0395         //
0396         //---- README_CQ step 2: 0-1.2 GeV (was 0-0.3; the pp-sized femtoscopic bump reaches ~0.4 GeV), 1 MeV bins
0397         //---- 2026-09-28: 0-2.0 GeV, same 1 MeV bins (room for the p-pi, p-Lambda, K+K- pair types)
0398         hQsib[izv]      = new TH1D( Form("hQsib%d",izv), Form("hQsib%d",izv), 2000,0.,2.0 );
0399         hQmix[izv]      = new TH1D( Form("hQmix%d",izv), Form("hQmix%d",izv), 2000,0.,2.0 );
0400         hCQ[izv]        = new TH1D( Form("hCQ%d"  ,izv), Form("hCQ%d"  ,izv), 2000,0.,2.0 );
0401         hQsib[izv]      ->Sumw2();
0402         hQmix[izv]      ->Sumw2();
0403         //---- 2026-10-02: long-Q test copies, 0-8 GeV in 10 MeV bins, for the multiplicity / closure tests only
0404         //---- (README_CQcomparison sec 2.3); the physics C(Q) above stays 0-2 GeV (user: keep the physics axes)
0405         hQsibW[izv]     = new TH1D( Form("hQsibW%d",izv), Form("hQsibW%d",izv), 800,0.,8.0 );
0406         hQmixW[izv]     = new TH1D( Form("hQmixW%d",izv), Form("hQmixW%d",izv), 800,0.,8.0 );
0407         hQsibW[izv]     ->Sumw2();
0408         hQmixW[izv]     ->Sumw2();
0409         //---- README_CQ step 3: (Qinv, kT), 2 MeV in Q, STAR's kT bins (arXiv:1004.0925); kT outside
0410         //---- 0.15-0.60 goes to the kT under/overflow, so summing all kT bins gives back hQsib (rebinned x2)
0411         {
0412             const int   nkt         = 4;
0413             double      ktbins[nkt+1]   = {0.15,0.25,0.35,0.45,0.60};
0414             hQsibKT[izv]    = new TH2D( Form("hQsibKT%d",izv), Form("hQsibKT%d",izv), 1000,0.,2.0, nkt,ktbins );
0415             hQmixKT[izv]    = new TH2D( Form("hQmixKT%d",izv), Form("hQmixKT%d",izv), 1000,0.,2.0, nkt,ktbins );
0416             hCQKT[izv]      = new TH2D( Form("hCQKT%d"  ,izv), Form("hCQKT%d"  ,izv), 1000,0.,2.0, nkt,ktbins );
0417             hQsibKT[izv]    ->Sumw2();
0418             hQmixKT[izv]    ->Sumw2();
0419         }
0420 //      hMinvdq_S[izv]  = new TH2D( Form("hMinvdq_S%d",izv), Form("hMinvdq_S%d",izv), nbins,xbins, 150,xl,xl+0.3);
0421 //      hMinvdq_M[izv]  = new TH2D( Form("hMinvdq_M%d",izv), Form("hMinvdq_M%d",izv), nbins,xbins, 150,xl,xl+0.3);
0422 //      hMinvdq[izv]    = new TH2D( Form("hMinvdq%d"  ,izv), Form("hMinvdq%d"  ,izv), nbins,xbins, 150,xl,xl+0.3);
0423         //
0424     }   // end izv
0425     //
0426     //---- README sec 16.8: spike-extent zoom. 0.001 in deta x 0.1deg in dphi, (0,0) at a bin CENTRE,
0427     //---- deliberately far finer than any binning used to set the old box (whose "edges" were just
0428     //---- bin widths, i.e. upper limits). Raw counts, summed over Zvtx, filled after PairInfo.
0429     hzoom_S = new TH2D("hzoom_S","hzoom_S;#Delta#eta;#Delta#phi (deg)",101,-0.0505,0.0505,121,-6.05,6.05);
0430     hzoom_M = new TH2D("hzoom_M","hzoom_M;#Delta#eta;#Delta#phi (deg)",101,-0.0505,0.0505,121,-6.05,6.05);
0431     //---- README_SplitTracks573 sec 11: two-track-resolution study (see CalcRm.h)
0432     for (int sm=0;sm<2;sm++) for (int is=0;is<2;is++) for (int ir=0;ir<4;ir++){
0433         hTTR[sm][is][ir]    = new TH2D(Form("hTTR_%d_%d_%d",sm,is,ir),Form("hTTR_%d_%d_%d;dy;#Delta#phi* (deg)",sm,is,ir),40,-0.2,0.2,160,-8,8);
0434     }
0435     for (int sm=0;sm<2;sm++) for (int sd=0;sd<2;sd++)
0436         hTTRside[sm][sd]    = new TH2D(Form("hTTRside_%d_%d",sm,sd),Form("hTTRside_%d_%d;dy;#Delta#phi*_{min} (deg)",sm,sd),40,-0.2,0.2,160,-8,8);
0437     for (int sm=0;sm<2;sm++) for (int w=0;w<2;w++)  // README_SplitTracks573 sec 28
0438         hGap[sm][w] = new TH2D(Form("hGap_%d_%d",sm,w),Form("hGap_%d_%d;#Delta#phi (deg);s (deg)",sm,w),120,-60.,60.,90,-90.,90.);
0439     for (int sm=0;sm<2;sm++)    // README_SplitTracks573 sec 29
0440         hISep[sm]   = new TH2D(Form("hISep_%d",sm),Form("hISep_%d;#Delta#phi*(R=%.0f cm) (deg);|dy|",sm,100*ISEP_R),40,-10.,10.,15,0.,1.5);
0441     for (int sm=0;sm<2;sm++)
0442         hGapDy[sm]  = new TH2D(Form("hGapDy_%d",sm),Form("hGapDy_%d;#Delta#phi (deg);|dy|",sm),120,-60.,60.,20,0.,2.);
0443     for (int sm=0;sm<2;sm++){   // README_SplitTracks573 sec 32
0444         hGapPhi[sm]     = new TH2D(Form("hGapPhi_%d",sm),Form("hGapPhi_%d;#Delta#phi (deg);#LT#phi#GT (deg)",sm),120,-60.,60.,72,-180.,180.);
0445         hGapYbar[sm]    = new TH2D(Form("hGapYbar_%d",sm),Form("hGapYbar_%d;#Delta#phi (deg);#LTy#GT",sm),120,-60.,60.,22,-1.1,1.1);
0446         const double ptE[9]     = {0.1,0.2,0.3,0.4,0.5,0.65,0.8,1.1,2.0};
0447         const double nchE[12]   = {1.5,3.5,5.5,7.5,9.5,12.5,15.5,19.5,24.5,29.5,39.5,79.5};
0448         hGapPt[sm]  = new TH2D(Form("hGapPt_%d",sm),Form("hGapPt_%d;#Delta#phi (deg);#LTp_{T}#GT (GeV/c)",sm),120,-60.,60.,8,ptE);
0449         hGapRm[sm]  = new TH2D(Form("hGapRm_%d",sm),Form("hGapRm_%d;#Delta#phi (deg);R_{m} (meeting radius, m)",sm),120,-60.,60.,29,0.,1.45);
0450         hGapNch[sm] = new TH2D(Form("hGapNch_%d",sm),Form("hGapNch_%d;#Delta#phi (deg);N_{ch} accepted",sm),120,-60.,60.,11,nchE);
0451     }
0452     //---- fine invariant mass near threshold, drawn next to C(Q): 500 x 1 MeV from m1+m2-5 MeV
0453     {
0454         double xth  = fMass1 + fMass2;
0455         hMinvF_S    = new TH1D("hMinvF_S","hMinvF_S;M_{inv} (GeV);pairs",500,xth-0.005,xth+0.495);
0456         hMinvF_M    = new TH1D("hMinvF_M","hMinvF_M;M_{inv} (GeV);pairs",500,xth-0.005,xth+0.495);
0457     }
0458 }
0459 
0460 //------------------------------------------------------------
0461 void CalcRm::Increment(double zv, double field,
0462                         int n1, double eff_1[], double Pvec_1[][3],
0463                         int n2, double eff_2[], double Pvec_2[][3]){
0464     //
0465     //cout<<"Increment "<<zv<<endl;
0466 //  TimerIncrement->Start(kTRUE);       // start and zero...
0467     //
0468 //NONLL if (!(n1>0&&n2>0)) return;              // must have at least 1 of each particle in this event
0469 //NONLL if (!fDistinguishable && n1<2) return;  // if identical particles in pair (pid1=pid2), require there's at least 2 of these particles in this event
0470     //
0471     //---- protection and Zvtx assignment...
0472     if (n1>MAXMULT){ cout<<"CalcRm::Increment .. mult n1 too large! Increase MAXMULT... "<<n1<<" "<<MAXMULT<<endl; exit(0); }
0473     if (n2>MAXMULT){ cout<<"CalcRm::Increment .. mult n2 too large! Increase MAXMULT... "<<n2<<" "<<MAXMULT<<endl; exit(0); }
0474     if (n1>NTRKMAX){ cout<<"CalcRm::Increment .. mult n1 too large! Increase NTRKMAX... "<<n1<<" "<<NTRKMAX<<endl; exit(0); }
0475     if (n2>NTRKMAX){ cout<<"CalcRm::Increment .. mult n2 too large! Increase NTRKMAX... "<<n2<<" "<<NTRKMAX<<endl; exit(0); }
0476     if (zv<ZVTXL || zv>=ZVTXU) return;
0477     hzvtx       ->Fill(zv);
0478     int izv     = axiszvtx->FindBin(zv) - 1; 
0479     //
0480     fField      = field;
0481     //
0482     //---- fill mixing buffers...
0483     bool fillHists               = false;
0484     int n1k,n2k; n1k=n2k=0;
0485 //NONLL if (n1>0 && n2>0) {             // require all events to have both particles!! 
0486         int evtid                = mix_nevt[izv] % NMIX;
0487         mix_mult1[evtid][izv]    = n1;
0488         mix_mult2[evtid][izv]    = n2;
0489         mix_field[evtid][izv]    = field;
0490         mix_zvtx[evtid][izv]     = zv;
0491         mix_run[evtid][izv]      = fCurrentRun;         // sec 18.20
0492         mix_evt[evtid][izv]      = fCurrentEvt;
0493         mix_nch[evtid][izv]      = fCurrentNch;         // sec 34
0494         if (evtid==NMIX-1){
0495             fillHists            = true;
0496         }
0497         //cout<<"evtid = "<<evtid<<" "<<izv<<" "<<mix_nevt[izv]<<endl;
0498         for (int i=0;i<n1;i++) {
0499             double eff  = eff_1[i];
0500             double y    = Pvec_1[i][0];
0501             double phi  = Pvec_1[i][1]*raddeg;      // degrees!
0502             double pt   = Pvec_1[i][2];
0503             if (phi <    0.) phi +=  360.;
0504             if (phi >= 360.) phi -=  360.;
0505             mix_part1[0][i][evtid][izv] = y;
0506             mix_part1[1][i][evtid][izv] = phi;
0507             mix_part1[2][i][evtid][izv] = pt;
0508             mix_part1[3][i][evtid][izv] = eff;
0509             //cout<<"part1 \t"<<y<<" "<<pt<<" \t "<<YL1<<" "<<YU1<<" "<<PTL1<<" "<<PTU1<<" "<<endl;
0510             if (y>=YL1&&y<YU1&&pt>=PTL1&&pt<PTU1){
0511                 ++n1k;
0512             } else {
0513                 cout<<"PART1 FAILED IN CLASS .. "<<y<<" "<<phi<<" "<<pt<<" "<<endl;         
0514                 cout<<"\t \t"<<std::setprecision(10)<<pt<<" \t "<<PTL1<<" "<<PTU1<<endl;        
0515             }
0516         }
0517         for (int j=0;j<n2;j++) {
0518             double eff  = eff_2[j];
0519             double y    = Pvec_2[j][0];
0520             double phi  = Pvec_2[j][1]*raddeg;      // degrees!
0521             double pt   = Pvec_2[j][2];
0522             if (phi <    0.) phi +=  360.;
0523             if (phi >= 360.) phi -=  360.;
0524             mix_part2[0][j][evtid][izv] = y;
0525             mix_part2[1][j][evtid][izv] = phi;
0526             mix_part2[2][j][evtid][izv] = pt;
0527             mix_part2[3][j][evtid][izv] = eff;
0528             //cout<<"part2 \t"<<y<<" "<<pt<<" \t "<<YL2<<" "<<YU2<<" "<<PTL2<<" "<<PTU2<<" "<<endl;
0529             if (y>=YL2&&y<YU2&&pt>=PTL2&&pt<PTU2){
0530                 ++n2k;
0531             } else {
0532                 cout<<"PART2 FAILED IN CLASS .. "<<y<<" "<<phi<<" "<<pt<<" "<<endl;         
0533                 cout<<"\t \t"<<std::setprecision(10)<<pt<<" \t "<<PTL2<<" "<<PTU2<<endl;        
0534             }
0535         }
0536         mix_nevt[izv]           += 1;
0537         //if (izv==16)cout<<"checking if mix .. "<<nevt<<" \t "<<mix_nevt[izv]<<"  "<<evtid<<"  "<<mix_mult[evtid][izv]<<endl;
0538 //NONLL     }
0539     //
0540     if ((n1k!=n1)||(n2k!=n2)){
0541         cout<<"CalcRm::Increment -- class cuts issue! "<<n1<<" "<<n1k<<" \t "<<n2<<" "<<n2k<<endl;
0542     }
0543     //
0544     if (fillHists){
0545         //
0546         //int nfillnum  = 0;
0547         //int nfillden  = 0;
0548         //
0549         //---- fill SIBLING 2Ds...          
0550         //      Better to fill numerator for all NMIX events only once all NMIX events are in hand... 
0551 //cout<<"fillHists! iev="<<-1<<" zv="<<zv<<" izv="<<izv<<endl;
0552         for (int iev=0;iev<NMIX;iev++){
0553             //++nfillnum;
0554             //
0555             //cout<<izv<<" "<<mix_mult1[iev][izv]<<endl;
0556             // if (mix_mult1[iev][izv]<=5||mix_mult2[iev][izv]<=5){
0557             //  cout<<"FILLHISTS .. "<<mix_mult1[iev][izv]<<" "<<mix_mult2[iev][izv]<<" \t "<<n1<<" "<<n2<<" \t "
0558             //      <<iev<<" "<<izv<<endl;
0559             // }
0560             //
0561 //          double zvtx = mix_zvtx[iev][izv];
0562 //          int izv     = axiszvtx->FindBin(zvtx) - 1; 
0563 //cout<<"fillHists! iev="<<iev<<" zvtx="<<zvtx<<" izv="<<izv<<endl;
0564             hmult[izv]->Fill(mix_mult1[iev][izv],mix_mult2[iev][izv]);
0565             //
0566             //double multfactor = 1.; 
0567             //int n1 = mix_mult1[iev][izv];
0568             //int n2 = mix_mult2[iev][izv];
0569             //if(!fDistinguishable){ multfactor=((double)n1)*(n1-1.)/n1/n1; }
0570             //
0571             double multc1=0.,multc2=0.;
0572             for (int i=0;i<mix_mult1[iev][izv];i++){    // particle1
0573                 double y    = mix_part1[0][i][iev][izv];
0574                 double phi  = mix_part1[1][i][iev][izv];
0575                 double pt   = mix_part1[2][i][iev][izv];
0576                 double eff  = mix_part1[3][i][iev][izv];
0577                 hy1_[izv]   ->Fill(y,1.    );
0578                 hyc1_[izv]  ->Fill(y,1./eff);
0579                 hrho1_1[izv]->Fill(y,phi,pt,1./eff);
0580                 multc1      +=1./eff;
0581             }
0582             for (int j=0;j<mix_mult2[iev][izv];j++){    // particle2
0583                 double y    = mix_part2[0][j][iev][izv];
0584                 double phi  = mix_part2[1][j][iev][izv];
0585                 double pt   = mix_part2[2][j][iev][izv];
0586                 double eff  = mix_part2[3][j][iev][izv];
0587                 hy2_[izv]   ->Fill(y,1.    );
0588                 hyc2_[izv]  ->Fill(y,1./eff);
0589                 hrho1_2[izv]->Fill(y,phi,pt,1./eff);
0590                 multc2      +=1./eff;
0591             }
0592             //hmultc[izv]->Fill(multc1,multc2);
0593             //
0594             for (int i=0;i<mix_mult1[iev][izv];i++){        // event A  iev
0595                 for (int j=0;j<mix_mult2[iev][izv];j++){    // event A  iev
0596                     //
0597                     if (!fDistinguishable && (i==j)) continue;
0598                     //
0599                     //----- NUM simpler filling (by dpt)
0600 //                  double  ty1,ty2,tphi1,tphi2,tpt1,tpt2,dty,dtpt,dtphi;
0601 //                  ty1     = mix_part1[0][i][iev][izv];    // event A
0602 //                  tphi1   = mix_part1[1][i][iev][izv];    // event A
0603 //                  tpt1    = mix_part1[2][i][iev][izv];    // event A
0604 //                  ty2     = mix_part2[0][j][iev][izv];    // event A
0605 //                  tphi2   = mix_part2[1][j][iev][izv];    // event A
0606 //                  tpt2    = mix_part2[2][j][iev][izv];    // event A
0607 //                  dtpt    =  tpt1 -  tpt2;
0608 //                  dty     =   ty1 -   ty2;
0609 //                  dtphi   = tphi1 - tphi2;
0610 //                  if (dtphi   <  DPHIL) dtphi +=  360.;
0611 //                  if (dtphi   >= DPHIU) dtphi -=  360.;
0612                     //
0613                     double eff1     = mix_part1[3][i][iev][izv];    // event A
0614                     double eff2     = mix_part2[3][j][iev][izv];    // event A
0615                     double weight   = 1.;
0616                     if (eff1*eff2>0.){
0617                         weight      = 1./eff1/eff2;
0618                     } else {
0619                         cout<<"numerator zero efficiency!!!"<<endl;
0620                     }
0621                     //
0622                     //cout<<dtpt<<" "<<ty1<<" "<<ty2<<" "<<dty<<" "<<dtphi<<endl;
0623 //                  if (dtpt>=0.){
0624 //                      hrho2_S_dptP[0][izv]    ->Fill(ty1,ty2  ,weight);
0625 //                      hrho2_S_dptP[1][izv]    ->Fill(dty,dtphi,weight);
0626 //                      //hrho2_M_dptP[2][izv]  ->Fill(dty,dtq  ,weight);   // dQ not available in simple fill...
0627 //                  } else {
0628 //                      hrho2_S_dptN[0][izv]    ->Fill(ty1,ty2  ,weight);
0629 //                      hrho2_S_dptN[1][izv]    ->Fill(dty,dtphi,weight);
0630 //                      //hrho2_M_dptN[2][izv]  ->Fill(dty,dtq  ,weight);   // dQ not available in simple fill...
0631 //                  }
0632                     //
0633                     //----- via pairinfo..
0634                     double y1,y2,dy,dphi,dpt,dq,Qinv,Minv,Minvr,kT; bool NearSide;
0635                     fPairSM = 0;    // sec 29: sibling (for hISep)
0636                     bool keep = PairInfo(i,iev,j,iev,izv,
0637                                          y1,y2,dy,dphi,dpt,dq,Qinv,Minv,NearSide,kT);
0638                     if (!keep) continue;
0639                     //
0640                     hrho2_S[0][izv] ->Fill(y1,y2  ,weight);
0641                     hrho2_S[1][izv] ->Fill(dy,dphi,weight);
0642                     hzoom_S         ->Fill(dy,dphi,weight); // sec 16.8
0643                     FillTTR(0,i,iev,j,iev,izv,weight);          // README_SplitTracks573 sec 11
0644                     FillGap(0,i,iev,j,iev,izv,weight);          // README_SplitTracks573 sec 28
0645                     hrho2_S[2][izv] ->Fill(dq,2.*kT,weight);    // README_meanpT_from_CQ: (Q_inv, pT_pair = |pT1+pT2| = 2 kT)
0646                     hMinv_S[izv]    ->Fill(Minv   ,weight);
0647                     hMinvF_S        ->Fill(Minv   ,weight);
0648                     hQsib[izv]      ->Fill(dq     ,weight); // dq is the STAR-style qInv (see PairInfo); the local "Qinv" is q^2's own byproduct and is negative-definite for identical species
0649                     hQsibKT[izv]    ->Fill(dq,kT  ,weight); // README_CQ step 3
0650                     hQsibW[izv]     ->Fill(dq     ,weight); // long-Q test copy
0651                     //hMinvdq_S[izv]->Fill(dq,Minv,weight);
0652                     //cout<<izv<<" "<<dq<<" "<<Minv<<" "<<weight<<" "<<Minv-dq<<endl;
0653                     //
0654                     //++npair_all_S;
0655                     //if (fabs(dy)  <0.1 ) ++npair_dylow1_S;
0656                     //if (fabs(dy)  <0.3 ) ++npair_dylow2_S;
0657                     //if (fabs(dy)  <0.5 ) ++npair_dylow3_S;
0658                     //if (fabs(dq)  <0.15) ++npair_qlow_S;
0659                     //if (Minv      <1.5 ) ++npair_mlow_S;
0660                     //
0661                 }
0662             }
0663         }
0664         //
0665         //---- fill MIXED 2Ds...
0666 //      for (int icomb=0;icomb<NCombinations2;icomb++){
0667 //          int iev = Combinations2[0][icomb];      // index of event A from range [0,...,NMIX-1]
0668 //          int jev = Combinations2[1][icomb];      // index of event B from range [0,...,NMIX-1]
0669         //---- brute force loop over all unique 2-combinations...
0670         for (int iev=0;iev<NMIX;iev++){
0671         for (int jev=iev+1;jev<NMIX;jev++){         // as defined, jev cannot equal iev... 
0672             //++nfillden;
0673             //
0674             if (mix_field[iev][izv]*mix_field[jev][izv] < 0.){
0675                 cout<<"Field Flip! .. "<<mix_field[iev][izv]<<" "<<mix_field[jev][izv]<<" "
0676                     <<iev<<" "<<jev
0677                     <<endl;
0678                 cout<<"Exiting! You must analyze different fields separately!"<<endl;
0679                 exit(0);
0680             }
0681             //++NCombinations2_Seen[izv];
0682             //for (int j=0;j<2;j++){ cout<<Combinations2[j][icomb]<<" "; } cout<<endl;      
0683             //---- sec 18.23: skip whole mixed EVENT pairs from neighboring trigger frames -- copies of one
0684             //---- silicon seed can land in adjacent TFs (sec 18.22), which the same-TF XTFclean cleaner
0685             //---- cannot see (cluster keys are not comparable across events). Bookkept per zvtx bin so
0686             //---- each bin's rho2(M) is normalized by the event pairs it actually used (see Calculate()).
0687             ++nComb_possible[izv];
0688             if (fExcludeAdjTF>0 && mix_run[iev][izv]==mix_run[jev][izv]){
0689                 int devt = abs(mix_evt[iev][izv]-mix_evt[jev][izv]);
0690                 if (devt==1 || (fExcludeAdjTF==2 && devt==0)) continue;
0691             }
0692             ++nComb_used[izv];
0693             //
0694             //double multfactor=1.; 
0695             //int n1 = mix_mult1[iev][izv];
0696             //int n2 = mix_mult2[jev][izv];
0697             //multfactor=((double)n1)*n2/n1/n2; 
0698             //double weight = 1./multfactor;
0699             //
0700             for (int i=0;i<mix_mult1[iev][izv];i++){        // event A  iev
0701                 for (int j=0;j<mix_mult2[jev][izv];j++){    // event B  jev
0702                     //
0703                     //-------------------------------------------------
0704                     // DENOM simpler filling (by dpt)
0705 //                  double  ty1,ty2,tphi1,tphi2,tpt1,tpt2,dty,dtpt,dtphi;
0706 //                  ty1     = mix_part1[0][i][iev][izv];    // event A
0707 //                  tphi1   = mix_part1[1][i][iev][izv];    // event A
0708 //                  tpt1    = mix_part1[2][i][iev][izv];    // event A
0709 //                  ty2     = mix_part2[0][j][jev][izv];    // event B
0710 //                  tphi2   = mix_part2[1][j][jev][izv];    // event B
0711 //                  tpt2    = mix_part2[2][j][jev][izv];    // event B
0712 //                  dtpt    =  tpt1 -  tpt2;
0713 //                  dty     =   ty1 -   ty2;
0714 //                  dtphi   = tphi1 - tphi2;
0715 //                  if (dtphi   <  DPHIL) dtphi +=  360.;
0716 //                  if (dtphi   >= DPHIU) dtphi -=  360.;
0717                     //
0718                     double eff1     = mix_part1[3][i][iev][izv];    // event A
0719                     double eff2     = mix_part2[3][j][jev][izv];    // event B
0720                     double weight   = 1.;
0721                     if (eff1*eff2>0.){
0722                         weight      = 1./eff1/eff2;
0723                     } else {
0724                         cout<<"denominator zero efficiency!!!"<<endl;
0725                     }
0726 //                  if (dtpt>=0.){
0727 //                      hrho2_M_dptP[0][izv]    ->Fill(ty1,ty2  ,weight);
0728 //                      hrho2_M_dptP[1][izv]    ->Fill(dty,dtphi,weight);
0729 //                      //hrho2_M_dptP[2][izv]  ->Fill(dty,dtq  ,weight);   // dQ not avail in simple fill!
0730 //                  } else {
0731 //                      hrho2_M_dptN[0][izv]    ->Fill(ty1,ty2  ,weight);
0732 //                      hrho2_M_dptN[1][izv]    ->Fill(dty,dtphi,weight);
0733 //                      //hrho2_M_dptN[2][izv]  ->Fill(dty,dtq  ,weight);   // dQ not avail in simple fill!
0734 //                  }
0735                     //-------------------------------------------------
0736                     //
0737                     double y1,y2,dy,dphi,dpt,dq,Qinv,Minv,kT; bool NearSide;
0738                     fPairSM = 1;    // sec 29: mixed (for hISep)
0739                     bool keep = PairInfo(i,iev,j,jev,izv,
0740                                          y1,y2,dy,dphi,dpt,dq,Qinv,Minv,NearSide,kT);
0741                     if (!keep) continue;
0742                     //
0743                     hrho2_M[0][izv]     ->Fill(y1,y2  ,weight);
0744                     hrho2_M[1][izv]     ->Fill(dy,dphi,weight);
0745                     hzoom_M             ->Fill(dy,dphi,weight); // sec 16.8
0746                     FillTTR(1,i,iev,j,jev,izv,weight);              // README_SplitTracks573 sec 11
0747                     FillGap(1,i,iev,j,jev,izv,weight);              // README_SplitTracks573 sec 28
0748                     //---- sec 18.20: same-TF / neighboring-TF mixed-pair counters (cheap per-production
0749                     //---- monitor of the trigger-frame structure; see README sec 18.20-18.23)
0750                     {
0751                         ++nMixedPairs_total;
0752                         bool sameTF = (mix_run[iev][izv]==mix_run[jev][izv] && mix_evt[iev][izv]==mix_evt[jev][izv]);
0753                         bool neighborTF = (!sameTF && mix_run[iev][izv]==mix_run[jev][izv]
0754                                          && abs(mix_evt[iev][izv]-mix_evt[jev][izv])<=1);
0755                         if (sameTF) ++nMixedPairs_sameTF;
0756                         if (neighborTF) ++nMixedPairs_neighborTF;
0757                     }
0758                     hrho2_M[2][izv]     ->Fill(dq,2.*kT,weight);    // README_meanpT_from_CQ: (Q_inv, pT_pair), same as sibling
0759                     hMinv_M[izv]        ->Fill(Minv   ,weight);
0760                     hMinvF_M            ->Fill(Minv   ,weight);
0761                     hQmix[izv]          ->Fill(dq     ,weight); // dq is the STAR-style qInv (see PairInfo); the local "Qinv" is q^2's own byproduct and is negative-definite for identical species
0762                     hQmixKT[izv]        ->Fill(dq,kT  ,weight); // README_CQ step 3, same kT as sibling
0763                     hQmixW[izv]         ->Fill(dq     ,weight); // long-Q test copy
0764                     //
0765                     //hMinvdq_M[izv]    ->Fill(dq,Minv,weight);
0766                     //cout<<izv<<" "<<dq<<" "<<Minv<<" "<<weight<<" "<<Minv-dq<<endl;
0767                     //
0768                     //++npair_all_M;
0769                     //if (fabs(dy)  <0.1 ) ++npair_dylow1_M;
0770                     //if (fabs(dy)  <0.3 ) ++npair_dylow2_M;
0771                     //if (fabs(dy)  <0.5 ) ++npair_dylow3_M;
0772                     //if (fabs(dq)  <0.15) ++npair_qlow_M;
0773                     //if (Minv      <1.5 ) ++npair_mlow_M;
0774                     //
0775                 }
0776             }
0777             //
0778         }   // end jev
0779         }   // end iev
0780 //      }   // end loop over 2-combinations...
0781         //
0782         //cout<<"NFILL: "<<nfillnum<<" "<<nfillden<<" "<<(double)nfillden/nfillnum<<endl;
0783         //
0784     }   // end fillHists
0785     //
0786 //  TimerIncrement  -> Stop();
0787 //  fTimeIncrement  += TimerIncrement->CpuTime();
0788     //
0789 }
0790 
0791 //------------------------------------------------------------
0792 //------------------------------------------------------------
0793 // README_SplitTracks573 sec 11: dphi*(R) = phi1 - phi2 - s*q*[asin(a R/pt1) - asin(a R/pt2)], a = 0.3*B/2
0794 // (B in T, R in m, pt in GeV/c): the two tracks' azimuthal separation at transverse radius R. Both sign
0795 // hypotheses s = +-1 are filled (the q*B sign convention is chosen from the data). Unordered (index order),
0796 // so the maps are symmetric in dphi*. Radii a track cannot reach (a R/pt > 1) are skipped.
0797 void CalcRm::FillTTR(int sm, int i, int iev, int j, int jev, int izv, double weight){
0798     if (fChg1==0. || fChg2==0.) return;
0799     double y1   = mix_part1[0][i][iev][izv], phi1 = mix_part1[1][i][iev][izv], pt1 = mix_part1[2][i][iev][izv];
0800     double y2   = mix_part2[0][j][jev][izv], phi2 = mix_part2[1][j][jev][izv], pt2 = mix_part2[2][j][jev][izv];
0801     double dy   = y1-y2;
0802     if (fabs(dy)>=0.2) return;
0803     double dphi0    = phi1-phi2;
0804     while (dphi0>= 180.) dphi0 -= 360.;
0805     while (dphi0< -180.) dphi0 += 360.;
0806     if (fabs(dphi0)>=40.) return;
0807     double a    = 0.3*fabs(fField)/2.0;
0808     static const double RFIX[3] = {0.30,0.50,0.70};
0809     for (int is=0;is<2;is++){
0810         double s    = (is==0) ? 1.0 : -1.0;
0811         auto dps    = [&](double R, bool& ok){
0812             double x1 = a*R/pt1, x2 = a*R/pt2;
0813             ok  = (x1<1.0 && x2<1.0);
0814             if (!ok) return 0.0;
0815             return dphi0 - s*(fChg1*asin(x1) - fChg2*asin(x2))*180.0/M_PI;
0816         };
0817         for (int ir=0;ir<3;ir++){ bool ok; double d = dps(RFIX[ir],ok); if (ok) hTTR[sm][is][ir]->Fill(dy,d,weight); }
0818         double best=1e9; bool any=false;
0819         for (double R=0.30; R<=0.781; R+=0.02){ bool ok; double d = dps(R,ok); if (!ok) break; any=true; if (fabs(d)<fabs(best)) best=d; }
0820         if (any) hTTR[sm][is][3]->Fill(dy,best,weight);
0821         if (any && is==0){  // sec 20: the side the pt-ordering (PairInfo) puts this pair on
0822             double dpt  = pt1-pt2, od = dphi0;
0823             if (fLikeSign){ if ((fChg1>0 && dpt<0.0) || (fChg1<0 && dpt>0.0)) od = -od; }
0824             else if (fChg1>0 && fChg2<0) od = -od;
0825             hTTRside[sm][od<0 ? 1 : 0]->Fill(dy,best,weight);
0826         }
0827     }
0828 }
0829 
0830 //------------------------------------------------------------
0831 // README_SplitTracks573 sec 28: sector-gap diagnostic. The TPC sector gaps are fixed in detector phi, so a track
0832 // meets them at vertex phi = phi_gap + q*asin(aR/pt): two tracks see the gaps "aligned" when dphi - s is a multiple
0833 // of the sector pitch (30 deg), s = q1*asin(aR/pt1) - q2*asin(aR/pt2). Within one s bin sibling and mixed pairs
0834 // see the same alignment, so the gap acceptance cancels in S/M bin by bin in s.
0835 void CalcRm::FillGap(int sm, int i, int iev, int j, int jev, int izv, double weight){
0836     if (fChg1==0. || fChg2==0.) return;
0837     double y1   = mix_part1[0][i][iev][izv], phi1 = mix_part1[1][i][iev][izv], pt1 = mix_part1[2][i][iev][izv];
0838     double y2   = mix_part2[0][j][jev][izv], phi2 = mix_part2[1][j][jev][izv], pt2 = mix_part2[2][j][jev][izv];
0839     double ady  = fabs(y1-y2);
0840     double dphi = phi1-phi2;
0841     while (dphi>= 180.) dphi -= 360.;
0842     while (dphi< -180.) dphi += 360.;
0843     if (fabs(dphi)>=60.) return;
0844     hGapDy[sm]->Fill(dphi,ady,weight);
0845     if (ady>=1.0) return;
0846     double phib = phi2 + 0.5*dphi;                      // circular mean of the two vertex phis
0847     while (phib>= 180.) phib -= 360.;
0848     while (phib< -180.) phib += 360.;
0849     hGapPhi[sm]->Fill(dphi,phib,weight);
0850     hGapYbar[sm]->Fill(dphi,0.5*(y1+y2),weight);
0851     hGapPt[sm]->Fill(dphi,0.5*(pt1+pt2),weight);                    // sec 34
0852     hGapNch[sm]->Fill(dphi,mix_nch[iev][izv],weight);
0853     {   //---- sec 34.1: the meeting radius R_m, where the two tracks meet in phi (swap order), phi_i(R) = phi_i + q_i asin(aR/pt_i)
0854         //---- (the sign the data pick, sec 28), small-angle: dphi + aR (q1/pt1 - q2/pt2) = 0. Never meet (R < 0) -> 1.4 m.
0855         const double aa = 0.3*fabs(fField)/2.0;
0856         double k    = aa*(fChg1/pt1 - fChg2/pt2);
0857         double rx   = (k!=0.) ? -(dphi*M_PI/180.0)/k : -1.;
0858         if (rx<0. || rx>1.4) rx = 1.4;
0859         hGapRm[sm]->Fill(dphi,rx,weight);
0860     }
0861     const double a  = 0.3*fabs(fField)/2.0, R = 0.55;
0862     double x1 = a*R/pt1, x2 = a*R/pt2;
0863     if (x1>=1.0 || x2>=1.0) return;
0864     double s    = (fChg1*asin(x1) - fChg2*asin(x2))*180.0/M_PI;
0865     hGap[sm][ady<0.4 ? 1 : 0]->Fill(dphi,s,weight);
0866 }
0867 
0868 bool CalcRm::PairInfo(int i, int iev, int j, int jev, int izv,
0869                       double& y1,double& y2,double& dy,double& dphi,
0870                       double& dpt,double& dq,double& Qinv,double& Minv,bool& NearSide,double& kT){
0871     //
0872     // default is to accept all pairs in the acceptance
0873     // in this code, pairs can be rejected due to a dQ cut, or an Minv cut (or both)
0874     bool keep   = true;
0875     //
0876     double  phi1,phi2,pt1,pt2;
0877     y1      = mix_part1[0][i][iev][izv];
0878     phi1    = mix_part1[1][i][iev][izv];
0879     pt1     = mix_part1[2][i][iev][izv];
0880     y2      = mix_part2[0][j][jev][izv];
0881     phi2    = mix_part2[1][j][jev][izv];
0882     pt2     = mix_part2[2][j][jev][izv];
0883     //
0884     dy      = y1 - y2;
0885     dpt     = pt1 - pt2;
0886     dphi    = phi1 - phi2;              // deg!!
0887     //---- README_SplitTracks573 sec 11: two-track-resolution cut (opt-in, "tsepYYPP"), before any flip,
0888     //---- identical for sibling and mixed pairs. dphi* at R = 0.5 m, sign "+" (chosen from the data, sec 11).
0889     if (fChg1!=0. && fChg2!=0.) ++nPairCut[fPairSM][0]; // README_SplitTracks573 Final state: pairs reaching the pair cuts
0890     if (fTSepDy>0. && fLikeSign && fChg1!=0. && fChg2!=0. && fabs(dy)<fTSepDy){
0891         const double a0 = 0.3*fabs(fField)/2.0;
0892         auto dstar  = [&](double R, bool& ok){
0893             double x1 = a0*R/pt1, x2 = a0*R/pt2;
0894             ok = (x1<1.0 && x2<1.0);
0895             if (!ok) return 999.;
0896             double d    = dphi - (fChg1*asin(x1) - fChg2*asin(x2))*180.0/M_PI;
0897             while (d>= 180.) d -= 360.;
0898             while (d< -180.) d += 360.;
0899             return fabs(d);
0900         };
0901         double dmin = 999.;
0902         if (fTSepMin){
0903             for (double R=0.30; R<=0.781; R+=0.02){ bool ok; double d = dstar(R,ok); if (!ok) break; dmin = std::min(dmin,d); }
0904         } else { bool ok; dmin = dstar(0.5,ok); }
0905         if (dmin<fTSepDphi){ ++nPairCut[fPairSM][1]; return false; }
0906     }
0907     //---- README_SplitTracks573 sec 29: near-vertex two-track cut (opt-in, "isepPPP"). Sibling tracks at nearly the same
0908     //---- phi near the vertex are lost up to abs(dy) ~ 0.8 (sec 28.1/29: the net loss is deepest at R ~ 2-3 cm), so reject
0909     //---- abs(dphi*(R = ISEP_R)) < fISepDphi at abs(dy) < ISEP_DYMAX, LS and ULS, identical for sibling and mixed.
0910     //---- hISep records every charged pair BEFORE the cut (the cut is drawn on it in the PDF).
0911     if (fChg1!=0. && fChg2!=0.){
0912         const double a0 = 0.3*fabs(fField)/2.0;
0913         double x1 = a0*ISEP_R/pt1, x2 = a0*ISEP_R/pt2;
0914         if (x1<1.0 && x2<1.0){
0915             double d    = dphi - (fChg1*asin(x1) - fChg2*asin(x2))*180.0/M_PI;
0916             while (d>= 180.) d -= 360.;
0917             while (d< -180.) d += 360.;
0918             hISep[fPairSM]->Fill(d,fabs(dy));
0919             if (fISepDphi>0. && fabs(dy)<ISEP_DYMAX && fabs(d)<fISepDphi){ ++nPairCut[fPairSM][2]; return false; }
0920         }
0921     }
0922     if (fDoCrossing){
0923         //---- 2026-09-25 (README_Crossing sec 8, user): dphi sign convention chosen so the crossing
0924         //---- damage lands just BELOW dphi=0 (dirty side dphi<0 at field>0, as in STAR); 0..180 is clean.
0925         //---- These are the complements of the first conditions used (which put it at dphi>0).
0926         if (fLikeSign){
0927             if (fChg1>0 && dpt<0.0){        // LS Pos
0928                 if (fFlipDy) dy = -dy;
0929                 dphi    = -dphi;
0930             }
0931             if (fChg1<0 && dpt>0.0){        // LS Neg
0932                 if (fFlipDy) dy = -dy;
0933                 dphi    = -dphi;
0934             }   
0935         } else if (!fLikeSign){ 
0936             if (fChg1>0 && fChg2<0){        // ULS +- (a neutral leg is never flipped, in either order)
0937                 if (fFlipDy) dy = -dy;
0938                 dphi = -dphi;
0939             }
0940         } 
0941     }
0942 //STAR  if (fField >    0.0) dphi  = -dphi;
0943     if (dphi   <  DPHIL) dphi +=  360.;
0944     if (dphi   >= DPHIU) dphi -=  360.;
0945     //
0946     //NearSide  = false;
0947     //if (fabs(dy)<0.25 && fabs(dphi)<60.) NearSide = true;
0948     //
0949     //------------------
0950     // https://www.star.bnl.gov/cgi-bin/protected/cvsweb.cgi/StRoot/StHbtMaker/Infrastructure/StHbtPair.cc?rev=1.29
0951     //
0952     dq = 0;
0953     Minv = 0;
0954     kT = 0;
0955     {   //---- dq, Minv, kT: always computed (C(Q) and the ir2=2 (Q,pT_pair) block need them; fDoDQ removed 2026-10-10)
0956         double px1      = pt1*cos(phi1/raddeg);     // class phi angles are in degrees
0957         double py1      = pt1*sin(phi1/raddeg);     // class phi angles are in degrees
0958         //---- y1,y2 are RAPIDITIES (README_PID.md, 2026-09-28: corral::Loop converts eta -> y with the PID mass;
0959         //---- before that it passed eta here, which overstated pz by mt/pt)
0960         //---- an h+/h- leg (fUseEta) carries eta: pz = pT sinh(eta), E = sqrt(p^2 + m^2) with the pion mass (2026-10-11)
0961         double mt1      = sqrt(pt1*pt1 + fMass1*fMass1);
0962         double pz1      = fUseEta1 ? pt1*sinh(y1) : mt1*sinh(y1);
0963         double pE1      = fUseEta1 ? sqrt(mt1*mt1 + pz1*pz1) : mt1*cosh(y1);
0964         double px2      = pt2*cos(phi2/raddeg);     // class phi angles are in degrees
0965         double py2      = pt2*sin(phi2/raddeg);     // class phi angles are in degrees
0966         double mt2      = sqrt(pt2*pt2 + fMass2*fMass2);
0967         double pz2      = fUseEta2 ? pt2*sinh(y2) : mt2*sinh(y2);
0968         double pE2      = fUseEta2 ? sqrt(mt2*mt2 + pz2*pz2) : mt2*cosh(y2);
0969         double Px       = px1+px2;
0970         double Py       = py1+py2;
0971         double Pz       = pz1+pz2;
0972         double PE       = pE1+pE2;
0973         double dPx      = px1-px2;
0974         double dPy      = py1-py2;
0975         double dPz      = pz1-pz2;
0976         double dPE      = pE1-pE2;
0977         double Ptrans   = Px*Px + Py*Py;
0978                kT       = 0.5*std::sqrt(Ptrans);    // README_CQ: STAR kT = |pT1+pT2|/2, from the unflipped momenta
0979         double Mtrans   = PE*PE - Pz*Pz;
0980         double Pinv     = std::sqrt(Mtrans - Ptrans);
0981         //     Mtrans   = std::sqrt(Mtrans);
0982         //     Ptrans   = std::sqrt(Ptrans);
0983         double Qinv2    = dPE*dPE - dPx*dPx - dPy*dPy - dPz*dPz;
0984         double Q        = (fMass1*fMass1 - fMass2*fMass2)/Pinv;
0985                dq       = std::sqrt(Q*Q - Qinv2);
0986                Qinv     = sqrt(Qinv2);
0987         double Minv2    = PE*PE - Px*Px - Py*Py - Pz*Pz;
0988         if (Minv2<0){ cout<<"neg minv!"<<endl; exit(0); }
0989         Minv    = sqrt(Minv2);
0990         //
0991         // 
0992     }
0993     //
0994     if (fDoMinvCut){
0995         if ( Minv >= fMinvCut_mlower 
0996           && Minv <  fMinvCut_mupper ){
0997             keep    = false;        // This Pair has Minv consistent with Ks, Phi, L, or Lbar so reject it (if requested).. 
0998         }
0999         if (fDoMinvCutb){           // K+K- can come from TWO different decay parents!  Ks and D0, this is the 2nd one... 
1000             if ( Minv >= fMinvCutb_mlower 
1001               && Minv <  fMinvCutb_mupper ){
1002                 keep    = false;    // This Pair has Minv consistent with D0 so reject it (if requested).. 
1003             }
1004         }
1005     }
1006     if (fDoMinvLLCut){
1007         if ( Minv < fMass1 + fMass2 + 0.004 ){      // lowest 2 bins (lowest 4 MeV of Minv distribution)
1008             keep    = false;    // This Pair has Minv near lower limit (this pair is a split track?) so reject it (if requested).. 
1009         }
1010     }
1011     if (fDoQcut){
1012         if ( dq < fQcut ){
1013             keep    = false;    // This Pair has dQ below the cut value so reject it (if requested)..
1014         }
1015     }
1016     return keep;
1017     //
1018 }
1019 
1020 //------------------------------------------------------------
1021 //------------------------------------------------------------
1022 void CalcRm::Calculate(){
1023     //
1024     //---- README_Crossing sec 8: the crossing correction symmetrizes in dphi ONLY, which is consistent
1025     //---- only with a dphi-only pt-ordering in Increment. A dy flip would need a different correction.
1026     if (fDoCrossing && fFlipDy){
1027         cout<<"CalcRm::Calculate -- fFlipDy=true is not supported by the crossing correction. Exiting."<<endl;
1028         exit(0);
1029     }
1030     //
1031 //  TimerCalculate->Start(kTRUE);   // start and zero...
1032     //
1033 //  cout<<"npair_all_S      = "<<npair_all_S    <<" \t "<<(double)npair_all_S   /npair_all_S    <<endl;
1034 //  cout<<"npair_dylow1_S   = "<<npair_dylow1_S <<" \t "<<(double)npair_dylow1_S/npair_all_S    <<endl;
1035 //  cout<<"npair_dylow2_S   = "<<npair_dylow2_S <<" \t "<<(double)npair_dylow2_S/npair_all_S    <<endl;
1036 //  cout<<"npair_dylow3_S   = "<<npair_dylow3_S <<" \t "<<(double)npair_dylow3_S/npair_all_S    <<endl;
1037 //  cout<<"npair_qlow_S     = "<<npair_qlow_S   <<" \t "<<(double)npair_qlow_S  /npair_all_S    <<endl;
1038 //  cout<<"npair_mlow_S     = "<<npair_mlow_S   <<" \t "<<(double)npair_mlow_S  /npair_all_S    <<endl;
1039 //  cout<<"npair_all_M      = "<<npair_all_M    <<" \t "<<(double)npair_all_M   /npair_all_M    <<endl;
1040 //  cout<<"npair_dylow1_M   = "<<npair_dylow1_M <<" \t "<<(double)npair_dylow1_M/npair_all_M    <<endl;
1041 //  cout<<"npair_dylow2_M   = "<<npair_dylow2_M <<" \t "<<(double)npair_dylow2_M/npair_all_M    <<endl;
1042 //  cout<<"npair_dylow3_M   = "<<npair_dylow3_M <<" \t "<<(double)npair_dylow3_M/npair_all_M    <<endl;
1043 //  cout<<"npair_qlow_M     = "<<npair_qlow_M   <<" \t "<<(double)npair_qlow_M  /npair_all_M    <<endl;
1044 //  cout<<"npair_mlow_M     = "<<npair_mlow_M   <<" \t "<<(double)npair_mlow_M  /npair_all_M    <<endl;
1045     //
1046     double denomfactor  = ((double)NCombinations2)/NMIX;
1047     //cout<<"CalcRm::Calculate -- Nentries in denominator relative to numerator = "<<denomfactor<<endl;
1048     //
1049     //cout<<"CalcRm::Calculate -- Normalizing... "<<endl;
1050     //---- fine Minv (all Zvtx summed): bring the MIXED histogram to the same per-sibling-event footing
1051     //---- as hMinv_M below (divide by mixed event pairs used per sibling event, summed over Zvtx), so
1052     //---- the shape-matching factor shown on the C(Q) page is only the residual sib/mix level (~1),
1053     //---- not the NCombinations2/NMIX combinatorics. The sibling fine histogram stays raw counts.
1054     {
1055         double nevtTot  = 0., ncombTot = 0.;
1056         for (int izv=0;izv<ZVTXNB;izv++){
1057             double ne   = hmult[izv]->GetEntries();
1058             nevtTot     += ne;
1059             ncombTot    += (fExcludeAdjTF>0) ? (double)nComb_used[izv] : ne*denomfactor;
1060         }
1061         if (ncombTot>0.) hMinvF_M->Scale(nevtTot/ncombTot);
1062     }
1063     //---- empty-bin protection (README_Crossing sec 8, 2026-09-25): a slice that is skipped below is
1064     //---- left out of the Zvtx average; a bin is valid in a slice iff its rho2(M) > 0.
1065     bool  sliceOK[NZVTXMAX];    for (int k=0;k<NZVTXMAX;k++) sliceOK[k] = false;
1066     for (int k=0;k<NZVTXMAX;k++) fDenomZ[k] = 0.;
1067     TH2D* hMaskC[NZVTXMAX];     for (int k=0;k<NZVTXMAX;k++) hMaskC[k]  = 0;    // validity of the crossing-corrected maps
1068     for (int izv=0;izv<ZVTXNB;izv++){
1069         //
1070         double nevt     = hmult[izv]->GetEntries();
1071         if (nevt<2.){ continue; }
1072         TH1D *hmult1    = (TH1D*)hmult[izv]->ProjectionX("hmult1");
1073         TH1D *hmult2    = (TH1D*)hmult[izv]->ProjectionY("hmult2");
1074               hmult1    ->Scale(1./nevt);
1075               hmult2    ->Scale(1./nevt);
1076         double f1_1     = hmult1->GetMean();        // <n1>
1077         double f1_2     = hmult2->GetMean();        // <n2>
1078         delete hmult1; hmult1=0;
1079         delete hmult2; hmult2=0;
1080         //---- sec 18.23: per-zvtx-bin mixed normalization. nevt = (full buffers)*NMIX exactly (hmult is
1081         //---- filled once per buffered event at fillHists), so with no exclusion nComb_used/nevt ==
1082         //---- NCombinations2/NMIX; the old expression is kept verbatim when the exclusion is off.
1083         double denomfactor_izv  = denomfactor;
1084         if (fExcludeAdjTF>0){
1085             if (nComb_used[izv]<=0){ continue; }
1086             denomfactor_izv = ((double)nComb_used[izv])/nevt;
1087             cout<<"CalcRm::Calculate -- sec 18.23 izv="<<izv<<"  mixed event pairs used/possible="<<nComb_used[izv]<<"/"<<nComb_possible[izv]
1088                 <<Form(" (%.2f%%)",100.*nComb_used[izv]/std::max(1L,nComb_possible[izv]))<<"  denomfactor="<<denomfactor_izv<<" (NMIX-only: "<<denomfactor<<")"<<endl;
1089         }
1090         cout<<"CalcRm::Calculate -- izv="<<izv<<"  nev="<<nevt<<"  NpairSibling="<<hrho2_S[0][izv]->GetEntries()<<"  NpairMixed="<<hrho2_M[0][izv]->GetEntries()<<endl;
1091         sliceOK[izv]    = true;
1092         fDenomZ[izv]    = denomfactor_izv;      // README_Finalize: saved per zvtx bin for combining chunks
1093         //
1094         //cout<<"---------------------------------------"<<endl;
1095         //cout<<izv<<" \t <n1>="<<hmult[izv]->ProjectionX()->GetMean()
1096         //      <<" <n2>="<<hmult[izv]->ProjectionY()->GetMean()
1097         //      <<" \t "<<endl;
1098         //
1099         hy1_[izv]   ->Scale(1./nevt);
1100         hy2_[izv]   ->Scale(1./nevt);
1101         hyc1_[izv]  ->Scale(1./nevt);
1102         hyc2_[izv]  ->Scale(1./nevt);
1103         hrho1_1[izv]->Scale(1./nevt);
1104         hrho1_2[izv]->Scale(1./nevt);
1105         //
1106         double ainte_1,ainte_2;
1107         double aint_1   = hy1_[izv]->IntegralAndError(1,0,ainte_1,"");
1108         double aint_2   = hy2_[izv]->IntegralAndError(1,0,ainte_2,"");
1109         double binte_1,binte_2;
1110         double bint_1   = hrho1_1[izv]->IntegralAndError(1,0,1,0,1,0,binte_1,"");
1111         double bint_2   = hrho1_2[izv]->IntegralAndError(1,0,1,0,1,0,binte_2,"");
1112         double icheck1  = int(10000.*fabs(f1_1-aint_1));
1113         double icheck2  = int(10000.*fabs(f1_2-aint_2));
1114         if ( icheck1>1 || icheck2>1 ){              // <0.5/10000 accuracy or better
1115             cout<<"INTTEST FAIL .. izv="<<izv
1116                 <<" \t part1: "<<f1_1<<" "<<aint_1<<" "<<bint_1<<" chk="<<icheck1
1117                 <<" \t part2: "<<f1_2<<" "<<aint_2<<" "<<bint_2<<" chk="<<icheck2
1118                 <<endl; 
1119         }
1120         //
1121         for (int ir2=0;ir2<NR2TYPES;ir2++){
1122             double npair_S      = hrho2_S[0][izv]->GetEntries();
1123             double npair_M      = hrho2_M[0][izv]->GetEntries();
1124             hrho2_S[ir2][izv]   ->Scale(1.0/nevt            );
1125             hrho2_M[ir2][izv]   ->Scale(1.0/nevt/denomfactor_izv);  // sec 18.23
1126             //
1127 //dptM          hrho2_S_dptP[ir2][izv]  ->Scale(1.0/nevt            );  // ir2=2 (dy,dq) isn't actually filled at the moment...
1128 //dptM          hrho2_M_dptP[ir2][izv]  ->Scale(1.0/nevt/denomfactor);
1129 //dptM          hrho2_S_dptN[ir2][izv]  ->Scale(1.0/nevt            );
1130 //dptM          hrho2_M_dptN[ir2][izv]  ->Scale(1.0/nevt/denomfactor);
1131             //
1132             //BuildR2( hrho2_S[ir2][izv], hrho2_M[ir2][izv], hR2[ir2][izv] );   // this method defined in READER CLASS
1133             //
1134             hC2[ir2][izv]       ->Reset();
1135             hR2[ir2][izv]       ->Reset();
1136             for (int ibin=1;ibin<=hrho2_S[ir2][izv]->GetNbinsX();ibin++){
1137                 for (int jbin=1;jbin<=hrho2_S[ir2][izv]->GetNbinsY();jbin++){
1138                     double valn     = hrho2_S[ir2][izv]->GetBinContent(ibin,jbin);  // rho2
1139                     double valne    = hrho2_S[ir2][izv]->GetBinError(  ibin,jbin);  // rho2e
1140                     double vald     = hrho2_M[ir2][izv]->GetBinContent(ibin,jbin);  // rho1rho1
1141                     double valde    = hrho2_M[ir2][izv]->GetBinError(  ibin,jbin);  // rho1rho1e
1142                     double valC2,valC2e,valR2,valR2e;
1143                     //---- valid iff the denominator is filled. rho2(S)=0 over a filled denominator is a valid
1144                     //---- zero (R2=-1, C2=-rho2(M)); its error uses one pair's worth of density (1/nevt) for
1145                     //---- rho2(S). Approximate -- these per-run errors are replaced by subgroup errors in Finalize.
1146                     if (vald>0. && valn<=0.){
1147                         double valne1   = 1./nevt;
1148                         valC2    = -vald;
1149                         valC2e   = sqrt(valne1*valne1 + valde*valde);
1150                         valR2    = -1.;
1151                         valR2e   = valne1/vald;
1152                     } else if (valn>0.&&vald>0.){
1153                         valC2    = valn - vald;
1154                         valC2e   = sqrt(valne*valne + valde*valde);
1155                         valR2    = valn/vald;
1156                         valR2e   = valR2*sqrt(pow(valde/vald,2)+pow(valne/valn,2)); // uncertainty of ratio
1157                         valR2   -= 1.;  // note must get errors BEFORE SUBTRACTING 1!! (this 1 has no error!)
1158 //                      if (fPid1==2&&fPid2==2&&ir2==1&&izv==16&&ibin==20&&jbin==7){
1159 //                          cout<<"R2CLASS: "<<valn<<"+-"<<valne<<"\t"<<vald<<"+-"<<valde<<"\t"<<valR2<<"+-"<<valR2e<<endl;
1160 //                      }
1161                         //if (izv==16 && (ibin==1&&jbin==1)){cout<<ir2<<" "<<valR2<<" "<<valR2e<<endl;}
1162                         //
1163                     //} else if (valn>0){
1164                     //  cout<<"rho2_S nonzero & rho2_M zero "<<ibin<<" "<<jbin<<" "<<vald<<" "<<valn<<endl; 
1165                     } else {
1166                         valC2   =  0.;  //?
1167                         valC2e  =  0.;  //?
1168                         valR2   = -1.;
1169                         valR2e  =  0.;
1170                     }
1171                     hC2[ir2][izv]   ->SetBinContent(ibin,jbin,valC2 );
1172                     hC2[ir2][izv]   ->SetBinError(  ibin,jbin,valC2e);                       
1173                     hR2[ir2][izv]   ->SetBinContent(ibin,jbin,valR2 );
1174                     hR2[ir2][izv]   ->SetBinError(  ibin,jbin,valR2e);                       
1175                     //
1176                     if (TMath::IsNaN(valC2)){cout<<"c2 nan"<<endl;}
1177                     if (TMath::IsNaN(valC2e)){cout<<"c2e nan"<<endl;}
1178                     if (TMath::IsNaN(valR2)){cout<<"r2 nan"<<endl;}
1179                     if (TMath::IsNaN(valR2e)){cout<<"r2e nan"<<endl;}
1180                 }
1181             }   
1182             //
1183         }   // end r2 types
1184         //
1185         hMinv_S[izv]    ->ResetBit(TH1::kIsAverage);
1186         hMinv_M[izv]    ->ResetBit(TH1::kIsAverage);
1187         hMinv_S[izv]    ->Scale(1.0);
1188         hMinv_M[izv]    ->Scale(1.0/denomfactor_izv);   // sec 18.23
1189         double entvals  = hMinv_S[izv]->GetEntries();
1190         double entvalm  = hMinv_M[izv]->GetEntries();
1191         for (int ibin=1;ibin<=hMinv_S[izv]->GetNbinsX();ibin++){    // copy hMinv_S into hMinv
1192             double val  = hMinv_S[izv]->GetBinContent(ibin);
1193             double vale = hMinv_S[izv]->GetBinError(  ibin);
1194             hMinv[izv]  ->SetBinContent(ibin,val );
1195             hMinv[izv]  ->SetBinError(  ibin,vale);
1196         }
1197         hMinv[izv]  ->SetEntries(entvals);      // this is Minv_S - Minv_M
1198         hMinv[izv]  ->Add(hMinv_M[izv],-1.0);
1199         //
1200         //---- Femtoscopic C(Q) = hQsib/hQmix in this Zvtx bin. hQsib is left as raw (per-NMIX-events)
1201         //---- counts, matching how hMinv_S is left un-normalized; hQmix must be brought down to the
1202         //---- same "per-event" footing before the ratio is meaningful, since (per Increment()) each
1203         //---- fillHists cycle deposits NMIX sibling-events'-worth of pairs into hQsib but
1204         //---- NCombinations2=NMIX*(NMIX-1)/2 mixed-event-pairs'-worth into hQmix. denomfactor
1205         //---- (=NCombinations2/NMIX=(NMIX-1)/2) removes exactly that excess -- it depends only on NMIX.
1206         hQmix[izv]  ->Scale(1.0/denomfactor_izv);   // sec 18.23
1207         hQmixKT[izv]->Scale(1.0/denomfactor_izv);   // README_CQ step 3, same normalization
1208         hQmixW[izv] ->Scale(1.0/denomfactor_izv);   // long-Q test copy, same normalization
1209         //---- same bin-by-bin ratio for the 1D and the (Qinv,kT) versions; GetNcells covers every bin
1210         //---- including flow (the kT under/overflow are real kT ranges, <0.15 and >0.60)
1211         TH1* qn[2]  = {hQsib[izv], hQsibKT[izv]};
1212         TH1* qd[2]  = {hQmix[izv], hQmixKT[izv]};
1213         TH1* qc[2]  = {hCQ[izv],   hCQKT[izv]  };
1214         for (int k=0;k<2;k++){
1215             qc[k]   ->Reset();
1216             for (int ibin=0;ibin<qn[k]->GetNcells();ibin++){
1217                 double valn     = qn[k]->GetBinContent(ibin);
1218                 double valne    = qn[k]->GetBinError(  ibin);
1219                 double vald     = qd[k]->GetBinContent(ibin);
1220                 double valde    = qd[k]->GetBinError(  ibin);
1221                 double valCQ,valCQe;
1222                 if (vald>0. && valn<=0.){       // valid zero; one-pair error (approximate, replaced in Finalize)
1223                     valCQ   = 0.;
1224                     valCQe  = 1./vald;
1225                 } else if (valn>0. && vald>0.){
1226                     valCQ   = valn/vald;
1227                     valCQe  = valCQ*sqrt(pow(valne/valn,2)+pow(valde/vald,2));
1228                 } else {
1229                     valCQ   = 0.;
1230                     valCQe  = 0.;
1231                 }
1232                 qc[k]->SetBinContent(ibin,valCQ );
1233                 qc[k]->SetBinError(  ibin,valCQe);
1234             }
1235         }
1236         //
1237         //      hMinvdq_S[izv]  ->Scale(1.0);
1238         //      hMinvdq_M[izv]  ->Scale(1.0/denomfactor);
1239         //if (izv==15){
1240         //  cout<<hMinvdq_S[izv]->GetNbinsX()<<" "<<hMinvdq_S[izv]->GetNbinsY()<<" "
1241         //      <<hMinvdq_S[izv]->GetEntries()<<" "
1242         //      <<hMinvdq_M[izv]->GetNbinsX()<<" "<<hMinvdq_M[izv]->GetNbinsY()<<" "
1243         //      <<hMinvdq_M[izv]->GetEntries()<<" "
1244         //      <<endl;
1245         //}
1246         //      for (int ibin=1;ibin<=hMinvdq_S[izv]->GetNbinsX();ibin++){
1247         //          for (int jbin=1;jbin<=hMinvdq_S[izv]->GetNbinsY();jbin++){
1248         //              double val      = hMinvdq_S[izv]->GetBinContent(ibin,jbin);
1249         //              double vale     = hMinvdq_S[izv]->GetBinError(  ibin,jbin);
1250         //if (izv==15 && val!=0){
1251         //double tmpdq= hMinvdq_S[izv]->GetXaxis()->GetBinCenter(ibin);
1252         //double tmpm   = hMinvdq_S[izv]->GetYaxis()->GetBinCenter(jbin);
1253         //cout<<tmpdq<<" "<<tmpm<<" \t "<<val<<" "<<vale<<" \t "
1254         //  <<    hMinvdq_M[izv]->GetBinContent(ibin,jbin)<<" \t "
1255         //  <<val-hMinvdq_M[izv]->GetBinContent(ibin,jbin)
1256         //  <<endl;
1257         //}
1258         //              hMinvdq[izv]    ->SetBinContent(ibin,jbin,val);
1259         //              hMinvdq[izv]    ->SetBinError(  ibin,jbin,vale);
1260         //          }
1261         //      }
1262         //      hMinvdq[izv]->Add(hMinvdq_M[izv],-1.0);
1263         //
1264         //cout<<"CalcRm::Calculate -- Calculating R2..."<<endl;
1265         //
1266         //---- get and apply Baseline
1267         if (fDoBaseline){
1268             double baseR2       = GetR2Baseline(hmult[izv]);
1269             //cout<<"CalcRc::Calculate -- Baseline: "<<baseR2<<endl;
1270             for (int ir2=0;ir2<NR2TYPES;ir2++){     
1271                 for (int ibx=1;ibx<=hR2[ir2][izv]->GetNbinsX();ibx++){
1272                     for (int iby=1;iby<=hR2[ir2][izv]->GetNbinsY();iby++){
1273                         double oval2 = hR2[ir2][izv]->GetBinContent(ibx,iby);   // shift itself assumed known perfectly for now
1274                         if (hrho2_M[ir2][izv]->GetBinContent(ibx,iby)>0.){      // valid bin (README_Crossing sec 8)
1275                             hR2[ir2][izv]->SetBinContent(ibx,iby,oval2-baseR2);     // and keep same errors
1276                         } else {
1277                             hR2[ir2][izv]->SetBinContent(ibx,iby,0.);               // no entries here!
1278                             hR2[ir2][izv]->SetBinError(ibx,iby,0.);                 // clamp error to zero for safety! 
1279                         }
1280                     }   // end iby
1281                 }   // end ibx
1282             }   // end r2 type
1283         }   // end doBaseline
1284         //
1285         //---- README_Crossing step 6: crossing correction, (dy,dphi) only, per Zvtx bin, applied ONCE
1286         //---- to the final uncorrected rho2(S), C2, R2 (after the baseline shift). rho2(M) is never
1287         //---- corrected. With "nocross" the C histograms stay empty.
1288         if (fDoCrossing){
1289             TH2D* src[3]    = { hrho2_S[1][izv], hC2[1][izv], hR2[1][izv] };
1290             TH2D* dst[3]    = { hrho2C_S[izv],   hC2C[izv],   hR2C[izv]   };
1291             for (int k=0;k<3;k++){
1292                 dst[k]->Reset();
1293                 for (int ib=0;ib<(src[k]->GetNbinsX()+2)*(src[k]->GetNbinsY()+2);ib++){
1294                     dst[k]->SetBinContent(ib,src[k]->GetBinContent(ib));
1295                     dst[k]->SetBinError(  ib,src[k]->GetBinError(ib));
1296                 }
1297                 dst[k]->SetEntries(src[k]->GetEntries());
1298                 CrossingCorrect(dst[k],fDirtySide,hrho2_M[1][izv]);
1299             }
1300             //---- validity of the corrected maps in this slice: correct a 0/1 mask of rho2(M)>0 with itself
1301             hMaskC[izv] = (TH2D*)hrho2_M[1][izv]->Clone(Form("hMaskC%d",izv));
1302             hMaskC[izv]->Reset();
1303             for (int ib=0;ib<hMaskC[izv]->GetNcells();ib++){        // all cells, incl. under/overflow (never touched by CrossingCorrect)
1304                 hMaskC[izv]->SetBinContent(ib, hrho2_M[1][izv]->GetBinContent(ib)>0. ? 1. : 0.);
1305             }
1306             CrossingCorrect(hMaskC[izv],fDirtySide,hMaskC[izv]);
1307         }
1308 
1309         //double dAvg_dy[2*YNB-1];  memset( dAvg_dy, 0, (2*YNB-1)*sizeof(int) );
1310         //double dAvg_N[2*YNB-1];   memset( dAvg_N,    0, (2*YNB-1)*sizeof(int) );
1311         //double dAvg_S[2*YNB-1];   memset( dAvg_S,    0, (2*YNB-1)*sizeof(int) );
1312         //cout<<"CalcRm::Calculate -- Averaging in dy slices..."<<endl;
1313 
1314         //for (int ibx=1;ibx<=hrho2_S[0][izv]->GetXaxis()->GetNbins();ibx++){       // x-bin is y1
1315         //  for (int iby=1;iby<=hrho2_S[0][izv]->GetYaxis()->GetNbins();iby++){     // y-bin is y2
1316         //      double dy,ay,val,vale;
1317         //      dy      = hrho2_S[0][izv]->GetXaxis()->GetBinCenter(ibx) 
1318         //              - hrho2_S[0][izv]->GetYaxis()->GetBinCenter(iby);
1319         //      //ay    =(hrho2_S[0][izv]->GetXaxis()->GetBinCenter(ibx)
1320         //      //      + hrho2_S[0][izv]->GetYaxis()->GetBinCenter(iby))/2.;
1321         //      val     = hrho2_S[0][izv]->GetBinContent(ibx,iby);
1322         //      vale    = hrho2_S[0][izv]->GetBinError(ibx,iby);
1323         //      hrho2_Sdy[izv]  ->Fill(dy, val);
1324         //      hrho2_Sdye[izv] ->Fill(dy, vale*vale);
1325         //      hrho2_SdyN[izv] ->Fill(dy, 1.0);
1326         //  }   // iby
1327         //} // ibx
1328         //for (int ibi=1;ibi<=hrho2_Sdy[izv]->GetNbinsX();ibi++){
1329         //  double v,e,n;
1330         //  v   =       hrho2_Sdy[izv]  ->GetBinContent(ibi);
1331         //  e   = sqrt( hrho2_Sdye[izv] ->GetBinContent(ibi));
1332         //  n   =       hrho2_SdyN[izv] ->GetBinContent(ibi);
1333         //  if (n>0){
1334         //      hrho2_Sdy[izv]->SetBinContent(ibi,v/n);                 
1335         //      hrho2_Sdy[izv]->SetBinError(ibi,e/n);
1336         //  }
1337         //}
1338         //delete[] hrho2_Sdye; //hrho2_Sdye[izv]=0;
1339         //delete[] hrho2_SdyN; //hrho2_SdyN[izv]=0;
1340     
1341         //---- Project R2(y1,y2) onto R2(dy)...
1342         //      we now get R2(dy) by projecting R2(dy,dphi), NOT from R2(y1,y2) as before
1343         //      ...because R2(dy,dphi) includes the complete correction for track crossing
1344         //
1345         //for (int ibx=1;ibx<=hR2[0][izv]->GetXaxis()->GetNbins();ibx++){       // x-bin is y1
1346         //  for (int iby=1;iby<=hR2[0][izv]->GetYaxis()->GetNbins();iby++){     // y-bin is y2
1347         //      double dy,ay,val,vale;
1348         //      dy      = hR2[0][izv]->GetXaxis()->GetBinCenter(ibx) 
1349         //              - hR2[0][izv]->GetYaxis()->GetBinCenter(iby);
1350         //      //ay    =(hR2[0][izv]->GetXaxis()->GetBinCenter(ibx)
1351         //      //      + hR2[0][izv]->GetYaxis()->GetBinCenter(iby))/2.;
1352         //      val     = hR2[0][izv]->GetBinContent(ibx,iby);
1353         //      vale    = hR2[0][izv]->GetBinError(ibx,iby);
1354         //      hR2dy[izv]  ->Fill(dy, val);
1355         //      hR2dye[izv] ->Fill(dy, vale*vale);
1356         //      hR2dyN[izv] ->Fill(dy, 1.0);
1357         //  }   // iby
1358         //} // ibx
1359         //for (int ibi=1;ibi<=hR2dy[izv]->GetNbinsX();ibi++){
1360         //  double v,e,n;
1361         //  v   =       hR2dy[izv]  ->GetBinContent(ibi);
1362         //  e   = sqrt( hR2dye[izv] ->GetBinContent(ibi));
1363         //  n   =       hR2dyN[izv] ->GetBinContent(ibi);
1364         //  if (n>0){
1365         //      hR2dy[izv]->SetBinContent(ibi,v/n);                 
1366         //      hR2dy[izv]->SetBinError(ibi,e/n);
1367         //  }
1368         //}
1369         //delete[] hR2dye; //hR2dye[izv]=0;
1370         //delete[] hR2dyN; //hR2dyN[izv]=0;
1371         //
1372         //---- Project R2(y1,y2) onto R2yy(dy) (a cross-check). Equal y widths = the dy width: the cell centre is a dy bin
1373         //---- centre; otherwise each cell is spread over the dy bins it overlaps (DyOverlap, fluct_common.h).
1374         bool sameW  = (fabs(YBW1-YBW2)<1.e-6 && fabs(YBW1-DYBW)<1.e-6);
1375         std::vector<std::pair<int,double>> ov;
1376         for (int ibx=1;ibx<=hR2[0][izv]->GetXaxis()->GetNbins();ibx++){         // x-bin is y1
1377             for (int iby=1;iby<=hR2[0][izv]->GetYaxis()->GetNbins();iby++){     // y-bin is y2
1378                 double y1,y2,dy,val,vale;
1379                 y1      = hR2[0][izv]->GetXaxis()->GetBinCenter(ibx);
1380                 y2      = hR2[0][izv]->GetYaxis()->GetBinCenter(iby);
1381                 dy      = y1 - y2;
1382                 val     = hR2[0][izv]->GetBinContent(ibx,iby);
1383                 vale    = hR2[0][izv]->GetBinError(ibx,iby);
1384                 if (hrho2_M[0][izv]->GetBinContent(ibx,iby)>0.){    // valid bin (README_Crossing sec 8); R2=-1 is valid
1385                     if (sameW){ ov.clear(); ov.push_back({hR2yydy[izv]->GetXaxis()->FindFixBin(dy),1.0}); }
1386                     else DyOverlap(y1,YBW1,y2,YBW2,DYNB,DYL,DYBW,ov);
1387                     for (auto &o : ov){
1388                         double x    = hR2yydy[izv]->GetXaxis()->GetBinCenter(o.first);
1389                         hR2yydy[izv]    ->Fill(x, o.second*val);
1390                         hR2yydye[izv]   ->Fill(x, o.second*vale*vale);
1391                         hR2yydyN[izv]   ->Fill(x, o.second);
1392                     }
1393                 }
1394             }   // iby
1395         }   // ibx
1396         for (int ibi=1;ibi<=hR2dy[izv]->GetNbinsX();ibi++){
1397             double v,e,n;
1398             v   =       hR2yydy[izv]    ->GetBinContent(ibi);
1399             e   = sqrt( hR2yydye[izv]   ->GetBinContent(ibi));
1400             n   =       hR2yydyN[izv]   ->GetBinContent(ibi);
1401             if (n>0){
1402                 hR2yydy[izv]->SetBinContent(ibi,v/n);                   
1403                 hR2yydy[izv]->SetBinError(ibi,e/n);
1404             }
1405         }
1406         //delete[] hR2dye; //hR2dye[izv]=0;
1407         //delete[] hR2dyN; //hR2dyN[izv]=0;
1408         //
1409         //---- Project R2(dy,dphi) onto R2(dy)...
1410         for (int ibx=1;ibx<=hR2[1][izv]->GetXaxis()->GetNbins();ibx++){         // x-bin is dy
1411             for (int iby=1;iby<=hR2[1][izv]->GetYaxis()->GetNbins();iby++){     // y-bin is dphi
1412                 double dy,ay,val,vale;
1413                 dy      = hR2[1][izv]->GetXaxis()->GetBinCenter(ibx);
1414                 val     = hR2[1][izv]->GetBinContent(ibx,iby);
1415                 vale    = hR2[1][izv]->GetBinError(ibx,iby);
1416                 if (hrho2_M[1][izv]->GetBinContent(ibx,iby)>0.){    // valid bin (README_Crossing sec 8); R2=-1 is valid
1417                     hR2dy[izv]  ->Fill(dy, val);
1418                     hR2dye[izv] ->Fill(dy, vale*vale);
1419                     hR2dyN[izv] ->Fill(dy, 1.0);
1420                 }
1421             }   // iby
1422         }   // ibx
1423         for (int ibi=1;ibi<=hR2dy[izv]->GetNbinsX();ibi++){
1424             double v,e,n;
1425             v   =       hR2dy[izv]  ->GetBinContent(ibi);
1426             e   = sqrt( hR2dye[izv] ->GetBinContent(ibi));
1427             n   =       hR2dyN[izv] ->GetBinContent(ibi);
1428             if (n>0){
1429                 hR2dy[izv]->SetBinContent(ibi,v/n);                 
1430                 hR2dy[izv]->SetBinError(ibi,e/n);
1431             }
1432         }
1433         //delete[] hR2dye; //hR2dye[izv]=0;
1434         //delete[] hR2dyN; //hR2dyN[izv]=0;
1435         //
1436         //---- Project R2(dy,dphi) onto R2(dphi)...
1437         for (int iby=1;iby<=hR2[1][izv]->GetYaxis()->GetNbins();iby++){         // y-bin is dphi
1438             for (int ibx=1;ibx<=hR2[1][izv]->GetXaxis()->GetNbins();ibx++){     // x-bin is dy
1439                 double dphi = hR2[1][izv]->GetYaxis()->GetBinCenter(iby);
1440                 double val  = hR2[1][izv]->GetBinContent(ibx,iby);
1441                 double vale = hR2[1][izv]->GetBinError(ibx,iby);
1442                 if (hrho2_M[1][izv]->GetBinContent(ibx,iby)>0.){    // valid bin (README_Crossing sec 8); R2=-1 is valid
1443                     hR2dphi[izv]    ->Fill(dphi,val);
1444                     hR2dphie[izv]   ->Fill(dphi,vale*vale);
1445                     hR2dphiN[izv]   ->Fill(dphi,1.0);
1446                 }
1447             }   // iby
1448         }   // ibx
1449         for (int ibi=1;ibi<=hR2dphi[izv]->GetNbinsX();ibi++){
1450             double v,e,n;
1451             v   =       hR2dphi[izv]    ->GetBinContent(ibi);
1452             e   = sqrt( hR2dphie[izv]   ->GetBinContent(ibi));
1453             n   =       hR2dphiN[izv]   ->GetBinContent(ibi);
1454             if (n>0){
1455                 hR2dphi[izv]->SetBinContent(ibi,v/n);                   
1456                 hR2dphi[izv]->SetBinError(ibi,e/n);
1457             }
1458         }
1459         //delete[] hR2dye; //hR2dye[izv]=0;
1460         //delete[] hR2dyN; //hR2dyN[izv]=0;
1461         //
1462     }
1463     //delete[] hm2D; //hm2D=0;
1464 
1465     //---- now get the zvtx-averaged histograms...
1466     //
1467     //  Note; you ONLY average histograms that are *averages* (i.e. hR2xxx... )
1468     //       histograms that are counts are *summed* here (i.e. hmult, hMinv... ) 
1469     //
1470     double znent    = hzvtx->GetEntries();
1471     TH1D* hzvtxprob = (TH1D*)hzvtx->Clone("hzvtxprob");
1472     if (znent>0){ hzvtxprob->Scale(1./znent); } else { hzvtxprob->Reset(); }
1473     double weightsum = 0;
1474     for (int izv=0;izv<ZVTXNB;izv++){
1475         //
1476         double weight        = hzvtxprob->GetBinContent(izv+1);
1477         weightsum           += weight;
1478         //cout<<"Zvtx-Avg ... "<<izv<<" "<<weight<<" "<<weightsum<<endl;    // had better equal 1 by the last zvtx bin !!!!
1479         //
1480         hmult[ZVTXNB]               ->Add(hmult[izv]   ,   1.0);
1481         hy1_[ZVTXNB]                ->Add(hy1_[izv]    ,weight);        // Average
1482         hy2_[ZVTXNB]                ->Add(hy2_[izv]    ,weight);        // Average
1483         hyc1_[ZVTXNB]               ->Add(hyc1_[izv]   ,weight);        // Average
1484         hyc2_[ZVTXNB]               ->Add(hyc2_[izv]   ,weight);        // Average
1485         hrho1_1[ZVTXNB]             ->Add(hrho1_1[izv] ,weight);
1486         hrho1_2[ZVTXNB]             ->Add(hrho1_2[izv] ,weight);
1487         for (int ir2=0;ir2<NR2TYPES;ir2++){
1488             //---- rho2(S), rho2(M), C2, R2: averaged over VALID slices only, after this loop
1489             //
1490 //dptM          hrho2_S_dptP[ir2][ZVTXNB]   ->Add(hrho2_S_dptP[ir2][izv] ,weight);  // average...
1491 //dptM          hrho2_M_dptP[ir2][ZVTXNB]   ->Add(hrho2_M_dptP[ir2][izv] ,weight);  // average...
1492 //dptM          hrho2_S_dptN[ir2][ZVTXNB]   ->Add(hrho2_S_dptN[ir2][izv] ,weight);  // average...
1493 //dptM          hrho2_M_dptN[ir2][ZVTXNB]   ->Add(hrho2_M_dptN[ir2][izv] ,weight);  // average...
1494             //
1495         }
1496         //---- crossing-corrected maps, R2 projections, C(Q): averaged over VALID slices only, after this loop
1497         hMinv_S[ZVTXNB]     ->Add(hMinv_S[izv]  ,   1.0);
1498         hMinv_M[ZVTXNB]     ->Add(hMinv_M[izv]  ,   1.0);
1499         hMinv[ZVTXNB]       ->Add(hMinv[izv]    ,   1.0);
1500         hQsib[ZVTXNB]       ->Add(hQsib[izv]    ,   1.0);
1501         hQmix[ZVTXNB]       ->Add(hQmix[izv]    ,   1.0);
1502         hQsibKT[ZVTXNB]     ->Add(hQsibKT[izv]  ,   1.0);
1503         hQmixKT[ZVTXNB]     ->Add(hQmixKT[izv]  ,   1.0);
1504         hQsibW[ZVTXNB]      ->Add(hQsibW[izv]   ,   1.0);
1505         hQmixW[ZVTXNB]      ->Add(hQmixW[izv]   ,   1.0);
1506         //
1507         //double nev    = hmult[izv]->GetEntries();
1508         //double np = hmult[izv]->ProjectionX()->GetMean();
1509         //double npi    = hmult[izv]->ProjectionY()->GetMean();
1510         //double npair= hMinv_S[izv]->GetEntries();
1511         //cout<<izv<<" "<<nev<<" "<<np<<" "<<npi<<" "<<npair<<" "<<npair/nev<<" "<<np*npi<<endl;
1512         //
1513     }   // end Zvtx averaging
1514     //
1515     //---- CF-type histograms: Zvtx average over valid slices only (README_Crossing sec 8, 2026-09-25).
1516     //---- An empty denominator is never averaged in; it is counted (hMempty, one log line). The real check
1517     //---- (squawk, reduce binning) belongs in Finalize at full stats.
1518     {
1519         double wz[NZVTXMAX];
1520         for (int izv=0;izv<ZVTXNB;izv++) wz[izv] = hzvtxprob->GetBinContent(izv+1);
1521         TH1* sl[NZVTXMAX]; TH1* mk[NZVTXMAX];
1522         for (int ir2=0;ir2<NR2TYPES;ir2++){
1523             for (int izv=0;izv<ZVTXNB;izv++) mk[izv] = hrho2_M[ir2][izv];
1524             for (int izv=0;izv<ZVTXNB;izv++) sl[izv] = hrho2_S[ir2][izv];   ZvtxAverageValid(hrho2_S[ir2][ZVTXNB],sl,mk,wz,sliceOK,ZVTXNB, 0.);
1525             for (int izv=0;izv<ZVTXNB;izv++) sl[izv] = hC2[ir2][izv];       ZvtxAverageValid(hC2[ir2][ZVTXNB],    sl,mk,wz,sliceOK,ZVTXNB, 0.);
1526             for (int izv=0;izv<ZVTXNB;izv++) sl[izv] = hR2[ir2][izv];       ZvtxAverageValid(hR2[ir2][ZVTXNB],    sl,mk,wz,sliceOK,ZVTXNB,-1.);
1527             //---- rho2(M) last: it is its own mask
1528             for (int izv=0;izv<ZVTXNB;izv++) sl[izv] = hrho2_M[ir2][izv];   ZvtxAverageValid(hrho2_M[ir2][ZVTXNB],sl,mk,wz,sliceOK,ZVTXNB, 0.);
1529             //---- report empty denominators: (bin,slice) pairs with rho2(M)=0 in slices that were used
1530             long nMz=0, nSMz=0; int nbinAny=0;
1531             TH2D* hm    = hrho2_M[ir2][0];
1532             for (int ix=1;ix<=hm->GetNbinsX();ix++) for (int iy=1;iy<=hm->GetNbinsY();iy++){
1533                 int nz=0;
1534                 for (int izv=0;izv<ZVTXNB;izv++){
1535                     if (!sliceOK[izv] || wz[izv]<=0.) continue;
1536                     if (hrho2_M[ir2][izv]->GetBinContent(ix,iy)>0.) continue;
1537                     ++nz; ++nMz;
1538                     if (hrho2_S[ir2][izv]->GetBinContent(ix,iy)>0.) ++nSMz;
1539                 }
1540                 if (nz>0) ++nbinAny;
1541                 if (ir2==1) hMempty->SetBinContent(ix,iy,nz);
1542             }
1543             cout<<"CalcRm::Calculate -- empty denominators (pid "<<fPid1<<","<<fPid2<<", ir2="<<ir2<<"): "
1544                 <<nbinAny<<" of "<<hm->GetNbinsX()*hm->GetNbinsY()<<" bins have rho2(M)=0 in >=1 used Zvtx slice ("
1545                 <<nMz<<" bin-slices, left out of the Zvtx average; "<<nSMz<<" of them with rho2(S)>0). Finalize checks this at full stats."<<endl;
1546         }
1547         if (fDoCrossing){
1548             for (int izv=0;izv<ZVTXNB;izv++) mk[izv] = hMaskC[izv] ? (TH1*)hMaskC[izv] : (TH1*)hrho2_M[1][izv]; // unused slices have no mask
1549             for (int izv=0;izv<ZVTXNB;izv++) sl[izv] = hrho2C_S[izv];   ZvtxAverageValid(hrho2C_S[ZVTXNB],sl,mk,wz,sliceOK,ZVTXNB, 0.);
1550             for (int izv=0;izv<ZVTXNB;izv++) sl[izv] = hC2C[izv];       ZvtxAverageValid(hC2C[ZVTXNB],    sl,mk,wz,sliceOK,ZVTXNB, 0.);
1551             for (int izv=0;izv<ZVTXNB;izv++) sl[izv] = hR2C[izv];       ZvtxAverageValid(hR2C[ZVTXNB],    sl,mk,wz,sliceOK,ZVTXNB,-1.);
1552         }
1553         for (int izv=0;izv<ZVTXNB;izv++){ delete hMaskC[izv]; hMaskC[izv] = 0; }
1554         for (int izv=0;izv<ZVTXNB;izv++) sl[izv] = hR2yydy[izv];    ZvtxAverageValid(hR2yydy[ZVTXNB],sl,0,wz,sliceOK,ZVTXNB,0.);
1555         for (int izv=0;izv<ZVTXNB;izv++) sl[izv] = hR2dy[izv];      ZvtxAverageValid(hR2dy[ZVTXNB],  sl,0,wz,sliceOK,ZVTXNB,0.);
1556         for (int izv=0;izv<ZVTXNB;izv++) sl[izv] = hR2dphi[izv];    ZvtxAverageValid(hR2dphi[ZVTXNB],sl,0,wz,sliceOK,ZVTXNB,0.);
1557         for (int izv=0;izv<ZVTXNB;izv++){ sl[izv] = hCQ[izv]; mk[izv] = hQmix[izv]; }
1558         ZvtxAverageValid(hCQ[ZVTXNB],sl,mk,wz,sliceOK,ZVTXNB,0.);
1559         for (int izv=0;izv<ZVTXNB;izv++){ sl[izv] = hCQKT[izv]; mk[izv] = hQmixKT[izv]; }
1560         ZvtxAverageValid(hCQKT[ZVTXNB],sl,mk,wz,sliceOK,ZVTXNB,0.);
1561     }
1562     delete hzvtxprob; hzvtxprob = 0;
1563     //
1564     if (fChg1!=0. && fChg2!=0. && nPairCut[0][0]>0 && nPairCut[1][0]>0) // README_SplitTracks573 Final state: pair-cut fractions
1565         cout<<Form("CalcRm::Calculate -- pair cuts (pid %d,%d): tsep removed %.3f%% S / %.3f%% M, isep %.3f%% S / %.3f%% M of %ld S / %ld M charged pairs",
1566             fPid1,fPid2,100.*nPairCut[0][1]/nPairCut[0][0],100.*nPairCut[1][1]/nPairCut[1][0],100.*nPairCut[0][2]/nPairCut[0][0],100.*nPairCut[1][2]/nPairCut[1][0],nPairCut[0][0],nPairCut[1][0])<<endl;
1567     if (fDoCrossing && fDirtySide==0){
1568         cout<<"CalcRm::Calculate -- crossing correction (pid "<<fPid1<<","<<fPid2<<", dirty side 0): not pt-ordered, not corrected (C maps = uncorrected)"<<endl;
1569     } else if (fDoCrossing){    // README_Crossing step 7: log check that the corrected maps are dphi-symmetric
1570         cout<<"CalcRm::Calculate -- crossing correction (pid "<<fPid1<<","<<fPid2<<", dirty side "<<fDirtySide
1571             <<"): Zvtx-avg dphi-asymmetric bins: rho2C="<<CrossingAsymmetry(hrho2C_S[ZVTXNB])
1572             <<" C2C="<<CrossingAsymmetry(hC2C[ZVTXNB])<<" R2C="<<CrossingAsymmetry(hR2C[ZVTXNB])
1573             <<"  (uncorrected R2: "<<CrossingAsymmetry(hR2[1][ZVTXNB])<<" of "
1574             <<hR2C[ZVTXNB]->GetNbinsX()*hR2C[ZVTXNB]->GetNbinsY()<<")"<<endl;
1575     }
1576     //
1577     //double nev    = hmult[ZVTXNB]->GetEntries();
1578     //double np = hmult[ZVTXNB]->ProjectionX()->GetMean();
1579     //double npi    = hmult[ZVTXNB]->ProjectionY()->GetMean();
1580     //double npair= hMinv_S[ZVTXNB]->GetEntries();
1581     //cout<<ZVTXNB<<" "<<nev<<" "<<np<<" "<<npi<<" "<<npair<<" "<<npair/nev<<" "<<np*npi<<endl;
1582     //
1583 //  TimerCalculate->Stop();
1584 //  fTimeCalculate  += TimerCalculate->CpuTime();
1585     //
1586 }
1587 
1588 //------------------------------------------------------------
1589 // bool CalcRm::NextCombination(vector<int>& v, int k, int N) {
1590 //   // We want to find the index of the least significant element
1591 //   // in v that can be increased.  Let's call that index 'pivot'.
1592 //   int pivot = k - 1;
1593 //   while (pivot >= 0 && v[pivot] == N - k + pivot)
1594 //     --pivot;
1595 // 
1596 //   // pivot will be -1 iff v == {N - k, N - k + 1, ..., N - 1},
1597 //   // in which case, there is no next combination.
1598 //   if (pivot == -1)
1599 //     return false;
1600 // 
1601 //   ++v[pivot];
1602 //   for (int i = pivot + 1; i < k; ++i)
1603 //     v[i] = v[pivot] + i - pivot;
1604 //   return true;
1605 // }
1606 
1607 //----------------------------------------------------------------------------
1608 double CalcRm::GetR2Baseline(TH2D *hmult){
1609     double result   = -1.;
1610     if (!hmult){ cout<<"CalcRm::GetR2Baseline -- no hmult... exit"<<endl; exit(0); }
1611     double nent     = (double)hmult->GetEntries();
1612 //  if (nent<5){ cout<<"CalcRm::GetR2Baseline -- no entries..."<<endl; return result; }
1613     TH2D *hmultwork = (TH2D*)hmult->Clone("hmultwork");
1614     hmultwork       ->Scale(1./nent);
1615     double sumnum   = 0;
1616     double sumden1  = 0;
1617     double sumden2  = 0;
1618     TAxis* multaxisx    = (TAxis*)hmultwork->GetXaxis();
1619     TAxis* multaxisy    = (TAxis*)hmultwork->GetYaxis();
1620     TH1D* hmultworkx    = (TH1D*)hmultwork->ProjectionX();
1621     double meanmult     = hmultworkx->GetMean();
1622     if (!fDistinguishable){
1623         for (int ibx=1;ibx<=multaxisx->GetNbins();ibx++){
1624             double n1i   = multaxisx->GetBinCenter(ibx);
1625             double pi    = hmultworkx->GetBinContent(ibx);      
1626             sumnum      += pi*n1i*(n1i-1.);
1627             sumden1     += pi*n1i;
1628             //cout<<ibx<<" "<<n1i<<" "<<pi<<" "<<sumnum<<" "<<sumden1<<endl;
1629         }
1630         if ( sumnum>0.0 && sumden1>0.0 ){
1631             //result    = sumden1*sumden1/sumnum;           // rho1rho1/rho2
1632             result      = (sumnum/sumden1/sumden1) - 1.0;   // R2integral
1633             //cout<<">>--> "<<meanmult<<" "<<sumden1<<" "<<sumnum<<" \t "<<result<<" \t "<<sumnum/meanmult/meanmult<<endl;
1634         }
1635     } else if (fDistinguishable){
1636         for (int ibx=1;ibx<=multaxisx->GetNbins();ibx++){
1637             for (int iby=1;iby<=multaxisy->GetNbins();iby++){
1638                 double n1i   = multaxisx->GetBinCenter(ibx);
1639                 double n2i   = multaxisy->GetBinCenter(iby);
1640                 double pi    = hmultwork->GetBinContent(ibx,iby);       
1641                 sumnum      += pi*n1i*n2i;
1642                 sumden1     += pi*n1i;
1643                 sumden2     += pi*n2i;
1644             }
1645         }
1646         if (sumnum>0.0 && sumden1>0.0 && sumden2>0.0 ){
1647             //result    = sumden1*sumden2/sumnum;           // rho1rho1/rho2
1648             result      = (sumnum/sumden1/sumden2) - 1.0;   // R2integral
1649         }
1650     }   // end fDistinguishable...
1651     //
1652     delete hmultwork; hmultwork=0;
1653     return result;
1654 }
1655 
1656 //---- Ayeh code...
1657 //invariant mass and dq calculation
1658 //double px_p1, px_p2, py_p1, py_p2, etot_p1, etot_p2, 
1659 //double dpx_lsp, dpy_lsp, dpz_lsp, detot_lsp, dq_lsp, spx_lsp, spy_lsp, spz_lsp, setot_lsp,invm_lsp;
1660 ////px1=ptpmix[ievt][ii]*cos(Deg2Rad(phipmix[ievt][ii]-180));//arg cos and sin should be radian
1661 ////py1=ptpmix[ievt][ii]*sin(Deg2Rad(phipmix[ievt][ii]-180));
1662 ////px2=ptpmix[ievt2][kk]*cos(Deg2Rad(phipmix[ievt2][kk]-180));
1663 ////py2=ptpmix[ievt2][kk]*sin(Deg2Rad(phipmix[ievt2][kk]-180));
1664 ////etot_p1=sqrt((mass*mass)+(ptpmix[ievt][ii]*ptpmix[ievt][ii] + pzpmix[ievt][ii]*pzpmix[ievt][ii]));
1665 ////etot_p2=sqrt((mass*mass)+(ptpmix[ievt2][kk]*ptpmix[ievt2][kk] + pzpmix[ievt2][kk]*pzpmix[ievt2][kk]));
1666 //dpx_lsp=px1-px2;
1667 //dpy_lsp=py1-py2;
1668 //dpz_lsp=pz1-pz2;
1669 //detot_lsp=pE1-pE2;
1670 //spx_lsp=px1+px2;
1671 //spy_lsp=py1+py2;
1672 //spz_lsp=pz1+pz2;
1673 //setot_lsp=pE1+pE2;
1674 //dq_lsp=sqrt( ((dpx_lsp*dpx_lsp)+(dpy_lsp*dpy_lsp)+(dpz_lsp*dpz_lsp))-(detot_lsp*detot_lsp) );
1675 ////invm_lsp=sqrt( (setot_lsp*setot_lsp)-((spx_lsp*spx_lsp)+(spy_lsp*spy_lsp)+(spz_lsp*spz_lsp)) );
1676 ////---- end Ayeh code...
1677