StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StEmcOfflineCalibrationElectronAnalysis.cxx
1 /*
2  * StEmcOfflineCalibrationElectronAnalysis.cxx
3  * J. Kevin Adkins, University of Kentucky
4  * June 24, 2014
5  *
6  * This will combine old methods for creating
7  * ring, crate, and crateslice E/p histograms
8  * for the BEMC absolute calibration.
9  */
10 
11 // User defined includes
12 #include "StEmcOfflineCalibrationElectronAnalysis.h"
13 #include "StEmcOfflineCalibrationEvent.h"
14 
15 // STD includes
16 #include <map>
17 #include <set>
18 #include <stdio.h>
19 #include <math.h>
20 #include <fstream>
21 
22 // ROOT includes
23 #include "TH1D.h"
24 #include "TH2F.h"
25 #include "TF1.h"
26 #include "TFile.h"
27 #include "TChain.h"
28 #include "TString.h"
29 
30 // StRoot includes
31 #include "StEmcRawMaker/defines.h"
32 #include "StEmcUtil/geometry/StEmcGeom.h"
33 #include "StEmcUtil/database/StEmcDecoder.h"
34 #include "StEmcUtil/database/StBemcTables.h"
35 #include "StEmcADCtoEMaker/StEmcADCtoEMaker.h"
36 #include "StEmcADCtoEMaker/StBemcData.h"
37 
39 
40 StEmcOfflineCalibrationElectronAnalysis::StEmcOfflineCalibrationElectronAnalysis(const char *name, const char* outfile, const char* mipFilename, const char* geantFilename, TChain *calibChain):StMaker(name){
41  mCalibChain = calibChain;
42  mOutfileName = (TString)outfile;
43  mipGainFilename = (TString)mipFilename;
44  mGeantFilename = (TString)geantFilename;
45  mFile = 0; mGeantFile = 0; mEvent = 0; mVertex = 0; mTrack = 0; mCluster = 0;
46  mBHT0 = mBHT1 = mBHT2 = 0;
47  mEmcGeom = 0; mEmcAdcToE = 0; mBemcTables = 0; mEmcDecoder = 0;
48 }
49 
50 StEmcOfflineCalibrationElectronAnalysis::~StEmcOfflineCalibrationElectronAnalysis()
51 {
52  if (mCalibChain) delete mCalibChain; if (mFile) delete mFile; if (mGeantFile) delete mGeantFile;
53  if (mEvent) delete mEvent; if (mTrack) delete mTrack; if (mVertex) delete mVertex; if (mCluster) delete mCluster;
54  if (mBHT0) delete mBHT0; if (mBHT1) delete mBHT1; if (mBHT2) delete mBHT2;
55  if (mEmcGeom) delete mEmcGeom; if (mEmcAdcToE) delete mEmcAdcToE;
56  if (mBemcTables) delete mBemcTables; if (mEmcDecoder) delete mEmcDecoder;
57 }
58 
59 Int_t StEmcOfflineCalibrationElectronAnalysis::Init()
60 {
61  pi = TMath::Pi();
62  nTowers = 4800;
63  nRings = 40;
64  nCrates = 30;
65  nSlices = 20;
66  nGoodElectrons = 0;
67  mCalibChain->SetBranchAddress("event_branch",&mEvent);
68  mCluster = new StEmcOfflineCalibrationCluster();
69  mEmcGeom = StEmcGeom::instance("bemc");
70  mEmcAdcToE = static_cast<StEmcADCtoEMaker*>(this->GetMakerInheritsFrom("StEmcADCtoEMaker"));
71  mBemcTables = mEmcAdcToE->getBemcData()->getTables();
72  mEmcDecoder = mBemcTables->getDecoder();
73 
74  // Geant file and fits;
75  mGeantFile = new TFile(mGeantFilename);
76  Char_t fitName[100];
77  for (Int_t iFit = 0; iFit < 20; ++iFit){
78  sprintf(fitName,"fit_%i",iFit);
79  mGeantFits[iFit] = (TF1*)mGeantFile->Get(fitName);
80  }
81 
82  // Read in mip gains, errors, and statuses.
83  // Gainfile should be packaged with sandbox
84  ifstream mipGainFile(mipGainFilename,ifstream::in);
85  if (!mipGainFile.is_open()){
86  cout << "Cannot open the gainfile" << endl;
87  exit(1);
88  }
89 
90  while(1){
91  Int_t softId, towerStat;
92  Float_t mipAdc, mipAdcErr, mipGain, towEta, towTheta;
93  mipGainFile >> softId >> mipAdc >> mipAdcErr >> towerStat;
94  if(!mipGainFile.good())break;
95  mEmcGeom->getEta(softId, towEta);
96  mEmcGeom->getTheta(softId, towTheta);
97  mipGain = 0.264*(1+0.056*towEta*towEta)/(sin(towTheta)*mipAdc);
98  mipGains[softId-1] = mipGain;
99  mipStatus[softId-1] = towerStat;
100  }
101  mipGainFile.close();
102 
103  // Create TFile and initialize histograms afterwards so we may use only one TFile::Write() command
104  mFile = new TFile(mOutfileName, "RECREATE");
105 
106  Char_t ringName[100], cratesliceName[100];
107  Char_t ringTitle[200], cratesliceTitle[200];
108 
109  for (Int_t iRing = 0; iRing < nRings; ++iRing){
110  Int_t ringId = iRing+1;
111  sprintf(ringName,"ringHisto_%i",ringId);
112  sprintf(ringTitle,"Ring %i E/p",ringId);
113  ringHisto[iRing] = new TH1D(ringName,ringTitle, 60, 0., 3.);
114  ringHisto[iRing]->Sumw2();
115 
116  sprintf(ringName,"ringHisto_Unbiased_%i",ringId);
117  sprintf(ringTitle,"Ring %i E/p",ringId);
118  ringHisto_Unbiased[iRing] = new TH1D(ringName,ringTitle, 60, 0., 3.);
119  ringHisto_Unbiased[iRing]->Sumw2();
120 
121  sprintf(ringName,"ringHisto_HT_%i",ringId);
122  sprintf(ringTitle,"Ring %i E/p",ringId);
123  ringHisto_HT[iRing] = new TH1D(ringName,ringTitle, 60, 0., 3.);
124  ringHisto_HT[iRing]->Sumw2();
125  }
126 
127  // Initialize crate-slice E/p histograms
128  for (Int_t iCrate = 0; iCrate < nCrates; ++iCrate){
129  Int_t crateId = iCrate+1;
130  for (Int_t iSlice = 0; iSlice < nSlices; ++iSlice){
131  Int_t sliceId = iSlice+1;
132  sprintf(cratesliceName,"cratesliceHisto_%i_%i",crateId,sliceId);
133  sprintf(cratesliceTitle,"Crate Slice %i_%i E/p",crateId,sliceId);
134  cratesliceHisto[iCrate][iSlice] = new TH1D(cratesliceName, cratesliceTitle, 60, 0., 3.);
135  cratesliceHisto[iCrate][iSlice]->Sumw2();
136  }
137  }
138 
139  return StMaker::Init();
140 }
141 
143 {
144  // Get triggers for this event
145  mBHT0 = mEvent->trigger(370501);
146  mBHT1 = mEvent->trigger(370511);
147  if (mEvent->trigger(370531))
148  mBHT2 = mEvent->trigger(370531);
149  else if (mEvent->trigger(370521))
150  mBHT2 = mEvent->trigger(370521);
151  else
152  mBHT2 = mEvent->trigger(370522);
153 
154  // Get towers above HT threshold depending on which trigger fired
155  towersAboveTh0.clear(); towersAboveTh1.clear(); towersAboveTh2.clear();
156  towersAboveTh0 = mEvent->towersAboveHighTowerTh(0);
157  towersAboveTh1 = mEvent->towersAboveHighTowerTh(1);
158  towersAboveTh2 = mEvent->towersAboveHighTowerTh(2);
159 
160  // Loop through tracks to get excluded towers
161  includedTowers.clear();
162  excludedTowers.clear();
163 
164  // Loop over tracks to get excluded towers
165  for (Int_t iTrk = 0; iTrk < mEvent->nTracks(); ++iTrk){
166  mTrack = mEvent->track(iTrk);
167  Int_t softId = mTrack->towerId(0);
168 
169  if(includedTowers.find(softId) != includedTowers.end())
170  excludedTowers.insert(softId);
171  else
172  includedTowers.insert(softId);
173  }
174 
175  //Begin loop through vertices
176  for (Int_t iVertex = 0; iVertex < mEvent->nVertices(); ++iVertex){
177  mVertex = mEvent->vertex(iVertex);
178 
179  if (mVertex->ranking() < 1e6) continue;
180  if (fabs(mVertex->z()) > 60) continue;
181 
182  // Loop through tracks at vertex
183  for (Int_t iTrack = 0; iTrack < mVertex->nTracks(); ++iTrack){
184  mTrack = mVertex->track(iTrack);
185  /****************************************** Set some track variables ******************************************/
186  towerEta = towerPhi = towerTheta = 0.;
187  trackEta = trackPhi = towerTrackDr = trackEnergy = trackP = 0.;
188  geantScale = 0.;
189  towerCrate = towerSequence = ringIndex = sliceEtaIndex = 0;
190  softId = mTrack->towerId(0);
191  mEmcGeom->getEta(softId,towerEta);
192  mEmcGeom->getPhi(softId,towerPhi);
193  if (fabs(towerEta) > 0.965) // Outer tower Eta is 0.967, bump this up to 0.975 for calculating ringIndex correctly
194  towerEta += 0.008*fabs(towerEta)/towerEta;
195  mEmcDecoder->GetCrateFromTowerId(softId,towerCrate,towerSequence);
196  trackEta = mTrack->eta();
197  trackPhi = mTrack->phi();
198  trackP = mTrack->p();
199  trackEnergy = (mTrack->towerAdc(0) - mTrack->towerPedestal(0))*mipGains[softId-1];
200  towerTrackDr = sqrt(mTrack->deta()*mTrack->deta() + mTrack->dphi()*mTrack->dphi());
201  ringIndex = (TMath::Nint(towerEta*1000.) + 25)/50 + 19; // Ring index for eta rings
202  sliceEtaIndex = (TMath::Nint(fabs(towerEta)*1000.) + 25)/50 - 1; // For getting crateslice array index
203  geantScale = mGeantFits[sliceEtaIndex]->Eval(towerTrackDr);
204  trackEnergy /= geantScale;
205  if (sliceEtaIndex == 19)
206  towerTrackDr *= 0.025/0.017;
207  /**************************************************************************************************************/
208 
209  // Track cuts
210  if (mTrack->p() < 1.5 || mTrack->p() > 10.) continue;
211  if (mTrack->towerStatus(0) != 1) continue;
212  if (mipStatus[softId-1] != 1) continue;
213  if (mTrack->nHits() < 10) continue;
214  if (excludedTowers.find(softId) != excludedTowers.end()) continue;
215  if (mTrack->towerId(0) != mTrack->towerExitId()) continue;
216  if ((mTrack->towerAdc(0) - mTrack->towerPedestal(0)) < 2.5*mTrack->towerPedestalRms(0)) continue;
217  if (mTrack->dEdx() < 3.5e-6 || mTrack->dEdx() > 5.0e-6) continue;
218  if (mTrack->nSigmaElectron() < -1. || mTrack->nSigmaElectron() > 2.) continue;
219  if (mTrack->nSigmaPion() > -1. && mTrack->nSigmaPion() < 2.5) continue;
220  if (towerTrackDr > 0.02) continue;
221 
222  // The following line matches a track to the tower which fired the HT trigger. It's left in as an example, but not used for 2012 pp200 calibration
223  //if ((triggerFire(mBHT0) && trackPointsToHT(towersAboveTh0,softId)) || (triggerFire(mBHT1) && trackPointsToHT(towersAboveTh1,softId)) || (triggerFire(mBHT2) && trackPointsToHT(towersAboveTh2,softId))) continue;
224 
225  // Clear and form cluster around this track
226  mCluster->Clear();
227  mCluster->setCentralTrack(mTrack);
228  for (Int_t iNbr = 1; iNbr < 9; ++iNbr){
229  if (includedTowers.find(mTrack->towerId(iNbr)) == includedTowers.end()) continue;
230  for (Int_t aTrk = 0; aTrk < mEvent->nTracks(); ++aTrk){
231  if (aTrk == iTrack) continue;
232  StEmcOfflineCalibrationTrack *nbrTrack = mEvent->track(aTrk);
233  if (nbrTrack->towerId(0) == mTrack->towerId(iNbr))
234  mCluster->addNeighborTrack(nbrTrack);
235  }
236  }
237  if (mCluster->numberOfNeighborTracks() > 0) continue;
238 
239  // Check that maxEt
240  maxClusterEt = 0.;
241  maxClusterId = 0;
242  for (Int_t clustId = 0; clustId < 9; ++clustId){
243  if ((mTrack->towerAdc(clustId) - mTrack->towerPedestal(clustId)) < 0) continue;
244  if (mTrack->towerId(clustId) == 0) continue;
245  mEmcGeom->getTheta(mTrack->towerId(clustId),towerTheta);
246  Float_t holdEt = (mTrack->towerAdc(clustId) - mTrack->towerPedestal(clustId))*mipGains[mTrack->towerId(clustId)-1]*sin(towerTheta);
247  if (holdEt > maxClusterEt){
248  maxClusterEt = holdEt;
249  maxClusterId = clustId;
250  }
251  }
252  if (maxClusterId != 0) continue;
253  nGoodElectrons++;
254 
255  // Only use unbiased for inner eta rings (use sliceEtaIndex to define)
256  if (sliceEtaIndex <= 12 && trackP < 5. && (((!mBHT0 && !mBHT1 && !mBHT2) || (mBHT0 && !mBHT0->didFire()) || (mBHT1 && !mBHT1->didFire()) || (mBHT2 && !mBHT2->didFire())))){
257  ringHisto[ringIndex]->Fill(trackEnergy/trackP);
258  cratesliceHisto[towerCrate-1][sliceEtaIndex]->Fill(trackEnergy/trackP);
259  }
260  // Use BHT2 triggers for ALL rings if track momentum greater than 5 GeV
261  else if (trackP > 5. && !triggerFire(mBHT0) && !triggerFire(mBHT1) && triggerFire(mBHT2)){
262  ringHisto[ringIndex]->Fill(trackEnergy/trackP);
263  cratesliceHisto[towerCrate-1][sliceEtaIndex]->Fill(trackEnergy/trackP);
264  }
265 
266  // QA histograms for ALL eta ring slices
267  if (trackP < 5. && (((!mBHT0 && !mBHT1 && !mBHT2) || (mBHT0 && !mBHT0->didFire()) || (mBHT1 && !mBHT1->didFire()) || (mBHT2 && !mBHT2->didFire())))){
268  ringHisto_Unbiased[ringIndex]->Fill(trackEnergy/trackP);
269  }
270  if (trackP > 5. && !triggerFire(mBHT0) && !triggerFire(mBHT1) && triggerFire(mBHT2)){
271  ringHisto_HT[ringIndex]->Fill(trackEnergy/trackP);
272  }
273  }// Tracks Loop
274  }// Vertex Loop
275 
276  return kStOK;
277 }
278 
280 {
281  cout << "Added " << nGoodElectrons << " electrons to the calibration histograms" << endl;
282  mFile->Write(); mFile->Close(); delete mFile;
283  mGeantFile->Close(); delete mGeantFile;
284  return kStOk;
285 }
286 
287 Bool_t StEmcOfflineCalibrationElectronAnalysis::triggerFire(StEmcOfflineCalibrationTrigger *trig)
288 {
289  return trig && trig->didFire() && trig->shouldFire();
290 }
291 
292 Bool_t StEmcOfflineCalibrationElectronAnalysis::trackPointsToHT(const map<Int_t,Int_t>& highTowers, Int_t towId)
293 {
294  for (map<Int_t,Int_t>::const_iterator it = highTowers.begin(); it != highTowers.end(); ++it){
295  if (towId == it->first)
296  return true;
297  }
298 
299  return false;
300 }
StBemcData * getBemcData()
Return the StBemcData pointer.
StBemcTables * getTables()
Return the StBemcTable pointer.
Definition: StBemcRaw.h:207
int GetCrateFromTowerId(int softId, int &crate, int &sequence) const
Get crate number and position in crate for Software Id.
Definition: Stypes.h:40
StEmcDecoder * getDecoder()
Return pointer to decoder.
Definition: StBemcTables.h:137
Definition: Stypes.h:41