9 #include <TStopwatch.h>
12 #if defined __ROOT_HAS_MATHMORE && ROOT_VERSION_CODE >= ROOT_VERSION(5,18,0)
13 #include <Math/Interpolator.h>
38 double P_MAX = 1180.0 *
Qw::MeV;
44 double Z_MAX = -630.0 *
Qw::cm;
45 double Z_MIN = -670.0 *
Qw::cm;
49 double R_MAX = 100.0 *
Qw::cm;
50 double R_MIN = 30.0 *
Qw::cm;
54 double PHI_MAX = 360.0 *
Qw::deg;
69 fMin.push_back(Z_MIN);
fMax.push_back(Z_MAX);
fStep.push_back(DZ);
70 fMin.push_back(PHI_MIN);
fMax.push_back(PHI_MAX);
fStep.push_back(DPHI);
71 fMin.push_back(R_MIN);
fMax.push_back(R_MAX);
fStep.push_back(DR);
72 fMin.push_back(P_MIN);
fMax.push_back(P_MAX);
fStep.push_back(DP);
93 #if ! defined __ROOT_HAS_MATHMORE || ROOT_VERSION_CODE < ROOT_VERSION(5,18,0)
97 QwWarning <<
"Without this support the faster momentum reconstruction method using "
98 <<
"a track look-up table will not work. The momentum reconstruction "
99 <<
"will always happen by slower swimming through the magnetic field."
101 QwWarning <<
"The necessary functionality is included in the ROOT MathMore plugin, "
102 <<
"which is included on JLab CUE2 systems in /apps/root/5.26-00."
104 QwWarning <<
"No momentum look-up table will be used for track reconstruction."
111 if (gSystem->AccessPathName(TString(filename))) {
114 QwWarning <<
"Without this file the faster momentum reconstruction method using "
115 <<
"a track look-up table will not work. The momentum reconstruction "
116 <<
"will always happen by slower swimming through the magnetic field."
118 QwWarning <<
"The necessary file is /group/qweak/QwAnalysis/datafiles/QwTrajMatrix.root"
120 QwWarning <<
"No momentum look-up table will be used for track reconstruction."
126 TFile* rootfile =
new TFile(TString(filename),
"read");
130 QwWarning <<
"No momentum look-up table will be used for track reconstruction."
137 TTree *momentum_tree = (TTree *)rootfile->Get(
"Momentum_Tree");
138 if (! momentum_tree) {
141 QwWarning <<
"No momentum look-up table will be used for track reconstruction."
153 Double_t back_position_r, back_position_phi;
154 Double_t back_direction_theta, back_direction_phi;
155 momentum_tree->SetBranchAddress(
"index", &index);
156 momentum_tree->SetBranchAddress(
"position_r", &back_position_r);
157 momentum_tree->SetBranchAddress(
"position_phi", &back_position_phi);
158 momentum_tree->SetBranchAddress(
"direction_theta", &back_direction_theta);
159 momentum_tree->SetBranchAddress(
"direction_phi", &back_direction_phi);
162 float value[4] = {0.0, 0.0, 0.0, 0.0};
165 Int_t numberOfEntries = momentum_tree->GetEntries();
166 for (Int_t i = 0; i < numberOfEntries; i++) {
169 momentum_tree->GetEntry(i);
172 value[0] = back_position_r;
173 value[1] = back_position_phi;
174 value[2] = back_direction_theta;
175 value[3] = back_direction_phi;
212 Double_t position_r,position_phi;
213 Double_t direction_theta,direction_phi;
218 double magneticfield_min = -250.0 *
Qw::cm;
219 double magneticfield_max = 250.0 *
Qw::cm;
222 TString rootfilename = TString(filename);
223 TFile* rootfile =
new TFile(rootfilename,
"RECREATE",
"Qweak momentum matrix");
226 TTree *momentum_tree =
new TTree(
"Momentum_Tree",
"momentum data tree");
229 momentum_tree->Branch(
"position_r", &position_r,
"position_r/D");
230 momentum_tree->Branch(
"position_phi", &position_phi,
"position_phi/D");
231 momentum_tree->Branch(
"direction_theta",&direction_theta,
"direction_theta/D");
232 momentum_tree->Branch(
"direction_phi",&direction_phi,
"direction_phi/D");
240 Double_t step = 1.0 *
Qw::cm;
243 double coord[4] = {0.0, 0.0, 0.0, 0.0};
244 double& z = coord[0];
245 double& phi = coord[1];
246 double& r = coord[2];
247 double& p = coord[3];
250 TVector3 position, direction;
262 direction.SetMagThetaPhi(1.0, theta, phi);
276 position_r = position.Perp();
277 position_phi = position.Phi();
278 if (position_phi < 0.0) position_phi += 2.0 *
Qw::pi;
279 direction_phi = direction.Phi();
280 if (direction_phi < 0.0) direction_phi += 2.0 *
Qw::pi;
281 direction_theta = direction.Theta();
284 float value[4] = {(float) position_r, (
float) position_phi, (float) direction_phi, (
float) direction_theta};
300 QwMessage <<
"CPU time used: " << timer.CpuTime() <<
" s "
302 QwMessage <<
"Real time used: " << timer.RealTime() <<
" s "
306 rootfile->Write(0, TObject::kOverwrite);
327 #if ! defined __ROOT_HAS_MATHMORE || ROOT_VERSION_CODE < ROOT_VERSION(5,18,0)
344 double front_position_r = front_position.Perp();
345 double front_position_phi = front_position.Phi();
350 double momentum = 1.165 *
Qw::GeV;
351 double coord[4] = {vertex_z, front_position_phi, front_position_r, momentum};
363 double actual_back_position_r = actual_back_position.Perp();
369 double np = (p_max - p_min) / dp + 1.0;
372 std::vector<double> iP;
373 std::vector<double> iR;
375 iP.resize(np); iR.resize(np);
380 double value[4] = {0.0, 0.0, 0.0, 0.0};
381 unsigned int index = 0;
382 for (
double p = p_max; p >= p_min; p -= dp) {
388 iR[index] = value[0];
394 if ( (iR.front() < actual_back_position_r) &&
395 (iR.back() > actual_back_position_r) ) {
406 #if defined __ROOT_HAS_MATHMORE && ROOT_VERSION_CODE >= ROOT_VERSION(5,18,0)
408 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,22,0)
410 UInt_t size = iP.size();
411 ROOT::Math::Interpolator inter(size, ROOT::Math::Interpolation::kPOLYNOMIAL);
414 UInt_t size = iP.size();
415 ROOT::Math::Interpolator inter(size, ROOT::Math::Interpolation::POLYNOMIAL);
418 inter.SetData(iR, iP);
419 momentum = inter.Eval(actual_back_position_r/
Qw::cm);
421 #else // ! defined __ROOT_HAS_MATHMORE || ROOT_VERSION_CODE < ROOT_VERSION(5,18,0)
426 #endif // ! defined __ROOT_HAS_MATHMORE || ROOT_VERSION_CODE < ROOT_VERSION(5,18,0)
432 if (momentum < 0.98 * Qw::GeV || momentum > 1.165 *
Qw::GeV) {
433 QwMessage <<
"Out of momentum range: determined momentum by looking up table: "
441 double& back_position_r = value[0]; back_position_r *=
Qw::cm;
442 double& back_position_phi = value[1]; back_position_phi *=
Qw::deg;
443 double& back_direction_theta = value[2]; back_direction_theta *=
Qw::deg;
444 double& back_direction_phi = value[3]; back_direction_phi *=
Qw::deg;
447 double x = back_position_r * cos(back_position_phi);
448 double y = back_position_r * sin(back_position_phi);
450 TVector3 back_direction;
451 back_direction.SetMagThetaPhi(1.0, back_direction_theta, back_direction_phi);
454 double diff_position_r = actual_back_position.Perp() - back_position.Perp();
455 double diff_position_phi = actual_back_position.Phi() - back_position.Phi();
456 double diff_direction_phi = actual_back_direction.Phi() - back_direction.Phi();
457 double diff_direction_theta = actual_back_direction.Theta() - back_direction.Theta();
458 if (fabs(diff_position_r) > 2.0 *
Qw::cm
459 || fabs(diff_position_phi) > 4.0 *
Qw::deg
460 || fabs(diff_direction_phi) > 4.0 *
Qw::deg
461 || fabs(diff_direction_theta) > 1.0 *
Qw::deg ) {
471 track =
new QwTrack(front,back);
static const double pi
Angles: base unit is radian.
#define QwMessage
Predefined log drain for regular messages.
Definition of the ray-tracing bridging method for R2/R3 partial tracks.
std::vector< double > fStep
unsigned int GetCurrentEntries() const
Get the current number of entries.
Definition of the matrix lookup bridging method.
bool WriteTrajMatrix(const std::string filename)
Write the trajectory matrix to disk.
TVector3 fStartPosition
Position and direction before and after swimming.
const TVector3 GetPosition(const double z) const
Return the vertex at position z.
Definition of the partial track class.
coord_t GetMaximum(const unsigned int dim) const
Get maximum in dimension.
Definition of the track class.
TVector3 fEndDirectionActual
Actual direction of track at back plane.
bool Set(const coord_t &coord, const value_t &value)
Set a single value at a coordinate (false if not possible)
void SetInterpolationMethod(const EQwInterpolationMethod method)
Set the interpolation method.
QwInterpolator< float, 4 > * fMatrix
Look-up table.
TVector3 fStartDirection
Start direction of front track.
#define QwDebug
Predefined log drain for debugging output.
A logfile class, based on an identical class in the Hermes analyzer.
const TVector3 GetMomentumDirection() const
Return the direction.
TVector3 fEndPositionActual
Actual position of track at back plane.
Contains the complete track as a concatenation of partial tracks.
std::vector< double > fMax
void Coord(const unsigned int *cell_index, coord_t *coord) const
Return the coordinates based on the cell index (unchecked)
coord_t GetMinimum(const unsigned int dim) const
Get minimum in dimension.
TVector3 fEndDirectionGoal
Goal direction of back track.
std::vector< double > fMin
Look-up table minimum, maximum and step size.
bool InBounds(const coord_t *coord) const
Return true if the coordinate is in bounds.
static std::ostream & endl(std::ostream &)
End of the line.
TVector3 fEndPositionGoal
Goal position of back track.
An options class which parses command line, config file and environment.
virtual ~QwMatrixLookup()
Destructor.
bool LoadTrajMatrix(const std::string filename)
Load the trajectory matrix from disk.
QwMatrixLookup(QwOptions &options)
Default constructor.
#define QwWarning
Predefined log drain for warnings.
coord_t GetStepSize(const unsigned int dim) const
Get minimum in dimension.
double fMomentum
Spectrometer momentum.
unsigned int GetMaximumEntries() const
Get the maximum number of entries.
double fFrontRefPlane
Front and back reference planes.
Contains the straight part of a track in one region only.
void SetMinimumMaximumStep(const coord_t min, const coord_t max, const coord_t step)
Set minimum, maximum, and step size to single values.
const QwTrack * Bridge(const QwPartialTrack *front, const QwPartialTrack *back)
Bridge from the front to back partial track.
int IntegrateRK(const TMatrixD &A, const TMatrixD &b, TVector3 &r, TVector3 &v, const double p, const double z, const double h, const double epsilon)
Runge-Kutta numerical integration by Butcher tableau.
value_t GetValue(const coord_t &coord) const
Get the interpolated value at coordinate (zero if out of bounds)
static const double cm
Length units: base unit is mm.