Skip to content

Commit 916d43a

Browse files
badarotswiechula
authored andcommitted
TPC: change track params in dEdx calibration
* Correct for Tgl and Snp, instead of Z and Tgl * Iteractive fit method to remove electron tracks * Snp correction is off by default * Extended momentum range of input data using Beth-Bloch correction * Tgl limits based on the max acceptance per ROC type Minor changes: * Save the run number as CCDB metadata * Record number of tracks of each correction fit * Method to convert boost hist into a THn Apply suggestions from code review Co-authored-by: wiechula <11199190+wiechula@users.noreply.github.com>
1 parent b9dbcf0 commit 916d43a

16 files changed

Lines changed: 432 additions & 321 deletions

File tree

DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxCorrection.h

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616
#define ALICEO2_TPC_CALIBDEDXCORRECTION_H_
1717

1818
#include "GPUCommonDef.h"
19+
#include "GPUCommonMath.h"
1920
#include "GPUCommonRtypes.h"
2021

2122
#ifndef GPUCA_GPUCODE_DEVICE
2223
#include <string_view>
24+
#include <algorithm>
2325
#endif
2426

2527
// o2 includes
@@ -31,8 +33,9 @@ namespace o2::tpc
3133
class CalibdEdxCorrection
3234
{
3335
public:
34-
constexpr static int paramSize = 6;
35-
constexpr static int fitSize = 288;
36+
static constexpr int FitSize = 288; ///< Number of fitted corrections
37+
static constexpr int ParamSize = 8; ///< Number of params per fit
38+
3639
#if !defined(GPUCA_ALIGPUCODE)
3740
CalibdEdxCorrection()
3841
{
@@ -44,35 +47,39 @@ class CalibdEdxCorrection
4447
#endif
4548
~CalibdEdxCorrection() CON_DEFAULT;
4649

47-
GPUd() float getCorrection(const StackID& stack, ChargeType charge, float z = 0, float tgl = 0) const
50+
GPUd() float getCorrection(const StackID& stack, ChargeType charge, float tgl = 0, float snp = 0) const
4851
{
4952
// by default return 1 if no correction was loaded
5053
if (mDims < 0) {
5154
return 1;
5255
}
5356

54-
const auto& p = mParams[stackIndex(stack, charge)];
55-
float corr = p[0];
56-
57+
tgl = o2::gpu::CAMath::Abs(tgl);
58+
auto p = mParams[stackIndex(stack, charge)];
59+
float result = p[0];
60+
// Tgl part
5761
if (mDims > 0) {
58-
corr += p[1] * z + p[2] * z * z;
59-
if (mDims > 1) {
60-
corr += p[3] * tgl + p[4] * z * tgl + p[5] * tgl * tgl;
61-
}
62+
result += tgl * (p[1] + tgl * (p[2] + tgl * (p[3] + tgl * p[4])));
6263
}
63-
64-
return corr;
64+
// Snp and cross terms
65+
if (mDims > 1) {
66+
result += snp * (p[5] + snp * p[6] + tgl * p[7]);
67+
}
68+
return result;
6569
}
6670

6771
#if !defined(GPUCA_GPUCODE)
68-
float getChi2(const StackID& stack, ChargeType charge) const
72+
const float* getParams(const StackID& stack, ChargeType charge) const
6973
{
70-
return mChi2[stackIndex(stack, charge)];
74+
return mParams[stackIndex(stack, charge)];
7175
}
76+
float getChi2(const StackID& stack, ChargeType charge) const { return mChi2[stackIndex(stack, charge)]; }
77+
int getEntries(const StackID& stack, ChargeType charge) const { return mEntries[stackIndex(stack, charge)]; }
7278
int getDims() const { return mDims; }
7379

74-
void setParams(const StackID& stack, ChargeType charge, const float* params) { std::copy(params, params + paramSize, mParams[stackIndex(stack, charge)]); }
80+
void setParams(const StackID& stack, ChargeType charge, const float* params) { std::copy(params, params + ParamSize, mParams[stackIndex(stack, charge)]); }
7581
void setChi2(const StackID& stack, ChargeType charge, float chi2) { mChi2[stackIndex(stack, charge)] = chi2; }
82+
void setEntries(const StackID& stack, ChargeType charge, int entries) { mEntries[stackIndex(stack, charge)] = entries; }
7683
void setDims(int dims) { mDims = dims; }
7784

7885
void clear();
@@ -84,11 +91,12 @@ class CalibdEdxCorrection
8491
private:
8592
GPUd() static int stackIndex(const StackID& stack, ChargeType charge)
8693
{
87-
return stack.index() + charge * SECTORSPERSIDE * SIDES * GEMSTACKSPERSECTOR;
94+
return stack.getIndex() + charge * SECTORSPERSIDE * SIDES * GEMSTACKSPERSECTOR;
8895
}
8996

90-
float mParams[fitSize][paramSize];
91-
float mChi2[fitSize];
97+
float mParams[FitSize][ParamSize];
98+
float mChi2[FitSize];
99+
int mEntries[FitSize];
92100
int mDims{-1}; ///< Fit dimension
93101

94102
ClassDefNV(CalibdEdxCorrection, 1);

DataFormats/Detectors/TPC/include/DataFormatsTPC/DCS.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ struct HV {
257257
// the counting is GEM1 top, bottom, GEM2 top, bottom, ...
258258
const int electrode = 2 * (gem - 1) + !isTop;
259259
const StackID stackID{sector, stack};
260-
const int index = stackID.index() * 2 * GEMSPERSTACK + electrode;
260+
const int index = stackID.getIndex() * 2 * GEMSPERSTACK + electrode;
261261

262262
const auto type = sensor.back();
263263
// LOGP(info, "Fill type: {}, index: {} (sec: {}, stack: {}, gem: {}, elec: {}), time: {}, value: {}", type, index, sector, stack, gem, electrode, time, value);
@@ -276,7 +276,7 @@ struct HV {
276276
const StackID stackID{sector, stack};
277277

278278
// TODO: check value for validity
279-
states[stackID.index()].fill(time, static_cast<StackState>(value));
279+
states[stackID.getIndex()].fill(time, static_cast<StackState>(value));
280280
}
281281

282282
void sortAndClean()

DataFormats/Detectors/TPC/include/DataFormatsTPC/Defs.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,15 @@ struct StackID {
8080
GEMstack type{};
8181

8282
/// Single number identification for the stacks
83-
GPUdi() int index() const
83+
GPUdi() int getIndex() const
8484
{
8585
return sector + type * SECTORSPERSIDE * SIDES;
8686
}
87+
GPUdi() void setIndex(int index)
88+
{
89+
sector = index % (SECTORSPERSIDE * SIDES);
90+
type = static_cast<GEMstack>((index / (SECTORSPERSIDE * SIDES)) % GEMSTACKSPERSECTOR);
91+
}
8792
};
8893

8994
/// Statistics type

DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackCuts.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,22 @@ class TrackCuts
3737
{
3838
public:
3939
TrackCuts() = default;
40-
TrackCuts(float PMin, float PMax, float NClusMin);
40+
TrackCuts(float PMin, float PMax, float NClusMin, float dEdxMin = 0, float dEdxMax = 1e10);
4141

4242
bool goodTrack(o2::tpc::TrackTPC const& track);
4343

4444
void setPMin(float PMin) { mPMin = PMin; }
4545
void setPMax(float PMax) { mPMax = PMax; }
4646
void setNClusMin(float NClusMin) { mNClusMin = NClusMin; }
47+
void setdEdxMin(float dEdxMin) { mdEdxMin = dEdxMin; }
48+
void setdEdxMax(float dEdxMax) { mdEdxMax = dEdxMax; }
4749

4850
private:
49-
float mPMin{0}; // min momentum allowed
50-
float mPMax{1e10}; // max momentum allowed
51-
float mNClusMin{0}; // min number of clusters in track allowed
51+
float mPMin{0}; ///< min momentum allowed
52+
float mPMax{1e10}; ///< max momentum allowed
53+
float mNClusMin{0}; ///< min number of clusters in track allowed
54+
float mdEdxMin{0}; ///< min dEdx
55+
float mdEdxMax{1e10}; ///< max dEdx
5256

5357
ClassDefNV(TrackCuts, 1)
5458
};

DataFormats/Detectors/TPC/src/TrackCuts.cxx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,35 @@ ClassImp(o2::tpc::TrackCuts);
1818

1919
using namespace o2::tpc;
2020

21-
TrackCuts::TrackCuts(float PMin, float PMax, float NClusMin) : mPMin(PMin),
22-
mPMax(PMax),
23-
mNClusMin(NClusMin)
21+
TrackCuts::TrackCuts(float PMin, float PMax, float NClusMin, float dEdxMin, float dEdxMax)
22+
: mPMin(PMin),
23+
mPMax(PMax),
24+
mNClusMin(NClusMin),
25+
mdEdxMin(dEdxMin),
26+
mdEdxMax(dEdxMax)
2427
{
2528
}
2629

2730
//______________________________________________________________________________
2831
bool TrackCuts::goodTrack(o2::tpc::TrackTPC const& track)
2932
{
3033
const auto p = track.getP();
31-
const auto nclusters = track.getNClusterReferences();
34+
const auto nClusters = track.getNClusterReferences();
35+
const auto dEdx = track.getdEdx().dEdxTotTPC;
3236

3337
if (p > mPMax) {
3438
return false;
3539
}
3640
if (p < mPMin) {
3741
return false;
3842
}
39-
if (nclusters < mNClusMin) {
43+
if (nClusters < mNClusMin) {
44+
return false;
45+
}
46+
if (dEdx > mdEdxMax) {
47+
return false;
48+
}
49+
if (dEdx < mdEdxMin) {
4050
return false;
4151
}
4252
return true;

Detectors/TPC/calibration/doc/CalibdEdx.md

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,43 @@
11
<!-- doxy
2-
\page refTPCcalibrationCalibdEdx dEdx Calibration
2+
\page refTPCcalibrationCalibdEdx Residual dEdx Calibration
33
/doxy -->
44

5-
# dEdx Calibration
5+
# Residual dEdx Calibration
66

7-
The workflow `o2-tpc-miptrack-filter` is supposed to run in the EPNs, and will select only the track inside the defined cuts, the selected track in the streamed with the name `TPC/MIPS/0`. The cut values can be changed with these CLI options:
7+
The workflow `o2-tpc-miptrack-filter` will run on the EPNs. It selects only the tracks inside the defined cuts and stream them with the name `TPC/MIPS/0`. The cut values can be changed with these CLI options:
88

99
```
10-
--min-momentum (= 0.4)
11-
--max-momentum (= 0.6)
12-
--min-clusters (= 60) Minimum number of cluster in a track.
10+
--min-momentum (= 0.3)
11+
--max-momentum (= 0.7)
12+
--min-dedx (= 20) Minimum dEdx cut
13+
--max-dedx (= 200) Maximum dEdx cut
14+
--min-clusters (= 60) Minimum number of cluster in a track
1315
```
1416

15-
The workflow `o2-tpc-calibratordedx` should run in an aggregation node. It will fill dEdx histograms using the data sended by the `o2-tpc-miptrack-filter`, and will compute corrections for the dE/dx values for every time slot.
17+
The workflow `o2-tpc-calibratordedx` should run on an aggregation node. It fills dEdx histograms using the data sent by the `o2-tpc-miptrack-filter`, and computes corrections for the dE/dx values for every time slot.
1618

1719
```
18-
--tf-per-slot
19-
--max-delay
20+
--tf-per-slot TFs per calibration time slot
21+
--max-delay Slots in past to consider
2022
--min-entries Minimum number of entries per GEM stack to perform a fit
2123
22-
--min-entries-sector Bellow the number of entries per stack every sector will be integrated before the fit
23-
--min-entries-1d Minimum entries per stack to perform a 1D fit, bellow it only calculate the mean
24+
--min-entries-sector Minimum entries per GEM stack to enable sector by sector correction. Below this value we only perform one fit per ROC type (IROC, OROC1, ...; no side nor sector information)
25+
--min-entries-1d Minimum entries per stack to perform a 1D fit, bellow it we only calculate the mean of each gem stack
2426
--min-entries-2d Mininum entries per stack to perform a 2D fit
27+
--fit-passes Number of fit iterations
28+
--fit-threshold dEdx cut width around the MIP peak used in the fit
2529
2630
--dedxbins Number of dE/dx bins
27-
--zbins Number of Z bins
2831
--angularbins Number of angular bins, for values like Tgl and Snp
2932
--min-dedx Min. dE/dx value
3033
--max-dedx Max. dE/dx value
34+
--fit-snp Enable Snp correction
3135
3236
--file-dump Save calibration correction to a file
3337
--field Magnetic field in kG, need for track propagations, this value will be overwritten if a grp file is present
3438
```
3539

36-
The workflow `o2-tpc-calibdedx` is similar to `o2-tpc-calibratordedx`, but only compute correction for a single set of data.
40+
The workflow `o2-tpc-calibdedx` is similar to `o2-tpc-calibratordedx`, but compute only one correction using all available time frames.
3741

3842
## Executing
3943

@@ -43,18 +47,18 @@ The full dE/dx calibration workflow can be executed in the following way:
4347
o2-tpc-track-reader --disable-mc | o2-tpc-miptrack-filter | o2-tpc-calibrator-dedx --file-dump --min-entries 100 --tf-per-slot 10
4448
```
4549

46-
Where we enabled the option to save the corrections to a file, set the min. entires per time slot to 100 and defined that the time slots should have 10 time frames.
50+
Where we enabled the option to save the corrections to a file, set the min. entries per time slot to 100 and defined that the time slots should have 10 time frames.
4751

4852
## Simulating EPN workflow
4953

5054
To simulate the EPN/Agregation node topology you can execute the following.
51-
Run the `o2-tpc-miptrack-filter` workflow, it will start listening to `TPC/MIPS/0`, waiting for tracks data to process.
55+
Run `o2-tpc-miptrack-filter` workflow, it will start listening to `TPC/MIPS/0`, waiting for tracks data to process.
5256

5357
```
5458
o2-dpl-raw-proxy --dataspec A:TPC/MIPS/0 --channel-config "name=readout-proxy,type=pull,method=bind,address=tcp://localhost:30453,rateLogging=1,transport=zeromq" | o2-tpc-calib-dedx
5559
```
5660

57-
Now, in a new shell, start the `o2-tpc-miptrack-filter`.
61+
Now, in a new shell, start `o2-tpc-miptrack-filter`.
5862

5963
```
6064
o2-tpc-track-reader --disable-mc | o2-tpc-miptrack-filter | o2-dpl-output-proxy --channel-config "name=downstream,method=connect,address=tcp://localhost:30453,type=push,transport=zeromq" --dataspec downstream:TPC/MIPS -b

0 commit comments

Comments
 (0)