File indexing completed on 2025-08-03 08:13:03
0001 #include "EpFinder.h"
0002 #include "TVector3.h"
0003 #include "TH2D.h"
0004 #include "TFile.h"
0005 #include "TProfile.h"
0006 #include "TProfile2D.h"
0007 #include "TClonesArray.h"
0008 #include "TMath.h"
0009 #include <cassert>
0010 #include <iostream>
0011 #include <vector>
0012
0013 using namespace std;
0014
0015
0016 EpFinder::EpFinder(int nEventTypeBins, char const* OutFileName, char const* CorrectionFile, int pbinsx, int pbinsy) : mThresh(0.3), mMax(2.0)
0017 {
0018
0019 cout << "\n**********\n* Welcome to the Event Plane finder.\n"
0020 << "* Please note that when you specify 'order' as an argument to a method,\n"
0021 << "* then 1=first-order plane, 2=second-order plane, etc.\n"
0022 << "* This code is currently configured to go up to order=" << _EpOrderMax << "\n";
0023 cout << "**********\n";
0024
0025 mNumberOfEventTypeBins = nEventTypeBins;
0026
0027
0028
0029 mCorrectionInputFile = new TFile(CorrectionFile,"READ");
0030 if (mCorrectionInputFile->IsZombie()) {
0031 std::cout << "EPFinder: Error opening file with Correction Histograms" << std::endl;
0032 std::cout << "EPFinder: I will use no weighting at all." << std::endl;
0033 for (int order=1; order<_EpOrderMax+1; order++){
0034 mEpShiftInput_sin[order-1] = NULL;
0035 mEpShiftInput_cos[order-1] = NULL;
0036 }
0037 mPhiWeightInput = NULL;
0038 }
0039 else{
0040 for (int order=1; order<_EpOrderMax+1; order++){
0041 mEpShiftInput_sin[order-1] = (TProfile2D*)mCorrectionInputFile->Get(Form("EpShiftPsi%d_sin",order));
0042 mEpShiftInput_cos[order-1] = (TProfile2D*)mCorrectionInputFile->Get(Form("EpShiftPsi%d_cos",order));
0043 }
0044 mPhiWeightInput = (TH2D*)mCorrectionInputFile->Get(Form("PhiWeight"));
0045 }
0046
0047
0048 mCorrectionOutputFile = new TFile(OutFileName,"RECREATE");
0049 for (int order=1; order<_EpOrderMax+1; order++){
0050 mEpShiftOutput_sin[order-1] = new TProfile2D(Form("EpShiftPsi%d_sin",order),Form("EpShiftPsi%d_sin",order),
0051 _EpTermsMax,0.5,1.0*_EpTermsMax+.5,nEventTypeBins,-0.5,(double)nEventTypeBins-0.5,-1.0,1.0);
0052 mEpShiftOutput_cos[order-1] = new TProfile2D(Form("EpShiftPsi%d_cos",order),Form("EpShiftPsi%d_cos",order),
0053 _EpTermsMax,0.5,1.0*_EpTermsMax+.5,nEventTypeBins,-0.5,(double)nEventTypeBins-0.5,-1.0,1.0);
0054 }
0055
0056 if(pbinsx<=0) pbinsx = 1;
0057 if(pbinsy<=0) pbinsy = 1;
0058
0059
0060
0061 mPhiWeightOutput = new TH2D(Form("PhiWeight"),Form("Phi Weight"),pbinsx,-0.5,(pbinsx-0.5),pbinsy,-0.5,(pbinsy-0.5));
0062
0063 mPhiAveraged = new TH2D(Form("PhiAveraged"),Form("Phi Average"),pbinsx,-0.5,(pbinsx-0.5),pbinsy,-0.5,(pbinsy-0.5));
0064
0065 }
0066
0067 void EpFinder::Finish(){
0068
0069 mCorrectionInputFile->Close();
0070
0071 mPhiWeightOutput->Divide(mPhiAveraged);
0072 delete mPhiAveraged;
0073
0074 mCorrectionOutputFile->Write();
0075 mCorrectionOutputFile->Close();
0076
0077 cout << "EpFinder is finished!\n\n";
0078 }
0079
0080
0081 EpInfo EpFinder::Results(std::vector<EpHit> *EpdHits, int EventTypeId){
0082
0083 if ((EventTypeId<0)||(EventTypeId>=mNumberOfEventTypeBins)){
0084 cout << "You are asking for an undefined EventType - fail!\n";
0085 assert(0);
0086 }
0087
0088 EpInfo result;
0089
0090 double pi = TMath::Pi();
0091
0092
0093 double TotalWeight4Side[_EpOrderMax][2];
0094 for (int phiWeightedOrNo=0; phiWeightedOrNo<2; phiWeightedOrNo++){
0095 for (int order=1; order<_EpOrderMax+1; order++){
0096 TotalWeight4Side[order-1][phiWeightedOrNo] = 0;
0097 }
0098 }
0099
0100
0101 for (unsigned int hit=0; hit<EpdHits->size(); hit++){
0102
0103 float nMip = EpdHits->at(hit).nMip;
0104 if (nMip<mThresh) continue;
0105 double TileWeight = (nMip<mMax)?nMip:mMax;
0106 int idx_x = EpdHits->at(hit).ix;
0107 int idx_y = EpdHits->at(hit).iy;
0108 double phi = EpdHits->at(hit).phi;
0109
0110
0111
0112
0113
0114
0115 if(EpdHits->at(hit).samePhi){
0116 mPhiWeightOutput->Fill(idx_x,idx_y,TileWeight);
0117 for(unsigned int i = 0; i<EpdHits->at(hit).samePhi->size(); i++){
0118 float x = EpdHits->at(hit).samePhi->at(i).first;
0119 float y = EpdHits->at(hit).samePhi->at(i).second;
0120 mPhiAveraged->Fill(x,y,TileWeight/EpdHits->at(hit).samePhi->size());
0121 }
0122 }
0123
0124
0125
0126
0127
0128 double PhiWeightedTileWeight = TileWeight;
0129 if (mPhiWeightInput) PhiWeightedTileWeight /= mPhiWeightInput->GetBinContent(idx_x+1,idx_y+1);
0130
0131 for (int order=1; order<_EpOrderMax+1; order++){
0132 double etaWeight = 1.0;
0133 TotalWeight4Side[order-1][0] += fabs(etaWeight) * TileWeight;
0134 TotalWeight4Side[order-1][1] += fabs(etaWeight) * PhiWeightedTileWeight;
0135
0136 double Cosine = cos(phi*(double)order);
0137 double Sine = sin(phi*(double)order);
0138
0139 result.QrawOneSide[order-1][0] += etaWeight * TileWeight * Cosine;
0140 result.QrawOneSide[order-1][1] += etaWeight * TileWeight * Sine;
0141
0142 result.QphiWeightedOneSide[order-1][0] += etaWeight * PhiWeightedTileWeight * Cosine;
0143 result.QphiWeightedOneSide[order-1][1] += etaWeight * PhiWeightedTileWeight * Sine;
0144
0145 }
0146 }
0147
0148
0149
0150
0151 for (int order=1; order<_EpOrderMax+1; order++){
0152 result.WheelSumWeightsRaw[order-1] = TotalWeight4Side[order-1][0];
0153 result.WheelSumWeightsPhiWeighted[order-1] = TotalWeight4Side[order-1][1];
0154 }
0155
0156
0157
0158
0159 for (int order=1; order<_EpOrderMax+1; order++){
0160 if (TotalWeight4Side[order-1][0]>0.0001){
0161 result.QrawOneSide[order-1][0] /= TotalWeight4Side[order-1][0];
0162 result.QrawOneSide[order-1][1] /= TotalWeight4Side[order-1][0];
0163 }
0164 if (TotalWeight4Side[order-1][1]>0.0001){
0165 result.QphiWeightedOneSide[order-1][0] /= TotalWeight4Side[order-1][1];
0166 result.QphiWeightedOneSide[order-1][1] /= TotalWeight4Side[order-1][1];
0167 }
0168 }
0169
0170
0171
0172
0173
0174
0175 for (int order=1; order<_EpOrderMax+1; order++){
0176 result.PsiRaw[order-1] = GetPsiInRange(result.QrawOneSide[order-1][0],result.QrawOneSide[order-1][1],order);
0177 result.PsiPhiWeighted[order-1] = GetPsiInRange(result.QphiWeightedOneSide[order-1][0],result.QphiWeightedOneSide[order-1][1],order);
0178 }
0179
0180
0181
0182
0183 for (int order=1; order<_EpOrderMax+1; order++){
0184 result.PsiPhiWeightedAndShifted[order-1] = result.PsiPhiWeighted[order-1];
0185 if (mEpShiftInput_sin[order-1]) {
0186 for (int i=1; i<=_EpTermsMax; i++){
0187 double tmp = (double)(order*i);
0188 double sinAve = mEpShiftInput_sin[order-1]->GetBinContent(i,EventTypeId+1);
0189 double cosAve = mEpShiftInput_cos[order-1]->GetBinContent(i,EventTypeId+1);
0190 result.PsiPhiWeightedAndShifted[order-1] +=
0191 2.0*(cosAve*sin(tmp*result.PsiPhiWeighted[order-1]) - sinAve*cos(tmp*result.PsiPhiWeighted[order-1]))/tmp;
0192 }
0193 double AngleWrapAround = 2.0*pi/(double)order;
0194 if (result.PsiPhiWeightedAndShifted[order-1]<0) result.PsiPhiWeightedAndShifted[order-1] += AngleWrapAround;
0195 else if (result.PsiPhiWeightedAndShifted[order-1]>AngleWrapAround) result.PsiPhiWeightedAndShifted[order-1] -= AngleWrapAround;
0196 }
0197 }
0198
0199
0200
0201
0202 for (int i=1; i<=_EpTermsMax; i++){
0203 for (int order=1; order<_EpOrderMax+1; order++){
0204 double tmp = (double)(order*i);
0205 mEpShiftOutput_sin[order-1]->Fill(i,EventTypeId,sin(tmp*result.PsiPhiWeighted[order-1]));
0206 mEpShiftOutput_cos[order-1]->Fill(i,EventTypeId,cos(tmp*result.PsiPhiWeighted[order-1]));
0207 }
0208 }
0209
0210 return result;
0211 }
0212
0213 double EpFinder::GetPsiInRange(double Qx, double Qy, int order){
0214 double temp;
0215 if ((Qx==0.0)||(Qy==0.0)) temp=-999;
0216 else{
0217 temp = atan2(Qy,Qx)/((double)order);
0218 double AngleWrapAround = 2.0*TMath::Pi()/(double)order;
0219 if (temp<0.0) temp+= AngleWrapAround;
0220 else if (temp>AngleWrapAround) temp -= AngleWrapAround;
0221 }
0222 return temp;
0223 }
0224
0225 bool EpFinder::OrderOutsideRange(int order){
0226 if (order < 1) {
0227 cout << "\n*** Invalid order specified ***\n";
0228 cout << "order must be 1 (for first-order plane) or higher\n";
0229 return true;
0230 }
0231 if (order > _EpOrderMax) {
0232 cout << "\n*** Invalid order specified ***\n";
0233 cout << "Maximum order=" << _EpOrderMax << ". To change, edit StEpdUtil/StEpdEpInfo.h\n";
0234 return true;
0235 }
0236 return false;
0237 }
0238
0239 TString EpFinder::Report(){
0240 TString rep = Form("This is the EpFinder Report:\n");
0241 rep += Form("Number of EventType bins = %d\n",mNumberOfEventTypeBins);
0242 rep += Form("Threshold (in MipMPV units) = %f and MAX weight = %f\n",mThresh,mMax);
0243 return rep;
0244 }
0245