/
ParticleID.cxx
242 lines (224 loc) · 6.56 KB
/
ParticleID.cxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/**
\file
Implementation of class Smear::ParticleID.
\author Michael Savastio
\date 2011-08-12
\copyright 2011 BNL. All rights reserved.
*/
#include "eicsmear/smear/ParticleID.h"
#include <sstream>
#include <string>
#include <vector>
namespace Smear {
ParticleID::ParticleID()
: Ran(0)
, PMatPath("PIDMatrix.dat")
, bUseMC(false) {
ReadP(PMatPath);
}
ParticleID::ParticleID(TString filename)
: Ran(0)
, PMatPath(filename)
, bUseMC(false) {
ReadP(PMatPath);
}
ParticleID::~ParticleID() {
}
void ParticleID::Speak() {
std::cout.setf(std::ios::fixed);
std::cout.precision(6);
for (unsigned i(0); i < PMax.size(); i++) {
for (unsigned k(0); k < FalseIdent.size(); k++) {
std::cout << 1 << '\t' << i + 1 << '\t' << PMin.at(i) << '\t' <<
PMax.at(i) << '\t' << k + 1;
for (unsigned j(0); j < TrueIdent.size(); j++) {
std::cout << '\t' << PMatrix.at(i).at(j).at(k);
} // for
std::cout << std::endl;
} // for
} // for
}
void ParticleID::SetPMatrixSize() {
PMatrix.resize(PMin.size());
for (unsigned i(0); i < PMatrix.size(); i++) {
PMatrix.at(i).resize(TrueIdent.size());
for (unsigned j(0); j < PMatrix.at(i).size(); j++) {
PMatrix.at(i).at(j).resize(FalseIdent.size());
} // for
} // for
}
void ParticleID::SetupProbabilityArray() {
double t = 0.;
Range.resize(PMatrix.size());
for (unsigned i(0); i < Range.size(); i++) {
Range.at(i).resize(PMatrix.at(i).size());
for (unsigned j(0); j < Range.at(i).size(); j++) {
Range.at(i).at(j).resize(PMatrix.at(i).at(j).size());
for (unsigned k = 0; k < Range.at(i).at(j).size(); k++) {
t += PMatrix.at(i).at(j).at(k);
Range.at(i).at(j).at(k) = t;
} // for
t = 0.;
} // for
} // for
}
int ParticleID::Wild(int pbin, int trueID) {
const double r = Ran.Rndm();
const int k = InListOfTrue(trueID);
int falseid(-999999999);
// Get the cumulative probability values for this momentum bin
// and true ID
const std::vector<double>& values = Range.at(pbin).at(k);
for (unsigned i(0); i < values.size(); i++) {
if (0 == i) {
if (r < values.at(i)) {
falseid = FalseIdent.at(i);
} // if
} else if (r > values.at(i-1) && r < values.at(i)) {
falseid = FalseIdent.at(i);
} // if
} // for
return falseid;
}
int ParticleID::InListOfTrue(int ID) {
for (unsigned i(0); i < TrueIdent.size(); i++) {
if (TrueIdent.at(i) == abs(ID)) {
return i;
} // if
} // for
return -1;
}
int ParticleID::InListOfFalse(int ID) {
for (unsigned i(0); i < FalseIdent.size(); i++) {
if (FalseIdent.at(i) == abs(ID)) {
return i;
} // if
} // for
// This is to accomodate the old HERMES format
if (ID < 5 && ID > 0) {
return ID - 1;
} // for
return -1;
}
void ParticleID::Clear(Option_t* /* option */) {
TrueIdent.clear();
FalseIdent.clear();
PMin.clear();
PMax.clear();
PMatrix.clear();
Range.clear();
}
void ParticleID::ReadP(TString filename) {
Clear("");
// Open the file and check for errors
std::ifstream Qfile;
Qfile.open(filename);
if (!Qfile.good()) {
std::cerr << "Error in ParticleID: unable to open file "
<< filename << std::endl;
return;
} // if
// Returns true if s begins with pattern.
struct StartsWith {
bool operator()(const std::string& s,
const std::string& pattern) const {
return s.find(pattern, 0) == 0;
}
}
starts;
std::stringstream ss;
std::string line, dummy;
bool gotTrue(false), gotFalse(false), gotBins(false);
while (std::getline(Qfile, line).good()) {
// Strip leading whitespace
line.erase(0, line.find_first_not_of(" \t"));
// Feed the line to the stringstream, clearing existing contents first
ss.str(""); // Remove contents
ss.clear(); // Clear flags
ss << line;
int tmpint(0);
// Read true particle IDs
if (starts(line, "!T")) {
ss >> dummy;
while ((ss >> tmpint).good()) {
TrueIdent.push_back(tmpint);
} // while
gotTrue = !TrueIdent.empty();
} else if (starts(line, "!F")) {
// Read misidentified particle IDs
ss >> dummy;
while ((ss >> tmpint).good()) {
FalseIdent.push_back(tmpint);
} // while
gotFalse = !FalseIdent.empty();
} else if (starts(line, "!P")) {
// Read number of momentum bins
int pbin;
ss >> dummy >> pbin;
PMin.resize(pbin);
PMax.resize(pbin);
gotBins = !PMin.empty();
} else if (starts(line, "1") || starts(line, "2") || starts(line, "3")) {
// Read the probabilities for this momentum bin/true ID/false ID
if (!(gotTrue && gotFalse && gotBins)) {
std::cerr << "Error in ParticleID: " <<
"P matrix input file has bad or missing format lines.\n";
return;
} // if
int table, pbin, pid;
double pmin, pmax, p1, p2, p3;
ss >> table >> pbin >> pmin >> pmax >> pid >> p1 >> p2 >> p3;
if ((unsigned)pbin > PMin.size()) {
std::cerr << "Error in ParticleID: " <<
"Out of bounds momentum bin listing.\n";
return;
} // if
pbin -= 1; // Go from [1, N] to [0, N) for vector index range
PMin.at(pbin) = pmin;
PMax.at(pbin) = pmax;
pid = InListOfFalse(pid);
if ((unsigned)pid > FalseIdent.size()) {
std::cerr << "Error in ParticleID: " <<
"P matrix has bad particle listing.\n";
return;
} // if
if (PMatrix.empty()) {
SetPMatrixSize();
} // if
// Set identification probabilities
if (1 == table) {
PMatrix.at(pbin).at(0).at(pid) = p1;
PMatrix.at(pbin).at(1).at(pid) = p2;
PMatrix.at(pbin).at(2).at(pid) = p3;
} // if
} // if
} // while
SetupProbabilityArray();
}
void ParticleID::Smear(const erhic::VirtualParticle& prt,
ParticleMCS& prtOut) {
double momentum(0.);
if (bUseMC) {
momentum = prt.GetP();
} else {
momentum = prtOut.GetP();
} // if
const int pid = prt.Id();
if (InListOfTrue(pid) != -1 && Accept.Is(prt)) {
for (unsigned i(0); i < PMin.size(); i++) {
if (momentum > PMin.at(i) && momentum < PMax.at(i)) {
// Generated ID is always positive.
// Keep same sign as input PID i.e. no error in charge sign
if (pid > 0) {
prtOut.SetId (Wild(i, pid) );
} else {
prtOut.SetId( -Wild(i, pid) );
} // if
} // if
} // for
} // if
}
void ParticleID::Print(Option_t* /* option */) const {
std::cout << "ParticleID using " << PMatPath << std::endl;
}
} // namespace Smear