Project
Loading...
Searching...
No Matches
BuildTopologyDictionary.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13
17
20
21#include "TFile.h"
22
24
25namespace o2::its3
26{
27void BuildTopologyDictionary::accountTopology(const itsmft::ClusterTopology& cluster, bool IB, float dX, float dZ)
28{
29 accountTopologyImpl(cluster,
30 ((IB) ? mMapInfoIB : mMapInfoOB),
31 ((IB) ? mTopologyMapIB : mTopologyMapOB),
32 ((IB) ? mTotClustersIB : mTotClustersOB),
35 dX, dZ);
36}
37
38void BuildTopologyDictionary::accountTopologyImpl(const itsmft::ClusterTopology& cluster, TopoInfo& tinfo, TopoStat& tstat, unsigned int& tot, float sigmaX, float sigmaZ, float dX, float dZ)
39{
40 ++tot;
41 bool useDf = dX < IgnoreVal / 2; // we may need to account the frequency but to not update the centroid
42
43 // std::pair<unordered_map<unsigned long, itsmft::TopoStat>::iterator,bool> ret;
44 // auto ret = mTopologyMap.insert(std::make_pair(cluster.getHash(), std::make_pair(cluster, 1)));
45 auto& topoStat = tstat[cluster.getHash()];
46 topoStat.countsTotal++;
47 if (topoStat.countsTotal == 1) { // a new topology is inserted
48 topoStat.topology = cluster;
49 //___________________DEFINING_TOPOLOGY_CHARACTERISTICS__________________
51 topInf.mPattern.setPattern(cluster.getPattern().data());
52 topInf.mSizeX = cluster.getRowSpan();
53 topInf.mSizeZ = cluster.getColumnSpan();
54 //__________________COG_Determination_____________
55 topInf.mNpixels = cluster.getClusterPattern().getCOG(topInf.mCOGx, topInf.mCOGz);
56 if (useDf) {
57 topInf.mXmean = dX;
58 topInf.mZmean = dZ;
59 topoStat.countsWithBias = 1;
60 } else { // assign expected sigmas from the pixel X, Z sizes
61 topInf.mXsigma2 = sigmaX * sigmaX / 12.f / (float)std::min(10, topInf.mSizeX);
62 topInf.mZsigma2 = sigmaZ * sigmaZ / (float)std::min(10, topInf.mSizeZ);
63 }
64 tinfo.emplace(cluster.getHash(), topInf);
65 } else {
66 if (useDf) {
67 auto num = topoStat.countsWithBias++;
68 auto ind = tinfo.find(cluster.getHash());
69 float tmpxMean = ind->second.mXmean;
70 float newxMean = ind->second.mXmean = ((tmpxMean)*num + dX) / (num + 1);
71 float tmpxSigma2 = ind->second.mXsigma2;
72 ind->second.mXsigma2 = (num * tmpxSigma2 + (dX - tmpxMean) * (dX - newxMean)) / (num + 1); // online variance algorithm
73 float tmpzMean = ind->second.mZmean;
74 float newzMean = ind->second.mZmean = ((tmpzMean)*num + dZ) / (num + 1);
75 float tmpzSigma2 = ind->second.mZsigma2;
76 ind->second.mZsigma2 = (num * tmpzSigma2 + (dZ - tmpzMean) * (dZ - newzMean)) / (num + 1); // online variance algorithm
77 }
78 }
79}
80
81void BuildTopologyDictionary::setNCommon(unsigned int nCommon, bool IB)
82{
83 mDictionary.resetMaps(IB);
84
85 auto& freqTopo = ((IB) ? mTopologyFrequencyIB : mTopologyFrequencyOB);
86 auto& freqThres = ((IB) ? mFrequencyThresholdIB : mFrequencyThresholdOB);
87 auto& comTopo = ((IB) ? mNCommonTopologiesIB : mNCommonTopologiesOB);
88 auto ntot = ((IB) ? mTotClustersIB : mTotClustersOB);
89
90 setNCommonImpl(nCommon,
91 freqTopo,
92 ((IB) ? mTopologyMapIB : mTopologyMapOB),
93 comTopo,
94 ntot);
95 // Recaculate also the threshold
96 freqThres = ((double)freqTopo[comTopo - 1].first) / ntot;
97}
98
99void BuildTopologyDictionary::setNCommonImpl(unsigned int ncom, TopoFreq& tfreq, TopoStat& tstat, unsigned int& ncommon, unsigned int ntot)
100{
102 LOGP(warning, "Redefining nCommon from {} to {} to be below InvalidPatternID", ncom, itsmft::CompCluster::InvalidPatternID - 1);
104 }
105 tfreq.clear();
106 for (auto&& p : tstat) { // p os pair<ulong,TopoStat>
107 tfreq.emplace_back(p.second.countsTotal, p.first);
108 }
109 std::sort(tfreq.begin(), tfreq.end(),
110 [](const std::pair<unsigned long, unsigned long>& couple1,
111 const std::pair<unsigned long, unsigned long>& couple2) { return (couple1.first > couple2.first); });
112 ncommon = ncom;
113}
114
116{
117 mDictionary.resetMaps(IB);
118 setThresholdImpl(thr,
119 ((IB) ? mTopologyFrequencyIB : mTopologyFrequencyOB),
120 ((IB) ? mMapInfoIB : mMapInfoOB),
121 ((IB) ? mTopologyMapIB : mTopologyMapOB),
122 ((IB) ? mNCommonTopologiesIB : mNCommonTopologiesOB),
123 ((IB) ? mFrequencyThresholdIB : mFrequencyThresholdOB),
124 ((IB) ? mTotClustersIB : mTotClustersOB));
125}
126
127void BuildTopologyDictionary::setThresholdImpl(double thr, TopoFreq& tfreq, TopoInfo& tinfo, TopoStat& tstat, unsigned int& ncommon, double& freqthres, unsigned int ntot)
128{
129 setNCommonImpl(0, tfreq, tstat, ncommon, ntot);
130 freqthres = thr;
131 for (auto& q : tfreq) {
132 if (((double)q.first) / ntot > thr) {
133 ++ncommon;
134 } else {
135 break;
136 }
137 }
139 freqthres = ((double)tfreq[itsmft::CompCluster::InvalidPatternID - 1].first) / ntot;
140 LOGP(warning, "Redefining prob. threshold from {} to {} to be below InvalidPatternID (was {})", thr, freqthres, ntot);
142 }
143}
144
146{
147 if (cumulative <= 0. || cumulative >= 1.) {
148 cumulative = 0.99;
149 }
150
151 auto& freqTopo = ((IB) ? mTopologyFrequencyIB : mTopologyFrequencyOB);
152 auto& freqThres = ((IB) ? mFrequencyThresholdIB : mFrequencyThresholdOB);
153 auto& statTopo = ((IB) ? mTopologyMapIB : mTopologyMapOB);
154 auto& comTopo = ((IB) ? mNCommonTopologiesIB : mNCommonTopologiesOB);
155 auto ntot = ((IB) ? mTotClustersIB : mTotClustersOB);
156
157 mDictionary.resetMaps(IB);
158 setNCommonImpl(0, freqTopo, statTopo, comTopo, ntot);
159 setThresholdCumulativeImpl(cumulative, freqTopo, comTopo, freqThres, ntot);
160}
161
162void BuildTopologyDictionary::setThresholdCumulativeImpl(double cumulative, TopoFreq& tfreq, unsigned int& ncommon, double& freqthres, unsigned int ntot)
163{
164 double totFreq = 0.;
165 for (auto& q : tfreq) {
166 totFreq += ((double)(q.first)) / ntot;
167 if (totFreq < cumulative) {
168 ++ncommon;
170 totFreq -= ((double)(q.first)) / ntot;
171 --ncommon;
172 LOGP(warning, "Redefining cumulative threshould from {} to {} to be below InvalidPatternID)", cumulative, totFreq);
173 }
174 } else {
175 break;
176 }
177 }
178 freqthres = ((double)(tfreq[--ncommon].first)) / ntot;
179 while (std::fabs(((double)tfreq[ncommon--].first) / ntot - freqthres) < 1.e-15) {
180 }
181 freqthres = ((double)tfreq[ncommon++].first) / ntot;
182}
183
185{
186 LOG(info) << "Dictionary finalisation";
187 LOG(info) << "Number of IB clusters: " << mTotClustersIB;
188 LOG(info) << "Number of OB clusters: " << mTotClustersOB;
189
190 groupRareTopologiesImpl(mTopologyFrequencyIB, mMapInfoIB, mTopologyMapIB, mNCommonTopologiesIB, mFrequencyThresholdIB, mDictionary.mDataIB, mNCommonTopologiesIB);
191 groupRareTopologiesImpl(mTopologyFrequencyOB, mMapInfoOB, mTopologyMapOB, mNCommonTopologiesOB, mFrequencyThresholdOB, mDictionary.mDataOB, mNCommonTopologiesOB);
192
193 LOG(info) << "Dictionay finalised";
194 LOG(info) << "IB:";
195 mDictionary.mDataIB.print();
196 LOG(info) << "OB:";
197 mDictionary.mDataOB.print();
198}
199
200void BuildTopologyDictionary::groupRareTopologiesImpl(TopoFreq& tfreq, TopoInfo& tinfo, TopoStat& tstat, unsigned int& ncommon, double& freqthres, TopologyDictionaryData& data, unsigned int ntot)
201{
202 double totFreq = 0.;
203 for (unsigned int j = 0; j < ncommon; j++) {
205 gr.mHash = tfreq[j].second;
206 gr.mFrequency = ((double)(tfreq[j].first)) / ntot;
207 totFreq += gr.mFrequency;
208 // rough estimation for the error considering a8 uniform distribution
209 const auto& topo = tinfo.find(gr.mHash)->second;
210 gr.mErrX = std::sqrt(topo.mXsigma2);
211 gr.mErrZ = std::sqrt(topo.mZsigma2);
212 gr.mErr2X = topo.mXsigma2;
213 gr.mErr2Z = topo.mZsigma2;
214 gr.mXCOG = -1 * topo.mCOGx;
215 gr.mZCOG = topo.mCOGz;
216 gr.mNpixels = topo.mNpixels;
217 gr.mPattern = topo.mPattern;
218 gr.mIsGroup = false;
219 data.mVectorOfIDs.push_back(gr);
221 LOGP(warning, "Limiting N unique topologies to {}, threshold freq. to {}, cumulative freq. to {} to be below InvalidPatternID", j, gr.mFrequency, totFreq);
222 ncommon = j;
223 freqthres = gr.mFrequency;
224 break;
225 }
226 }
227 // groupRareTopologies based on binning over number of rows and columns (TopologyDictionary::NumberOfRowClasses *
228 // NumberOfColClasses)
229
230 std::unordered_map<int, std::pair<itsmft::GroupStruct, unsigned long>> tmp_GroupMap; //<group ID, <Group struct, counts>>
231
232 int grNum = 0;
233 int rowBinEdge = 0;
234 int colBinEdge = 0;
235 for (int iRowClass = 0; iRowClass < its3::TopologyDictionary::MaxNumberOfRowClasses; iRowClass++) {
236 for (int iColClass = 0; iColClass < its3::TopologyDictionary::MaxNumberOfColClasses; iColClass++) {
237 rowBinEdge = (iRowClass + 1) * its3::TopologyDictionary::RowClassSpan;
238 colBinEdge = (iColClass + 1) * its3::TopologyDictionary::ColClassSpan;
239 grNum = its3::LookUp::groupFinder(rowBinEdge, colBinEdge);
240 // Create a structure for a group of rare topologies
241 itsmft::GroupStruct gr;
242 gr.mHash = (((unsigned long)(grNum)) << 32) & 0xffffffff00000000;
243 gr.mErrX = its3::TopologyDictionary::RowClassSpan / std::sqrt(12.f * (float)std::min(10, rowBinEdge));
244 gr.mErrZ = its3::TopologyDictionary::ColClassSpan / std::sqrt(12.f * (float)std::min(10, colBinEdge));
245 gr.mErr2X = gr.mErrX * gr.mErrX;
246 gr.mErr2Z = gr.mErrZ * gr.mErrZ;
247 gr.mXCOG = 0;
248 gr.mZCOG = 0;
249 gr.mNpixels = rowBinEdge * colBinEdge;
250 gr.mIsGroup = true;
251 gr.mFrequency = 0.;
253 unsigned char dummyPattern[itsmft::ClusterPattern::kExtendedPatternBytes] = {0};
254 dummyPattern[0] = (unsigned char)rowBinEdge;
255 dummyPattern[1] = (unsigned char)colBinEdge;
256 int nBits = rowBinEdge * colBinEdge;
257 int nBytes = nBits / 8;
258 for (int iB = 2; iB < nBytes + 2; iB++) {
259 dummyPattern[iB] = (unsigned char)255;
260 }
261 int residualBits = nBits % 8;
262 if (residualBits != 0) {
263 unsigned char tempChar = 0;
264 while (residualBits > 0) {
265 residualBits--;
266 tempChar |= 1 << (7 - residualBits);
267 }
268 dummyPattern[nBytes + 2] = tempChar;
269 }
270 gr.mPattern.setPattern(dummyPattern);
271 // Filling the map for groups
272 tmp_GroupMap[grNum] = std::make_pair(gr, 0);
273 }
274 }
275 int rs{}, cs{}, index{};
276
277 // Updating the counts for the groups of rare topologies
278 for (auto j{ncommon}; j < tfreq.size(); j++) {
279 unsigned long hash1 = tfreq[j].second;
280 rs = tstat.find(hash1)->second.topology.getRowSpan();
281 cs = tstat.find(hash1)->second.topology.getColumnSpan();
283 tmp_GroupMap[index].second += tfreq[j].first;
284 }
285
286 for (auto&& p : tmp_GroupMap) {
287 itsmft::GroupStruct& group = p.second.first;
288 group.mFrequency = ((double)p.second.second) / ntot;
289 data.mVectorOfIDs.push_back(group);
290 }
291
292 // Sorting the dictionary preserving all unique topologies
293 std::sort(data.mVectorOfIDs.begin(), data.mVectorOfIDs.end(), [](const itsmft::GroupStruct& a, const itsmft::GroupStruct& b) {
294 return (!a.mIsGroup) && b.mIsGroup ? true : (a.mIsGroup && (!b.mIsGroup) ? false : (a.mFrequency > b.mFrequency));
295 });
296 if (data.mVectorOfIDs.size() >= itsmft::CompCluster::InvalidPatternID - 1) {
297 LOGP(warning, "Max allowed {} patterns is reached, stopping", itsmft::CompCluster::InvalidPatternID - 1);
298 data.mVectorOfIDs.resize(itsmft::CompCluster::InvalidPatternID - 1);
299 }
300 // Sorting the dictionary to final form
301 std::sort(data.mVectorOfIDs.begin(), data.mVectorOfIDs.end(), [](const itsmft::GroupStruct& a, const itsmft::GroupStruct& b) { return a.mFrequency > b.mFrequency; });
302 // Creating the map for common topologies
303 for (int iKey = 0; iKey < data.mVectorOfIDs.size(); iKey++) {
304 itsmft::GroupStruct& gr = data.mVectorOfIDs[iKey];
305 if (!gr.mIsGroup) {
306 data.mCommonMap.emplace(gr.mHash, iKey);
307 if (gr.mPattern.getUsedBytes() == 1) {
308 data.mSmallTopologiesLUT[(gr.mPattern.getColumnSpan() - 1) * 255 + (int)gr.mPattern.getByte(2)] = iKey;
309 }
310 } else {
311 data.mGroupMap.emplace((int)(gr.mHash >> 32) & 0x00000000ffffffff, iKey);
312 }
313 }
314}
315
316std::ostream& operator<<(std::ostream& os, const BuildTopologyDictionary& DB)
317{
318 os << "--- InnerBarrel\n";
319 for (unsigned int i = 0; i < DB.mNCommonTopologiesIB; i++) {
320 const unsigned long& hash = DB.mTopologyFrequencyIB[i].second;
321 os << "Hash: " << hash << '\n';
322 os << "counts: " << DB.mTopologyMapIB.find(hash)->second.countsTotal;
323 os << " (with bias provided: " << DB.mTopologyMapIB.find(hash)->second.countsWithBias << ")" << '\n';
324 os << "sigmaX: " << std::sqrt(DB.mMapInfoIB.find(hash)->second.mXsigma2) << '\n';
325 os << "sigmaZ: " << std::sqrt(DB.mMapInfoIB.find(hash)->second.mZsigma2) << '\n';
326 os << DB.mTopologyMapIB.find(hash)->second.topology;
327 }
328 os << "--- OuterBarrel\n";
329 for (unsigned int i = 0; i < DB.mNCommonTopologiesOB; i++) {
330 const unsigned long& hash = DB.mTopologyFrequencyOB[i].second;
331 os << "Hash: " << hash << '\n';
332 os << "counts: " << DB.mTopologyMapOB.find(hash)->second.countsTotal;
333 os << " (with bias provided: " << DB.mTopologyMapOB.find(hash)->second.countsWithBias << ")" << '\n';
334 os << "sigmaX: " << std::sqrt(DB.mMapInfoOB.find(hash)->second.mXsigma2) << '\n';
335 os << "sigmaZ: " << std::sqrt(DB.mMapInfoOB.find(hash)->second.mZsigma2) << '\n';
336 os << DB.mTopologyMapOB.find(hash)->second.topology;
337 }
338 return os;
339}
340
341void BuildTopologyDictionary::printDictionary(const std::string& fname)
342{
343 LOG(info) << "Saving the the dictionary in binary format: ";
344 std::ofstream out(fname);
345 out << mDictionary;
346 out.close();
347 LOG(info) << " `-> done!";
348}
349
351{
352 LOG(info) << "Printing the dictionary: ";
353 std::ofstream out(fname);
354 mDictionary.writeBinaryFile(fname);
355 out.close();
356 LOG(info) << " `-> done!";
357}
358
360{
361 LOG(info) << "Saving the the dictionary in a ROOT file: " << fname;
362 TFile output(fname.c_str(), "recreate");
363 output.WriteObjectAny(&mDictionary, mDictionary.Class(), "ccdb_object");
364 output.Close();
365 LOG(info) << " `-> done!";
366}
367
368} // namespace o2::its3
Definition of the ITSMFT compact cluster.
int32_t i
ClassImp(o2::itsmft::BuildTopologyDictionary)
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
uint32_t j
Definition RawData.h:0
Definition of the SegmentationAlpide class.
Definition of the SegmentationMosaix class.
Definition of the LookUp class for its3.
double num
void saveDictionaryRoot(const std::string &fname)
void setNCommon(unsigned int nCommon, bool IB)
void setThresholdCumulative(double cumulative, bool IB)
void accountTopology(const itsmft::ClusterTopology &cluster, bool IB, float dX=IgnoreVal, float dZ=IgnoreVal)
void printDictionary(const std::string &fname)
void printDictionaryBinary(const std::string &fname)
static int groupFinder(int nRow, int nCol)
Definition LookUp.cxx:47
static constexpr float PitchCol
static constexpr float PitchRow
static constexpr int ColClassSpan
Column span of the classes of rare topologies.
static constexpr int MaxNumberOfRowClasses
Maximum number of row classes for the groups of rare topologies.
static constexpr int MaxNumberOfColClasses
Maximum number of col classes for the groups of rare topologies.
static constexpr int RowClassSpan
Row span of the classes of rare topologies.
void writeBinaryFile(const std::string &outputFile)
Prints the dictionary in a binary file.
void resetMaps(bool IB=true) noexcept
static int getCOG(int rowSpan, int colSpan, const unsigned char patt[MaxPatternBytes], float &xCOG, float &zCOG)
Static: Compute pattern's COG position. Returns the number of fired pixels.
void setPattern(int nRow, int nCol, const unsigned char patt[MaxPatternBytes])
Sets the pattern.
static constexpr int kExtendedPatternBytes
Maximum number of bytes for the cluster puttern + 2 bytes respectively for the number of rows and col...
int getRowSpan() const
Returns the number of rows.
int getColumnSpan() const
Returns the number of columns.
const std::array< unsigned char, ClusterPattern::kExtendedPatternBytes > & getPattern() const
Returns the pattern.
unsigned long getHash() const
Returns the hashcode.
const ClusterPattern & getClusterPattern() const
static constexpr unsigned short InvalidPatternID
Definition CompCluster.h:46
static constexpr float PitchCol
static constexpr float PitchRow
GLuint index
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLboolean * data
Definition glcorearb.h:298
GLboolean GLuint group
Definition glcorearb.h:3991
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
std::ostream & operator<<(std::ostream &os, const BuildTopologyDictionary &DB)
Structure containing the most relevant pieces of information of a topology.
float mErrX
Error associated to the hit point in the x direction.
float mErr2X
Squared Error associated to the hit point in the x direction.
float mErrZ
Error associated to the hit point in the z direction.
unsigned long mHash
Hashcode.
float mXCOG
x position of the COG wrt the bottom left corner of the bounding box
int mNpixels
Number of fired pixels.
double mFrequency
Frequency of the topology.
bool mIsGroup
false: common topology; true: group of rare topologies
float mErr2Z
Squared Error associated to the hit point in the z direction.
float mZCOG
z position of the COG wrt the bottom left corner of the bounding box
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"