CbmRoot
Loading...
Searching...
No Matches
CbmStsAlgoAnaCluster.cxx
Go to the documentation of this file.
1/* Copyright (C) 2016-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer] */
4
11
12#include "CbmDigiManager.h"
13#include "CbmStsCluster.h"
14#include "CbmStsDigi.h"
15#include "CbmStsParModule.h"
16#include "CbmStsPhysics.h"
17
18#include <TMath.h>
19
20using std::unique_ptr;
21
23
24
25 // ----- Constructor ----------------------------------------------------
27 : fDigiMan(CbmDigiManager::Instance())
28 , fPhysics(CbmStsPhysics::Instance())
29{
30}
31// --------------------------------------------------------------------------
32
33
34// ----- Algorithm for one-digi clusters --------------------------------
36{
37
38 assert(module);
39 Int_t index = cluster.GetDigi(0);
40 const CbmStsDigi* digi = fDigiMan->Get<CbmStsDigi>(index);
41 assert(digi);
42 // printf("BEGIN CLUSTER CALC 1\n");
43 // printf("Digi %d: channel=%d, time=%d, charge=%d\n", index, digi->GetChannel(), digi->GetTimeU32(), digi->GetChargeU16());
44 // printf("END CLUSTER CALC\n");
45
46 auto& asic = module->GetParAsic(digi->GetChannel());
47 Double_t x = Double_t(digi->GetChannel());
48 Double_t time = digi->GetTime();
49 Double_t timeError = asic.GetTimeResol();
50 Double_t charge = asic.AdcToCharge(digi->GetCharge());
51 Double_t xError = 1. / sqrt(24.);
52
53 cluster.SetProperties(charge, x, xError, time, timeError);
54 cluster.SetSize(1);
55}
56// --------------------------------------------------------------------------
57
58
59// ----- Algorithm for two-digi clusters --------------------------------
61{
62
63 Int_t index1 = cluster.GetDigi(0);
64 Int_t index2 = cluster.GetDigi(1);
65 const CbmStsDigi* digi1 = fDigiMan->Get<CbmStsDigi>(index1);
66 const CbmStsDigi* digi2 = fDigiMan->Get<CbmStsDigi>(index2);
67 assert(digi1);
68 assert(digi2);
69
70 auto& asic1 = modPar->GetParAsic(digi1->GetChannel());
71 auto& asic2 = modPar->GetParAsic(digi2->GetChannel());
72
73 // --- Uncertainties of the charge measurements
74 Double_t eNoiseSq = 0.5 * (asic1.GetNoise() * asic1.GetNoise() + asic2.GetNoise() * asic2.GetNoise());
75 Double_t chargePerAdc =
76 0.5 * (asic1.GetDynRange() / Double_t(asic1.GetNofAdc()) + asic2.GetDynRange() / Double_t(asic2.GetNofAdc()));
77 Double_t eDigitSq = chargePerAdc * chargePerAdc / 12.;
78
79 UInt_t chan1 = digi1->GetChannel();
80 UInt_t chan2 = digi2->GetChannel();
81 assert(chan2 == chan1 + 1 || chan2 == chan1 - modPar->GetNofChannels() / 2 + 1);
82
83 // Channel positions and charge
84 Double_t x1 = Double_t(chan1);
85 Double_t q1 = asic1.AdcToCharge(digi1->GetCharge());
86 Double_t q2 = asic2.AdcToCharge(digi2->GetCharge());
87
88 // Periodic position for clusters round the edge
89 if (chan1 > chan2) x1 -= Double_t(modPar->GetNofChannels() / 2);
90
91 // Uncertainties of the charge measurements
92 Double_t width1 = fPhysics->LandauWidth(q1);
93 Double_t eq1sq = width1 * width1 + eNoiseSq + eDigitSq;
94 Double_t width2 = fPhysics->LandauWidth(q2);
95 Double_t eq2sq = width2 * width2 + eNoiseSq + eDigitSq;
96
97 // Cluster time
98 Double_t time = 0.5 * (digi1->GetTime() + digi2->GetTime());
99 Double_t timeError = 0.5 * (asic1.GetTimeResol() + asic2.GetTimeResol()) * 0.70710678; // 1/sqrt(2)
100
101 // Cluster position
102 // See corresponding software note.
103 Double_t x = x1 + 0.5 + (q2 - q1) / 3. / TMath::Max(q1, q2);
104
105 // Correct negative position for clusters around the edge
106 if (x < -0.5) x += Double_t(modPar->GetNofChannels() / 2);
107
108 // Uncertainty on cluster position. See software note.
109 Double_t ex0sq = 0.; // error for ideal charge measurements
110 Double_t ex1sq = 0.; // error from first charge
111 Double_t ex2sq = 0.; // error from second charge
112 if (q1 < q2) {
113 ex0sq = (q2 - q1) * (q2 - q1) / q2 / q2 / 72.;
114 ex1sq = eq1sq / q2 / q2 / 9.;
115 ex2sq = eq2sq * q1 * q1 / q2 / q2 / q2 / q2 / 9.;
116 }
117 else {
118 ex0sq = (q2 - q1) * (q2 - q1) / q1 / q1 / 72.;
119 ex1sq = eq1sq * q2 * q2 / q1 / q1 / q1 / q1 / 9.;
120 ex2sq = eq2sq / q1 / q1 / 9.;
121 }
122 Double_t xError = TMath::Sqrt(ex0sq + ex1sq + ex2sq);
123
124
125 // Cluster charge
126 Double_t charge = q1 + q2;
127
128 cluster.SetProperties(charge, x, xError, time, timeError);
129 cluster.SetSize(2);
130}
131// --------------------------------------------------------------------------
132
133
134// ----- Algorithm for clusters with more than two digis ----------------
136{
137
138 Double_t tSum = 0.; // sum of digi times
139 Int_t chanF = 9999999; // first channel in cluster
140 Int_t chanL = -1; // last channel in cluster
141 Double_t qF = 0.; // charge in first channel
142 Double_t qM = 0.; // sum of charges in middle channels
143 Double_t qL = 0.; // charge in last cluster
144 Double_t eqFsq = 0.; // uncertainty of qF
145 Double_t eqMsq = 0.; // uncertainty of qMid
146 Double_t eqLsq = 0.; // uncertainty of qL
147 Double_t prevChannel = 0;
148 Double_t tResolSum = 0.;
149
150 for (Int_t iDigi = 0; iDigi < cluster.GetNofDigis(); iDigi++) {
151
152 Int_t index = cluster.GetDigi(iDigi);
153 const CbmStsDigi* digi = fDigiMan->Get<CbmStsDigi>(index);
154
155 assert(digi);
156 Int_t channel = digi->GetChannel();
157 auto& asic = modPar->GetParAsic(channel);
158
159
160 // --- Uncertainties of the charge measurements
161 Double_t eNoiseSq = asic.GetNoise() * asic.GetNoise();
162 Double_t chargePerAdc = asic.GetDynRange() / Double_t(asic.GetNofAdc());
163 Double_t eDigitSq = chargePerAdc * chargePerAdc / 12.;
164 tResolSum += asic.GetTimeResol();
165
166 tSum += digi->GetTime();
167 Double_t charge = asic.AdcToCharge(digi->GetCharge());
168 Double_t lWidth = fPhysics->LandauWidth(charge);
169 Double_t eChargeSq = lWidth * lWidth + eNoiseSq + eDigitSq;
170
171 // Check ascending order of channel number
172 if (iDigi > 0) assert(channel == prevChannel + 1 || channel == prevChannel - modPar->GetNofChannels() / 2 + 1);
173 prevChannel = channel;
174
175 if (iDigi == 0) { // first channel
176 chanF = channel;
177 qF = charge;
178 eqFsq = eChargeSq;
179 }
180 else if (iDigi == cluster.GetNofDigis() - 1) { // last channel
181 chanL = channel;
182 qL = charge;
183 eqLsq = eChargeSq;
184 }
185 else { // one of the middle channels
186 qM += charge;
187 eqMsq += eChargeSq;
188 }
189
190 } //# digis in cluster
191
192
193 // Periodic channel position for clusters round the edge
194 if (chanF > chanL) chanF -= modPar->GetNofChannels() / 2;
195
196 // Cluster time and total charge
197 tSum = tSum / Double_t(cluster.GetNofDigis());
198 Double_t tError = (tResolSum / Double_t(cluster.GetNofDigis())) / TMath::Sqrt(Double_t(cluster.GetNofDigis()));
199 Double_t qSum = qF + qM + qL;
200
201 // Average charge in middle strips
202 qM /= Double_t(cluster.GetNofDigis() - 2);
203 eqMsq /= Double_t(cluster.GetNofDigis() - 2);
204
205 // Cluster position
206 Double_t x = 0.5 * (Double_t(chanF + chanL) + (qL - qF) / qM);
207
208 // Correct negative cluster position for clusters round the edge
209 if (x < -0.5) x += Double_t(modPar->GetNofChannels() / 2);
210
211 // Cluster position error
212 Double_t exFsq = eqFsq / qM / qM / 4.; // error from first charge
213 Double_t exMsq = eqMsq * (qL - qF) * (qL - qF) / qM / qM / qM / qM / 4.;
214 Double_t exLsq = eqLsq / qM / qM / 4.;
215 Double_t xError = TMath::Sqrt(exFsq + exMsq + exLsq);
216
217 // Correction for corrupt clusters
218 if (x < chanF || x > chanL) x = WeightedMean(cluster, modPar);
219
220 assert(x >= chanF && x <= chanL);
221
222 cluster.SetProperties(qSum, x, xError, tSum, tError);
223 cluster.SetSize(chanL - chanF + 1);
224}
225// --------------------------------------------------------------------------
226
227
228// ----- Algorithm execution --------------------------------------------
230{
231
232 Int_t nDigis = cluster.GetNofDigis();
233 assert(nDigis >= 0);
234
235 switch (nDigis) {
236
237 case 0: break;
238 case 1: AnaSize1(cluster, modPar); break;
239 case 2: AnaSize2(cluster, modPar); break;
240 default: AnaSizeN(cluster, modPar); break;
241
242 } //? number of digis
243}
244// --------------------------------------------------------------------------
245
246
247// ----- Weighted mean calculation --------------------------------------
249{
250
251 Double_t qSum = 0.;
252 Double_t xSum = 0.;
253 for (Int_t iDigi = 0; iDigi < cluster.GetNofDigis(); iDigi++) {
254 Int_t index = cluster.GetDigi(iDigi);
255 const CbmStsDigi* digi = fDigiMan->Get<CbmStsDigi>(index);
256 assert(digi);
257 Int_t channel = digi->GetChannel();
258 auto& asic = modPar->GetParAsic(channel);
259 Double_t charge = asic.AdcToCharge(digi->GetCharge());
260 qSum += charge;
261 xSum += charge * Double_t(channel);
262 }
263
264 return xSum / qSum;
265}
266// --------------------------------------------------------------------------
ClassImp(CbmStsAlgoAnaCluster) CbmStsAlgoAnaCluster
Data class for STS clusters.
CbmDigiManager * fDigiMan
friend fvec sqrt(const fvec &a)
int32_t GetDigi(int32_t index) const
Get digi at position index.
Definition CbmCluster.h:76
int32_t GetNofDigis() const
Number of digis in cluster.
Definition CbmCluster.h:69
CbmDigiManager.
const Digi * Get(Int_t index) const
Get a digi object.
Determination of cluster parameters.
CbmStsPhysics * fPhysics
Interface to digi data.
void AnaSize2(CbmStsCluster &cluster, const CbmStsParModule *modPar)
Analyse two-digi cluster.
Double_t WeightedMean(CbmStsCluster &cluster, const CbmStsParModule *modPar)
Weighted mean cluster position.
void Exec(CbmStsCluster &cluster, const CbmStsParModule *module)
Algorithm execution.
void AnaSize1(CbmStsCluster &cluster, const CbmStsParModule *modPar)
Analyse single-digi cluster.
CbmStsAlgoAnaCluster()
Constructor.
void AnaSizeN(CbmStsCluster &cluster, const CbmStsParModule *modPar)
Analyse cluster with more than two digis.
Data class for STS clusters.
void SetSize(int32_t size)
Set size of the cluster (number of channels)
void SetProperties(double charge, double position, double positionError, double time=0., double timeError=0.)
Data class for a single-channel message in the STS.
Definition CbmStsDigi.h:40
XPU_D uint16_t GetChannel() const
Channel number in module @value Channel number.
Definition CbmStsDigi.h:93
double AdcToCharge(uint16_t adc) const
Charge from ADC channel (mean)
double GetNoise() const
Electronic noise RMS.
Parameters for one STS module.
uint32_t GetNofChannels() const
Number of channels.
const CbmStsParAsic & GetParAsic(uint32_t channel) const
ASIC parameters for a given channel.
Auxiliary class for physics processes in Silicon.
Double_t LandauWidth(Double_t mostProbableCharge)
Half width at half max of Landau distribution in ultra-relativistic case.