Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DEventProcessor_rho_p_hists.cc
Go to the documentation of this file.
1 // $Id: DEventProcessor_rho_p_hists.cc 1816 2006-06-06 14:38:18Z davidl $
2 //
3 // File: DEventProcessor_rho_p_hists.cc
4 // Created: Thur Jan 11 15:42:21 EDT 2005
5 // Creator: davidl
6 //
7 
8 #include <iostream>
9 #include <cmath>
10 using namespace std;
11 
12 #include <TThread.h>
13 #include <TDirectoryFile.h>
14 #include <TLorentzVector.h>
15 
16 #include <JANA/JApplication.h>
17 #include <JANA/JEventLoop.h>
18 using namespace jana;
19 
20 #include <TRACKING/DMCThrown.h>
21 #include <PID/DKinematicData.h>
22 #include <PID/DParticle.h>
23 #include <PID/DPhoton.h>
24 #include <PID/DBeamPhoton.h>
25 
27 
28 //==========================================================================
29 // This file contains code for a plugin that will create a few histograms
30 // based on the reconstructed data. It can mainly serve as an example
31 // of how one could access the reconstructed data in their own analysis
32 // program.
33 //
34 // Histograms are created in the init() method and they are filled in
35 // the evnt() method.
36 //==========================================================================
37 
38 // Routine used to create our JEventProcessor
39 extern "C"{
40 void InitPlugin(JApplication *app){
41  InitJANAPlugin(app);
42  app->AddProcessor(new DEventProcessor_rho_p_hists());
43 }
44 }
45 
46 
47 //------------------
48 // init
49 //------------------
51 {
52  // Create histograms
53  mm_gp_to_pX = new TH1D("mm_gp_to_pX","Missing mass from #gamma p -> p X",4001, 0.0, 4.0);
54  mm_gp_to_pX->SetXTitle("Missing mass (GeV)");
55  mm_gp_to_pX_thrown = (TH1D*)mm_gp_to_pX->Clone("mm_gp_to_pX_thrown");
56 
57  t_pX = new TH1D("t_pX","-t for #gammap->pX",20, 0.0, 6.0);
58  t_pX->SetXTitle("-t (GeV)");
59 
60  sqrt_s = new TH1D("sqrt_s","Center of mass energy #sqrt{s}",2001, 0.0, 6.0);
61  sqrt_s->SetXTitle("#sqrt{s} C.M. energy (GeV)");
62 
63  // Create tree
64  evt = new Event();
65  tree = new TTree("t", "#rho p events");
66  tree->Branch("E",&evt);
67 
68  pthread_mutex_init(&mutex, NULL);
69 
70  return NOERROR;
71 }
72 
73 //------------------
74 // evnt
75 //------------------
76 jerror_t DEventProcessor_rho_p_hists::evnt(JEventLoop *loop, uint64_t eventnumber)
77 {
78  // Get reconstructed objects
79  vector<const DBeamPhoton*> beam_photons;
80  vector<const DParticle*> particles;
81  vector<const DParticle*> particles_thrown;
82 
83  loop->Get(beam_photons); // from truth info
84  loop->Get(particles); // all reconstructed charged (CDC and FDC)
85  loop->Get(particles_thrown, "THROWN"); // all thrown charged (CDC and FDC)
86 
87  // Target is proton at rest in lab frame
88  TLorentzVector target(0.0, 0.0, 0.0, 0.93827);
89 
90  // Create TLorentzVectors for reconstructed charged particles
91  vector<TLorentzVector> rec_piplus;
92  vector<TLorentzVector> rec_piminus;
93  vector<TLorentzVector> rec_protons;
94  SortChargedParticles(particles, rec_piplus, rec_piminus, rec_protons);
95 
96  // Create TLorentzVectors for thrown charged particles
97  vector<TLorentzVector> thrown_piplus;
98  vector<TLorentzVector> thrown_piminus;
99  vector<TLorentzVector> thrown_protons;
100  SortChargedParticles(particles_thrown, thrown_piplus, thrown_piminus, thrown_protons);
101 
102  // Some generators don't supply information on the beam photon. If there
103  // are no DBeamPhoton objects, then create a 9GeV one here
104  if(beam_photons.size()==0){
105  DBeamPhoton beam;
106  DVector3 mom(0.0, 0.0, 9.0);
107  DVector3 pos(0.0, 0.0, 65.0); // center of target
108  beam.setMomentum(mom);
109  beam.setPosition(pos);
110  beam.setMass(0.0);
111  beam.setCharge(0.0);
112  beam_photons.push_back(&beam);
113  }
114 
115  //--------------------------------------------------------------------
116  // Fill histograms below here using values in the rec_XXX containers.
117 
118  // Although we are only filling objects local to this plugin, TTree::Fill() periodically writes to file: Global ROOT lock
119  japp->RootWriteLock(); //ACQUIRE ROOT LOCK
120 
121  evt->Clear();
122  evt->event = eventnumber;
123 
124  // Loop over beam photons and fill histos for each "tagged" photon for this event
125  for(unsigned int i=0; i<beam_photons.size(); i++){
126 
127  // Make TLorentzVector for beam photon
128  TLorentzVector beam_photon = MakeTLorentz(beam_photons[i], 0.0);
129  evt->beam = beam_photon;
130 
131  // Center of mass energy
132  sqrt_s->Fill((beam_photon+target).M()); // Fill Center of Mass energy histo
133 
134  // Missing mass from gamma + p -> p + X
135  if(rec_protons.size()==1){
136  TLorentzVector missing = beam_photon + target - rec_protons[0];
137  mm_gp_to_pX->Fill(missing.M());
138  }
139 
140  // Missing mass from gamma + p -> p + X
141  if(thrown_protons.size()==1){
142  TLorentzVector missing = beam_photon + target - thrown_protons[0];
143  mm_gp_to_pX_thrown->Fill(missing.M());
144  }
145 
146  } // beam_photons
147 
148 
149  //-------------------------------------------------------------------
150  // Below here are the histos that do not depend on the tagged photon
151  // energy and so should be filled outside of the above loop.
152 
153  // We are only interested in single rho events so return now if there
154  // are not exactly one thrown pi+ and one thrown pi-
155  if(thrown_piplus.size()!=1)
156  {
157  japp->RootUnLock(); //RELEASE ROOT LOCK
158  return NOERROR;
159  }
160  if(thrown_piminus.size()!=1)
161  {
162  japp->RootUnLock(); //RELEASE ROOT LOCK
163  return NOERROR;
164  }
165 
166  // Determine whether both thrown pions are fiducial
167  evt->rho_thrown.isfiducial = IsFiducial(thrown_piplus[0]) && IsFiducial(thrown_piminus[0]);
168 
169  // Thrown pion parameters
170  evt->rho_thrown.pip = thrown_piplus[0];
171  evt->rho_thrown.pim = thrown_piminus[0];
172  evt->rho_thrown.m = (evt->rho_thrown.pip+evt->rho_thrown.pim).M();
173 
174  // pi+, pi- invariant mass. Loop over all possible combinations
175  for(unsigned int j=0; j<rec_piplus.size(); j++){
176  for(unsigned int k=0; k<rec_piminus.size(); k++){
177  evt->AddRho(rec_piplus[j], rec_piminus[k]);
178  }
179  }
180 
181  // Thrown proton
182  if(thrown_protons.size()==1)evt->proton_thrown = thrown_protons[0];
183 
184  // Calculate Mandelstam t=(p1-p3)^2
185  if(rec_protons.size()==1){
186  TLorentzVector beam_photon = beam_photons.size()>0 ? MakeTLorentz(beam_photons[0], 0.0):TLorentzVector(0.0, 0.0, 0.0, 9.0);
187  TLorentzVector &proton = rec_protons[0];
188  TLorentzVector p3 = beam_photon + target - proton;
189  double t = (beam_photon - p3).Mag2();
190  t_pX->Fill(-t);
191  }
192 
193  // Fill tree
194  evt->rho->Sort(); // sort by closeness of invariant mass to 770MeV/c^2 (uses rho_t::Compare );
195  tree->Fill();
196 
197  japp->RootUnLock(); //RELEASE ROOT LOCK
198 
199  return NOERROR;
200 }
201 
202 //------------------
203 // SortChargedParticles
204 //------------------
205 void DEventProcessor_rho_p_hists::SortChargedParticles(vector<const DParticle*> &particles, vector<TLorentzVector> &rec_piplus, vector<TLorentzVector> &rec_piminus, vector<TLorentzVector> &rec_protons)
206 {
207 
208  // Loop over charged particles turning them into TLorentzVector objects
209  // and sorting them into various containers declared just above.
210  for(unsigned int j=0; j<particles.size(); j++){
211  const DParticle *part = particles[j];
212 
213  // If this came from the HDParSim factory it will have a DMCThrown object
214  // associated with it that we can use to get the particle type since
215  // we currently don't have that info in reconstruction. If it is not there,
216  // then assume it's a pion.
217  int type = part->charge()<0.0 ? 9:8; // initialize to pi-(=9) or pi+(=8)
218 
219  // Here we try and get the "truth" object DMCThrown. The access mechanism
220  // forces us to get it as a list, but there should be at most 1.
221  vector<const DMCThrown*> throwns;
222  part->Get(throwns);
223  // if DMCThrown was found, overwrite pion with actual particle type
224  if(throwns.size()>0)type = throwns[0]->type;
225 
226  // Add TLorentzVector to appropriate container based on charged particle type
227  switch(type){
228  case 8: rec_piplus.push_back(MakeTLorentz(part, 0.13957)); break;
229  case 9: rec_piminus.push_back(MakeTLorentz(part, 0.13957)); break;
230  case 14: rec_protons.push_back(MakeTLorentz(part, 0.93827)); break;
231  }
232  } // particles
233 }
234 
235 //------------------
236 // MakeTLorentz
237 //------------------
238 TLorentzVector DEventProcessor_rho_p_hists::MakeTLorentz(const DKinematicData *kd, double mass)
239 {
240  // Create a ROOT TLorentzVector object out of a Hall-D DKinematic Data object.
241  // Here, we have the mass passed in explicitly rather than use the mass contained in
242  // the DKinematicData object itself. This is because right now (Feb. 2009) the
243  // PID code is not mature enough to give reasonable guesses. See above code.
244 
245  double p = kd->momentum().Mag();
246  double theta = kd->momentum().Theta();
247  double phi = kd->momentum().Phi();
248  double px = p*sin(theta)*cos(phi);
249  double py = p*sin(theta)*sin(phi);
250  double pz = p*cos(theta);
251  double E = sqrt(mass*mass + p*p);
252 
253  return TLorentzVector(px,py,pz,E);
254 }
255 
256 //------------------
257 // IsFiducial
258 //------------------
259 bool DEventProcessor_rho_p_hists::IsFiducial(TLorentzVector &pion)
260 {
261  double theta = pion.Theta()*TMath::RadToDeg();
262  if(theta<2.0 || theta>110.0)return false;
263  if(pion.P()<0.500)return false;
264 
265  return true;
266 }
267 
268 //------------------
269 // erun
270 //------------------
272 {
273  return NOERROR;
274 }
275 
276 //------------------
277 // fini
278 //------------------
280 {
281  // Histograms are automatically written to file by hd_root program (or equivalent)
282  // so we don't need to do anything here.
283 
284  return NOERROR;
285 }
jerror_t fini(void)
Invoked via DEventProcessor virtual method.
void setMomentum(const DVector3 &aMomentum)
jerror_t init(void)
Invoked via DEventProcessor virtual method.
TVector3 DVector3
Definition: DVector3.h:14
JApplication * japp
jerror_t evnt(JEventLoop *loop, uint64_t eventnumber)
Invoked via DEventProcessor virtual method.
void SortChargedParticles(vector< const DParticle * > &particles, vector< TLorentzVector > &rec_piplus, vector< TLorentzVector > &rec_piminus, vector< TLorentzVector > &rec_protons)
InitPlugin_t InitPlugin
TH1D * py[NCHANNELS]
double sqrt(double)
double sin(double)
const DVector3 & momentum(void) const
jerror_t erun(void)
Invoked via DEventProcessor virtual method.
void setPosition(const DVector3 &aPosition)
bool IsFiducial(TLorentzVector &pion)
TLorentzVector MakeTLorentz(const DKinematicData *track, double mass)