Neutral Particle Spectrometer analysis code
Loading...
Searching...
No Matches
THcNPSSecondaryKine.cxx
Go to the documentation of this file.
1// THcNPSSecondaryKine
2//
3// This module is to calculate the kinematics
4// for NPS DVCS analysis using detected photon
5// instead of track info in THcSecondaryKine
6
7/*
8 NPS cluster positions are defined in the coordinate system
9 +x=horizontal,beam left, +y=up, z=along the central ray
10 where the origin is at (XFront=0, YFront=0, Z)
11 Note that it's not defined in transport coordinate system
12
13 To get the position in lab frame,
14 we just need to rotate along y (assume phi=0)
15
16 X_lab X_cls
17 Y_lab = (R_y) Y_cls
18 Z_lab Z_cls
19
20 R_y = cos(th) 0 sin(th)
21 0 1 0
22 -sin(th) 0 cos(th)
23
24 Vertex corrections:
25 X_lab_corr = X_lab - Vertex(X)
26 Y_lab_corr = Y_lab - Vertex(Y)
27 Z_lab_corr = Z_lab - Vertex(Z)
28 */
29
30#include "THcReactionPoint.h"
31#include "THcPrimaryKine.h"
32#include "THcNPSApparatus.h"
33#include "THcNPSCalorimeter.h"
34#include "THcNPSCluster.h"
35#include "THcNPSSecondaryKine.h"
36#include "THcGlobals.h"
37#include "THcParmList.h"
38#include "VarDef.h"
39#include "VarType.h"
40#include "TVector3.h"
41
42
43#include <iostream>
44
46
47//__________________________________________________________________
48THcNPSSecondaryKine::THcNPSSecondaryKine( const char* name, const char* description,
49 const char* secondary_spectro,
50 const char* primary_kine,
51 Double_t secondary_mass,
52 const char* vertex_module) :
53 THcSecondaryKine(name, description, secondary_spectro, primary_kine, secondary_mass),
54 fApparatName("NPS"),
55 fApparatus(nullptr),
56 fNPSCalo(nullptr),
57 fVertexModuleName(vertex_module),
58 fVertexModule(nullptr),
59 fNPSAngle(0)
60{
61 // Constructor
62}
63
64//__________________________________________________________________
69
70//__________________________________________________________________
72{
73
74 fStatus = kOK;
75
76 // NPS not HallC spectrometer, use THcApparatus instead
77 fApparatus = dynamic_cast<THcNPSApparatus*>
78 ( FindModule( fApparatName.Data(), "THcNPSApparatus"));
79 if(!fApparatus) {
81 return fStatus;
82 }
83
84 fPrimary = dynamic_cast<THcPrimaryKine*>
85 ( FindModule( fPrimaryName.Data(), "THcPrimaryKine"));
86 if(!fPrimary) {
88 return fStatus;
89 }
90
91 fVertexModule = dynamic_cast<THcReactionPoint*>
92 ( FindModule( fVertexModuleName.Data(), "THcReactionPoint"));
93 if(!fVertexModule) {
95 return fStatus;
96 }
97
98 // We get NPS Calorimeter cluster info from this
99 // std::cout << "Init THcNPSSecondaryKine: fApparatus->GetDetector("cal")" << std::endl;
100 fNPSCalo = dynamic_cast<THcNPSCalorimeter*>(fApparatus->GetDetector("cal"));
101
102 if( (fStatus=THaPhysicsModule::Init( run_time )) != kOK ) {
103 return fStatus;
104 }
105
106 return fStatus;
107
108}
109
110//__________________________________________________________________
112{
113
114 if( mode == kDefine && fIsSetup ) return kOK;
115 fIsSetup = ( mode == kDefine );
116
117 RVarDef vars[] = {
118 { "th_xq", "Polar angle of detected particle with q (rad)",
119 "fTheta_xq" },
120 { "ph_xq", "Azimuth of detected particle with scattering plane (rad)",
121 "fPhi_xq" },
122 { "th_bq", "Polar angle of recoil system with q (rad)", "fTheta_bq" },
123 { "ph_bq", "Azimuth of recoil system with scattering plane (rad)",
124 "fPhi_bq" },
125 { "xangle", "Angle of detected particle with scattered electron (rad)",
126 "fXangle" },
127 { "pmiss", "Missing momentum magnitude (GeV), nuclear physics "
128 "definition (-pB)", "fPmiss" },
129 { "pmiss_x", "x-component of p_miss wrt q (GeV)", "fPmiss_x" },
130 { "pmiss_y", "y-component of p_miss wrt q (GeV)", "fPmiss_y" },
131 { "pmiss_z", "z-component of p_miss, along q (GeV)", "fPmiss_z" },
132 { "emiss_nuc", "Missing energy (GeV), nuclear physics definition "
133 "omega-Tx-Tb", "fEmiss_nuc" },
134 { "emiss", "Missing energy (GeV), ENGINE definition "
135 "omega-Mt-Ex", "fEmiss" },
136 { "Mrecoil", "Invariant mass of recoil system (GeV)", "fMrecoil" },
137 { "Erecoil", "Total energy of recoil system (GeV)", "fErecoil" },
138 { "Prec_x", "x-component of recoil system in lab (GeV/c)", "fB.X()" },
139 { "Prec_y", "y-component of recoil system in lab (GeV/c)", "fB.Y()" },
140 { "Prec_z", "z-component of recoil system in lab (GeV/c)", "fB.Z()" },
141 { "tx", "Kinetic energy of detected particle (GeV)", "fTX" },
142 { "tb", "Kinetic energy of recoil system (GeV)", "fTB" },
143 { "px_cm", "Magnitude of X momentum in CM system (GeV)", "fPX_cm" },
144 { "thx_cm", "Polar angle of X in CM system wrt q (rad)", "fTheta_x_cm" },
145 { "phx_cm", "Azimuth of X in CM system wrt q (rad)", "fPhi_x_cm" },
146 { "thb_cm", "Polar angle of recoil systm in CM wrt q (rad)",
147 "fTheta_b_cm" },
148 { "phb_cm", "Azimuth of recoil system in CM wrt q (rad)", "fPhi_b_cm" },
149 { "tx_cm", "Kinetic energy of X in CM (GeV)", "fTX_cm" },
150 { "tb_cm", "Kinetic energy of B in CM (GeV)", "fTB_cm" },
151 { "t_tot_cm", "Total CM kinetic energy", "fTtot_cm" },
152 { "MandelS", "Mandelstam s for secondary vertex (GeV^2)", "fMandelS" },
153 { "MandelT", "Mandelstam t for secondary vertex (GeV^2)", "fMandelT" },
154 { "MandelU", "Mandelstam u for secondary vertex (GeV^2)", "fMandelU" },
155 { 0 }
156 };
157
158 return DefineVarsFromList( vars, mode );
159
160}
161
162//__________________________________________________________________
164{
165
166 // Calculate secondary kinematics for e+N --> e'+gamma+X
167 // Replace tracks with clusters for calculating secondary kinematics
168 // Rest is same as THcSecondaryKine::Process
169
170 if( !IsOK() ) return -1;
171
172 // Require valid input data
173 if( !fPrimary->DataValid() ) return 2;
174
175 // No valid cluster
176 if(fNPSCalo->GetNClusters() == 0) return 1;
177
178 // Find vertex using HMS
182 else
183 vertex.SetXYZ(0,0,0);
184
185 // Set photon 4-momentum in lab frame (z = beam, y = up)
186 //
187 // In case we have multi clusters we need to set criteria to choose "golden" cluster
188 // or calcualte kinematics for all identified clusters, store, use it as a cut
189 // For now, use a cluster with highest energy deposit
190 Double_t ClusterMaxE = 0;
191 TVector3 pvect;
192 for(auto& cluster : fNPSCalo->GetClusters())
193 if( cluster.E() > ClusterMaxE )
194 {
195 ClusterMaxE = cluster.E();
196 // vertex correction and get P vector
197 cluster.RotateToLab(fNPSAngle, vertex, pvect);
198 if( vertex.Mag() < 1.e-38 ) cluster.SetVertexFlag(false);
199 }
200
201 // 4-momentum of X
202 fX.SetVectM( pvect, fMX );
203
204 // 4-momenta of the the primary interaction
205 const TLorentzVector* pA = fPrimary->GetA(); // Initial target
206 const TLorentzVector* pA1 = fPrimary->GetA1(); // Final target, fA1 = fA + fQ
207 const TLorentzVector* pQ = fPrimary->GetQ(); // Momentum xfer
208 const TLorentzVector* pP1 = fPrimary->GetP1(); // Final electron
209 Double_t omega = fPrimary->GetOmega(); // Energy xfer
210
211 // 4-momentum of undetected recoil system B
212 fB = *pA1 - fX;
213
214 // Angle of X with scattered primary particle
215 fXangle = fX.Angle( pP1->Vect());
216
217 // Angles of X and B wrt q-vector
218 // xq and bq are the 3-momentum vectors of X and B expressed in
219 // the coordinate system where q is the z-axis and the x-axis
220 // lies in the scattering plane (defined by q and e') and points
221 // in the direction of e', so the out-of-plane angle lies within
222 // -90<phi_xq<90deg if X is detected on the downstream/forward side of q.
223 TRotation rot_to_q;
224 rot_to_q.SetZAxis( pQ->Vect(), pP1->Vect()).Invert();
225 TVector3 xq = fX.Vect();
226 TVector3 bq = fB.Vect();
227 xq *= rot_to_q;
228 bq *= rot_to_q;
229 fTheta_xq = xq.Theta(); //"theta_xq"
230 fPhi_xq = xq.Phi(); //"out-of-plane angle", "phi"
231 fTheta_bq = bq.Theta();
232 fPhi_bq = bq.Phi();
233
234 // Missing momentum and components wrt q-vector
235 // The definition of p_miss as the negative of the undetected recoil
236 // momentum is the standard nuclear physics convention.
237 TVector3 p_miss = -bq;
238 fPmiss = p_miss.Mag(); //=fB.P()
239 //The missing momentum components in the q coordinate system.
240 //FIXME: just store p_miss in member variable
241 fPmiss_x = p_miss.X();
242 fPmiss_y = p_miss.Y();
243 fPmiss_z = p_miss.Z();
244
245 // Invariant mass of the recoil system, a.k.a. "missing mass".
246 // This invariant mass equals MB(ground state) plus any excitation energy.
247 fMrecoil = fB.M();
248
249 // Kinetic energies of X and B
250 fTX = fX.E() - fMX;
251 fTB = fB.E() - fMrecoil;
252
253 // Standard nuclear physics definition of "missing energy":
254 // binding energy of X in the target (= removal energy of X).
255 // NB: If X is knocked out of a lower shell, the recoil system carries
256 // a significant excitation energy. This excitation is included in Emiss
257 // here, as it should, since it results from the binding of X.
258 fEmiss_nuc = omega - fTX - fTB;
259 // Target Mass + Beam Energy - scatt ele energy - hadron total energy
260 fEmiss = omega + pA->M() - fX.E();
261
262 // In production reactions, the "missing energy" is defined
263 // as the total energy of the undetected recoil system.
264 // This is the "missing mass", Mrecoil, plus any kinetic energy.
265 fErecoil = fB.E();
266
267 // Calculate some interesting quantities in the CM system of A'.
268 // NB: If the target is initially at rest, the A'-vector (spatial part)
269 // is the same as the q-vector, so we could just reuse the q rotation
270 // matrix. The following is completely general, i.e. allows for a moving
271 // target.
272
273 // Boost of the A' system.
274 // NB: ROOT's Boost() boosts particle to lab if the boost vector points
275 // along the particle's lab velocity, so we need the negative here to
276 // boost from the lab to the particle frame.
277 Double_t beta = pA1->P()/(pA1->E());
278 TVector3 boost(0.,0.,-beta);
279
280 // CM vectors of X and B.
281 // Express X and B in the frame where q is along the z-axis
282 // - the typical head-on collision picture.
283 TRotation rot_to_A1;
284 rot_to_A1.SetZAxis( pA1->Vect(), pP1->Vect()).Invert();
285 TVector3 x_cm_vect = fX.Vect();
286 x_cm_vect *= rot_to_A1;
287 TLorentzVector x_cm(x_cm_vect,fX.E());
288 x_cm.Boost(boost);
289 TLorentzVector b_cm(-x_cm.Vect(), pA1->E()-x_cm.E());
290 fPX_cm = x_cm.P();
291 // pB_cm, by construction, is the same as pX_cm.
292
293 // CM angles of X and B in the A' frame
294 fTheta_x_cm = x_cm.Theta();
295 fPhi_x_cm = x_cm.Phi();
296 fTheta_b_cm = b_cm.Theta();
297 fPhi_b_cm = b_cm.Phi();
298
299 // CM kinetic energies of X and B and total kinetic energy
300 fTX_cm = x_cm.E() - fMX;
301 fTB_cm = b_cm.E() - fMrecoil;
303
304 // Mandelstam variables for the secondary vertex.
305 // These variables are defined for the reaction gA->XB,
306 // where g is the virtual photon (with momentum q), and A, X, and B
307 // are as before.
308
309 fMandelS = (*pQ+*pA).M2();
310 fMandelT = (*pQ-fX).M2();
311 fMandelU = (*pQ-fB).M2();
312
313 fDataValid = true;
314 return 0;
315
316}
317
318//_____________________________________________________________________________
320{
321
322 // NPS angle
324
325 // cout << "In THcSecondaryKine::ReadDatabase() " << endl;
326
327 // Ignore prefix for now
328 /*
329 char prefix[2];
330 prefix[0] = tolower(GetName()[0]);
331 prefix[1] = '\0';
332 */
333 fOopCentralOffset = 0.0;
334 DBRequest list[]={
335 {"nps_oopcentral_offset",&fOopCentralOffset, kDouble, 0, 1},
336 {"ppartmass", &fMX, kDouble, 0, 1},
337 {0}
338 };
339
340 gHcParms->LoadParmValues((DBRequest*)&list,"");
341 cout << "THcSecondaryKine particleMASS: " << fMX << endl;
342
343 // default value
344 fMX = 0.0;
346
347 return kOK;
348}
349
350//_____________________________________________________________________________
351void THcNPSSecondaryKine::SetApparatus( const char* name )
352{
353 // this in fact sets the name of THcApparatus instead of Spectrometer
354 if( !IsInit() )
355 fApparatName = name;
356 else
357 PrintInitError("SetSpectroemter()");
358}
int Int_t
double Double_t
Option_t Option_t TPoint TPoint const char mode
ClassImp(VDC::AnalyticTTDConv) using namespace std
R__EXTERN class THcParmList * gHcParms
static Int_t DefineVarsFromList(const void *list, EType type, EMode mode, const char *def_prefix, const TObject *obj, const char *prefix, const char *here, const char *comment_subst="")
THaAnalysisObject * FindModule(const char *name, const char *classname, bool do_error=true)
Bool_t IsOK() const
Bool_t IsInit() const
virtual THaDetector * GetDetector(const char *name)
bool DataValid() const
void PrintInitError(const char *here)
virtual Bool_t HasVertex() const
virtual const TVector3 & GetVertex() const
A dummy spectrometer apparatus for testing detectors.
Double_t GetNPSAngle()
Generic segmented shower detector.
vector< THcNPSCluster > GetClusters()
THcNPSCalorimeter * fNPSCalo
virtual Int_t Process(const THaEvData &)
THcReactionPoint * fVertexModule
THcNPSApparatus * fApparatus
virtual Int_t DefineVariables(EMode mode=kDefine)
void SetApparatus(const char *name)
THcNPSSecondaryKine(const char *name, const char *description="", const char *secondary_spectro="", const char *primary_kine="", Double_t secondary_mass=0.0, const char *vertex_module="")
virtual Int_t ReadDatabase(const TDatime &date)
Int_t LoadParmValues(const DBRequest *list, const char *prefix="")
Double_t GetOmega() const
const FourVect * GetA1() const
const FourVect * GetQ() const
const FourVect * GetA() const
const FourVect * GetP1() const
THcPrimaryKine * fPrimary
Double_t fPhi_b_cm
Double_t fTheta_bq
TLorentzVector fB
Double_t fEmiss_nuc
Double_t fOopCentralOffset
TLorentzVector fX
Double_t fTheta_b_cm
Double_t fTheta_xq
Double_t fTheta_x_cm
Double_t fPhi_x_cm
TString fPrimaryName
Double_t Angle(const TVector3 &v) const
TVector3 Vect() const
Double_t M() const
Double_t P() const
void Boost(const TVector3 &)
Double_t Theta() const
Double_t Phi() const
Double_t E() const
void SetVectM(const TVector3 &spatial, Double_t mass)
TRotation & SetZAxis(const TVector3 &axis)
TRotation & Invert()
const char * Data() const
Double_t Z() const
void SetXYZ(Double_t x, Double_t y, Double_t z)
Double_t Phi() const
Double_t Y() const
Double_t X() const
Double_t Mag() const
Double_t Theta() const
double beta(double x, double y)
LVector boost(const LVector &v, const BoostVector &b)
int Invert(LASymMatrix &)
constexpr Double_t DegToRad()
double * vertex