This method is called for each event.
All processing of the event takes place in this method.
86 {
87
88 if (not m_hits.isValid()) {
89 m_warnCount++;
90 if (m_warnCount < 10) {
91 B2WARNING("StoreArray 'CDCDedxHits' does not exist, returning. Probably running on old cdst.");
92 } else if (m_warnCount == 10) {
93 B2WARNING("StoreArray 'CDCDedxHits' does not exist, returning. ...message will be suppressed now.");
94 }
95 return;
96 }
97
98
99 m_likelihoods.clear();
100 m_dedxTracks.clear();
101
102
103 const auto& cdcgeo = CDCGeometryPar::Instance();
104 LinearGlobalADCCountTranslator adcTranslator;
105 RealisticTDCCountTranslator tdcTranslator;
106
107
108 bool isData = not Environment::Instance().isMC();
109
110
111 double runGain = isData ? m_DBRunGain->getRunGain() : 1.0;
112 double timeGain = 1;
113 double timeReso = 1;
114 if (isData and m_TTDInfo.isValid() and m_TTDInfo->hasInjection()) {
115 timeGain = m_DBInjectTime->getCorrection("mean", m_TTDInfo->isHER(), m_TTDInfo->getTimeSinceLastInjectionInMicroSeconds());
116 timeReso = m_DBInjectTime->getCorrection("reso", m_TTDInfo->isHER(), m_TTDInfo->getTimeSinceLastInjectionInMicroSeconds());
117 }
118 double scale = m_DBScaleFactor->getScaleFactor();
119 if (scale == 0) {
120 B2ERROR("Scale factor from DB is zero! Will be set to one");
121 scale = 1;
122 }
123
124
125 for (const auto& track : m_tracks) {
126
127 const auto* fitResult = track.getTrackFitResultWithClosestMass(Const::pion);
128 if (not fitResult) {
129 B2WARNING("No related fit for track, skip it.");
130 continue;
131 }
132
133
134 const auto hits = track.getRelationsTo<CDCDedxHit>();
135 if (hits.size() == 0) continue;
136
137
138 const auto& trackMom = fitResult->getMomentum();
139 double theta = trackMom.Theta();
140 double cosTheta = std::cos(theta);
141 double sinTheta = std::sin(theta);
142
143
144 bool isEdge = std::abs(cosTheta + 0.860) < 0.010 or std::abs(cosTheta - 0.955) <= 0.005;
145 double cosEdgeCor = (isData and isEdge) ? m_DBCosEdgeCor->getMean(cosTheta) : 1.0;
146
147
148 const auto* mcParticle = isData ? nullptr : track.getRelated<MCParticle>();
149
150
151 CDCDedxTrack* dedxTrack = m_dedxTracks.appendNew();
152 if (dedxTrack) {
153 dedxTrack->m_track = track.getArrayIndex();
154 dedxTrack->m_charge = fitResult->getChargeSign();
155 dedxTrack->m_cosTheta = cosTheta;
156 dedxTrack->m_p = trackMom.R();
157 if (isData and m_TTDInfo.isValid() and m_TTDInfo->hasInjection()) {
158 dedxTrack->m_injring = m_TTDInfo->isHER();
159 dedxTrack->m_injtime = m_TTDInfo->getTimeSinceLastInjectionInMicroSeconds();
160 }
161 if (mcParticle) {
162 dedxTrack->m_pdg = mcParticle->getPDG();
163 dedxTrack->m_mcmass = mcParticle->getMass();
164 const auto* mother = mcParticle->getMother();
165 dedxTrack->m_motherPDG = mother ? mother->getPDG() : 0;
166 const auto& trueMom = mcParticle->getMomentum();
167 dedxTrack->m_pTrue = trueMom.R();
168 dedxTrack->m_cosThetaTrue = std::cos(trueMom.Theta());
169 }
170 dedxTrack->m_scale = scale;
171 dedxTrack->m_cosEdgeCor = cosEdgeCor;
172 dedxTrack->m_runGain = runGain;
173 dedxTrack->m_timeGain = timeGain;
174 dedxTrack->m_timeReso = timeReso;
175 }
176
177
178 int lastLayer = -1;
179 double pCDC = 0;
180 std::map<int, DEDX> dedxWires;
181 for (const auto& hit : hits) {
182
183 const auto& wireID = hit.getWireID();
184 int layer = wireID.getILayer();
185 unsigned int superlayer = wireID.getISuperLayer();
186 int currentLayer = (superlayer == 0) ? layer : (8 + (superlayer - 1) * 6 + layer);
187 if (not m_useBackHalfCurlers and currentLayer < lastLayer) break;
188 lastLayer = currentLayer;
189
190
191 if (pCDC == 0) pCDC = hit.getPOCAMomentum().R();
192
193
194 double innerRadius = cdcgeo.innerRadiusWireLayer()[currentLayer];
195 double outerRadius = cdcgeo.outerRadiusWireLayer()[currentLayer];
196 const ROOT::Math::XYZVector& wirePosF = cdcgeo.wireForwardPosition(wireID, CDCGeometryPar::c_Aligned);
197 double wireRadius = wirePosF.Rho();
198 int nWires = cdcgeo.nWiresInLayer(currentLayer);
199 double topHeight = outerRadius - wireRadius;
200 double bottomHeight = wireRadius - innerRadius;
201 double topHalfWidth = M_PI * outerRadius / nWires;
202 double bottomHalfWidth = M_PI * innerRadius / nWires;
203 DedxDriftCell cell(DedxPoint(-topHalfWidth, topHeight),
204 DedxPoint(topHalfWidth, topHeight),
205 DedxPoint(bottomHalfWidth, -bottomHeight),
206 DedxPoint(-bottomHalfWidth, -bottomHeight));
207
208
209 double doca = hit.getSignedDOCAXY();
210 double entAng = hit.getEntranceAngle();
211 double celldx = cell.dx(doca, entAng) / sinTheta;
212 if (not cell.isValid()) continue;
213
214
215 double cosCor = isData ? m_DBCosineCor->getMean(currentLayer, cosTheta) : 1.0;
216
217
218 int wire = wireID.getIWire();
219 int iwire = (superlayer == 0) ? 160 * layer + wire : m_nLayerWires[superlayer - 1] + (160 + 32 * (superlayer - 1)) * layer + wire;
220 double wiregain = isData ? m_DBWireGains->getWireGain(iwire) : 1.0;
221
222
223 double cellHalfWidth = M_PI * wireRadius / nWires;
224 double cellHeight = topHeight + bottomHeight;
225 double cellR = 2 * cellHalfWidth / cellHeight;
226 double tana = std::max(std::min(std::tan(entAng), 1e10), -1e10);
227 double docaRS = doca * std::sqrt((1 + cellR * cellR * tana * tana) / (1 + tana * tana));
228 double normDocaRS = docaRS / cellHalfWidth;
229 double entAngRS = std::atan(tana / cellR);
230
231
232 double onedcor = isData ? m_DB1DCell->getMean(currentLayer, entAngRS) : 1.0;
233 double twodcor = isData ? m_DB2DCell->getMean(currentLayer, normDocaRS, entAngRS) : 1.0;
234
235
236 double correction = runGain * cosCor * cosEdgeCor * timeGain * wiregain * twodcor * onedcor;
237
238
239 double adcCount = isData ? m_DBNonlADC->getCorrectedADC(hit.getADCCount(), currentLayer) : hit.getADCCount();
240 double adcCalibrated = correction != 0 ? adcCount / scale / correction : 0;
241
242
243 if (correction != 0) dedxWires[iwire].add(hit, iwire, currentLayer, celldx, adcCalibrated);
244
245
246 if (dedxTrack) {
247 dedxTrack->m_pCDC = pCDC;
248 const auto& pocaMom = hit.getPOCAMomentum();
249 double pocaPhi = pocaMom.Phi();
250 double pocaTheta = pocaMom.Theta();
251 double pocaZ = hit.getPOCAOnWire().Z();
252 double hitCharge = adcTranslator.getCharge(adcCount, wireID, false, pocaZ, pocaPhi);
253 double driftDRealistic = tdcTranslator.getDriftLength(hit.getTDCCount(), wireID, 0, true, pocaZ, pocaPhi, pocaTheta);
254 double driftDRealisticRes = tdcTranslator.getDriftLengthResolution(driftDRealistic, wireID, true, pocaZ, pocaPhi, pocaTheta);
255 double cellDedx = adcCalibrated / celldx;
256
257 dedxTrack->addHit(wire, iwire, currentLayer, doca, docaRS, entAng, entAngRS,
258 adcCount, hit.getADCCount(), hitCharge, celldx * sinTheta, cellDedx, cellHeight, cellHalfWidth,
259 hit.getTDCCount(), driftDRealistic, driftDRealisticRes, cosCor, wiregain, twodcor, onedcor,
260 hit.getFoundByTrackFinder(), hit.getWeightPionHypo(), hit.getWeightKaonHypo(), hit.getWeightProtonHypo());
261 }
262
263 }
264
265
266 std::map<int, DEDX> dedxLayers;
267 for (const auto& dedxWire : dedxWires) {
268 const auto& dedx = dedxWire.second;
269 dedxLayers[dedx.cLayer].add(dedx);
270 }
271
272
273 std::vector<double> dedxValues;
274 for (const auto& dedxLayer : dedxLayers) {
275 const auto& dedx = dedxLayer.second;
276 if (dedx.dx > 0 and dedx.dE > 0) {
277 dedxValues.push_back(dedx.dE / dedx.dx);
278
279 if (dedxTrack) dedxTrack->addDedx(dedx.nhits, dedx.cWire, dedx.cLayer, dedx.dx, dedxValues.back());
280 }
281 }
282 if (dedxValues.empty()) continue;
283
284
285 std::sort(dedxValues.begin(), dedxValues.end());
286
287
288 double mean = 0;
289 for (auto x : dedxValues) mean += x;
290 mean /= dedxValues.size();
291
292
293 int lowEdgeTrunc = int(dedxValues.size() * m_removeLowest + 0.51);
294 int highEdgeTrunc = int(dedxValues.size() * (1 - m_removeHighest) + 0.51);
295 double truncatedMean = 0;
296 double sumOfSquares = 0;
297 int numValues = 0;
298 for (int i = lowEdgeTrunc; i < highEdgeTrunc; i++) {
299 double x = dedxValues[i];
300 truncatedMean += x;
301 sumOfSquares += x * x;
302 numValues++;
303 }
304 if (numValues > 0) {
305 truncatedMean /= numValues;
306 } else {
307 truncatedMean = mean;
308 numValues = dedxValues.size();
309 }
310 double truncatedError = numValues > 1 ? std::sqrt(sumOfSquares / numValues - truncatedMean * truncatedMean) / (numValues - 1) : 0;
311
312
313 double correctedMean = isData ? m_DBHadronCor->getCorrectedMean(truncatedMean, cosTheta) : truncatedMean;
314
315
316 if (m_trackLevel and mcParticle) {
317 double mass = mcParticle->getMass();
318 if (mass > 0) {
319 double mcMean = m_DBMeanPars->getMean(pCDC / mass);
320 double mcSigma = m_DBSigmaPars->getSigma(mcMean, numValues, cosTheta, timeReso);
321 correctedMean = gRandom->Gaus(mcMean, mcSigma);
322 while (correctedMean < 0) correctedMean = gRandom->Gaus(mcMean, mcSigma);
323
324 if (dedxTrack) dedxTrack->m_simDedx = correctedMean;
325 }
326 }
327
328
329 double cdcLogL[Const::ChargedStable::c_SetSize] = {0};
330 for (const auto& chargedStable : Const::chargedStableSet) {
331 double betagamma = pCDC / chargedStable.getMass();
332 double predictedMean = m_DBMeanPars->getMean(betagamma);
333 double predictedSigma = m_DBSigmaPars->getSigma(predictedMean, numValues, cosTheta, timeReso);
334 if (predictedSigma <= 0) B2ERROR("Predicted sigma is not positive for PDG = " << chargedStable.getPDGCode());
335 double chi = (correctedMean - predictedMean) / predictedSigma;
336 int index = chargedStable.getIndex();
337 cdcLogL[index] = -0.5 * chi * chi;
338
339 if (dedxTrack) {
340 dedxTrack->m_predmean[index] = predictedMean;
341 dedxTrack->m_predres[index] = predictedSigma;
342 dedxTrack->m_cdcChi[index] = chi;
343 dedxTrack->m_cdcLogl[index] = cdcLogL[index];
344 }
345 }
346
347
348 auto* likelihoods = m_likelihoods.appendNew(cdcLogL);
349 track.addRelationTo(likelihoods);
350
351
352 if (dedxTrack) {
353 double fullLength = 0;
354 for (const auto& dedxLayer : dedxLayers) fullLength += dedxLayer.second.dx;
355 dedxTrack->m_length = fullLength;
356 dedxTrack->m_dedxAvg = mean;
357 dedxTrack->m_dedxAvgTruncatedNoSat = truncatedMean;
358 dedxTrack->m_dedxAvgTruncatedErr = truncatedError;
359 dedxTrack->m_dedxAvgTruncated = correctedMean;
360 dedxTrack->m_lNHitsUsed = numValues;
361 track.addRelationTo(dedxTrack);
362 }
363
364 }
365
366 }