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
16
21#include <cmath>
22#include <TFile.h>
23
25
26namespace o2
27{
28namespace itsmft
29{
31
33
34void BuildTopologyDictionary::accountTopology(const ClusterTopology& cluster, float dX, float dZ)
35{
36 mTotClusters++;
37 bool useDf = dX < IgnoreVal / 2; // we may need to account the frequency but to not update the centroid
38 // std::pair<unordered_map<unsigned long, TopoStat>::iterator,bool> ret;
39 // auto ret = mTopologyMap.insert(std::make_pair(cluster.getHash(), std::make_pair(cluster, 1)));
40
41 auto& topoStat = mTopologyMap[cluster.getHash()];
42 topoStat.countsTotal++;
43 if (topoStat.countsTotal == 1) { // a new topology is inserted
44 topoStat.topology = cluster;
45 //___________________DEFINING_TOPOLOGY_CHARACTERISTICS__________________
46 TopologyInfo topInf;
47 topInf.mPattern.setPattern(cluster.getPattern().data());
48 int& rs = topInf.mSizeX = cluster.getRowSpan();
49 int& cs = topInf.mSizeZ = cluster.getColumnSpan();
50 //__________________COG_Determination_____________
51 topInf.mNpixels = cluster.getClusterPattern().getCOG(topInf.mCOGx, topInf.mCOGz);
52 if (useDf) {
53 topInf.mXmean = dX;
54 topInf.mZmean = dZ;
55 topoStat.countsWithBias = 1;
56 } else { // assign expected sigmas from the pixel X, Z sizes
57 topInf.mXsigma2 = SegmentationAlpide::PitchRow * SegmentationAlpide::PitchRow / 12. / std::min(10, topInf.mSizeX);
58 topInf.mZsigma2 = SegmentationAlpide::PitchCol * SegmentationAlpide::PitchCol / 12. / std::min(10, topInf.mSizeZ);
59 }
60 mMapInfo.insert(std::make_pair(cluster.getHash(), topInf));
61 } else {
62 if (useDf) {
63 auto num = topoStat.countsWithBias++;
64 auto ind = mMapInfo.find(cluster.getHash());
65 float tmpxMean = ind->second.mXmean;
66 float newxMean = ind->second.mXmean = ((tmpxMean)*num + dX) / (num + 1);
67 float tmpxSigma2 = ind->second.mXsigma2;
68 ind->second.mXsigma2 = (num * tmpxSigma2 + (dX - tmpxMean) * (dX - newxMean)) / (num + 1); // online variance algorithm
69 float tmpzMean = ind->second.mZmean;
70 float newzMean = ind->second.mZmean = ((tmpzMean)*num + dZ) / (num + 1);
71 float tmpzSigma2 = ind->second.mZsigma2;
72 ind->second.mZsigma2 = (num * tmpzSigma2 + (dZ - tmpzMean) * (dZ - newzMean)) / (num + 1); // online variance algorithm
73 }
74 }
75}
76
78{
79 mTopologyFrequency.clear();
80 for (auto&& p : mTopologyMap) { // p is pair<ulong,TopoStat>
81 mTopologyFrequency.emplace_back(std::make_pair(p.second.countsTotal, p.first));
82 }
83 std::sort(mTopologyFrequency.begin(), mTopologyFrequency.end(),
84 [](const std::pair<unsigned long, unsigned long>& couple1,
85 const std::pair<unsigned long, unsigned long>& couple2) { return (couple1.first > couple2.first); });
86 mNCommonTopologies = 0;
87 mDictionary.mCommonMap.clear();
88 mDictionary.mGroupMap.clear();
89 mFrequencyThreshold = thr;
90 for (auto& q : mTopologyFrequency) {
91 if (((double)q.first) / mTotClusters > thr) {
92 mNCommonTopologies++;
93 } else {
94 break;
95 }
96 }
97 if (mNCommonTopologies >= CompCluster::InvalidPatternID) {
98 mFrequencyThreshold = ((double)mTopologyFrequency[CompCluster::InvalidPatternID - 1].first) / mTotClusters;
99 LOGP(warning, "Redefining prob. threshould from {} to {} to be below InvalidPatternID (was {})", thr, mFrequencyThreshold, mNCommonTopologies);
100 mNCommonTopologies = CompCluster::InvalidPatternID - 1;
101 }
102}
103
104void BuildTopologyDictionary::setNCommon(unsigned int nCommon)
105{
106 if (nCommon >= CompCluster::InvalidPatternID) {
107 LOGP(warning, "Redefining nCommon from {} to {} to be below InvalidPatternID", nCommon, CompCluster::InvalidPatternID - 1);
108 nCommon = CompCluster::InvalidPatternID - 1;
109 }
110 mTopologyFrequency.clear();
111 for (auto&& p : mTopologyMap) { // p os pair<ulong,TopoStat>
112 mTopologyFrequency.emplace_back(std::make_pair(p.second.countsTotal, p.first));
113 }
114 std::sort(mTopologyFrequency.begin(), mTopologyFrequency.end(),
115 [](const std::pair<unsigned long, unsigned long>& couple1,
116 const std::pair<unsigned long, unsigned long>& couple2) { return (couple1.first > couple2.first); });
117 mNCommonTopologies = nCommon;
118 mDictionary.mCommonMap.clear();
119 mDictionary.mGroupMap.clear();
120 mFrequencyThreshold = ((double)mTopologyFrequency[mNCommonTopologies - 1].first) / mTotClusters;
121}
122
124{
125 mTopologyFrequency.clear();
126 if (cumulative <= 0. || cumulative >= 1.) {
127 cumulative = 0.99;
128 }
129 double totFreq = 0.;
130 for (auto&& p : mTopologyMap) { // p os pair<ulong,TopoStat>
131 mTopologyFrequency.emplace_back(std::make_pair(p.second.countsTotal, p.first));
132 }
133 std::sort(mTopologyFrequency.begin(), mTopologyFrequency.end(),
134 [](const std::pair<unsigned long, unsigned long>& couple1,
135 const std::pair<unsigned long, unsigned long>& couple2) { return (couple1.first > couple2.first); });
136 mNCommonTopologies = 0;
137 mDictionary.mCommonMap.clear();
138 mDictionary.mGroupMap.clear();
139 for (auto& q : mTopologyFrequency) {
140 totFreq += ((double)(q.first)) / mTotClusters;
141 if (totFreq < cumulative) {
142 mNCommonTopologies++;
143 if (mNCommonTopologies >= CompCluster::InvalidPatternID) {
144 totFreq -= ((double)(q.first)) / mTotClusters;
145 mNCommonTopologies--;
146 LOGP(warning, "Redefining cumulative threshould from {} to {} to be below InvalidPatternID)", cumulative, totFreq);
147 }
148 } else {
149 break;
150 }
151 }
152 mFrequencyThreshold = ((double)(mTopologyFrequency[--mNCommonTopologies].first)) / mTotClusters;
153 while (std::fabs(((double)mTopologyFrequency[mNCommonTopologies].first) / mTotClusters - mFrequencyThreshold) < 1.e-15) {
154 mNCommonTopologies--;
155 }
156 mFrequencyThreshold = ((double)mTopologyFrequency[mNCommonTopologies++].first) / mTotClusters;
157}
158
160{
161 std::cout << "Dictionary finalisation" << std::endl;
162 std::cout << "Number of clusters: " << mTotClusters << std::endl;
163
164 double totFreq = 0.;
165 for (int j = 0; j < mNCommonTopologies; j++) {
166 GroupStruct gr;
167 gr.mHash = mTopologyFrequency[j].second;
168 gr.mFrequency = ((double)(mTopologyFrequency[j].first)) / mTotClusters;
169 totFreq += gr.mFrequency;
170 // rough estimation for the error considering a8 uniform distribution
171 gr.mErrX = std::sqrt(mMapInfo.find(gr.mHash)->second.mXsigma2);
172 gr.mErrZ = std::sqrt(mMapInfo.find(gr.mHash)->second.mZsigma2);
173 gr.mErr2X = mMapInfo.find(gr.mHash)->second.mXsigma2;
174 gr.mErr2Z = mMapInfo.find(gr.mHash)->second.mZsigma2;
175 gr.mXCOG = -1 * mMapInfo.find(gr.mHash)->second.mCOGx * o2::itsmft::SegmentationAlpide::PitchRow;
176 gr.mZCOG = mMapInfo.find(gr.mHash)->second.mCOGz * o2::itsmft::SegmentationAlpide::PitchCol;
177 gr.mNpixels = mMapInfo.find(gr.mHash)->second.mNpixels;
178 gr.mPattern = mMapInfo.find(gr.mHash)->second.mPattern;
179 gr.mIsGroup = false;
180 mDictionary.mVectorOfIDs.push_back(gr);
181 if (j == int(CompCluster::InvalidPatternID - 1)) {
182 LOGP(warning, "Limiting N unique topologies to {}, threshold freq. to {}, cumulative freq. to {} to be below InvalidPatternID", j, gr.mFrequency, totFreq);
183 mNCommonTopologies = j;
184 mFrequencyThreshold = gr.mFrequency;
185 break;
186 }
187 }
188 // groupRareTopologies based on binning over number of rows and columns (TopologyDictionary::NumberOfRowClasses *
189 // NumberOfColClasses)
190
191 std::unordered_map<int, std::pair<GroupStruct, unsigned long>> tmp_GroupMap; //<group ID, <Group struct, counts>>
192
193 int grNum = 0;
194 int rowBinEdge = 0;
195 int colBinEdge = 0;
196 for (int iRowClass = 0; iRowClass < TopologyDictionary::MaxNumberOfRowClasses; iRowClass++) {
197 for (int iColClass = 0; iColClass < TopologyDictionary::MaxNumberOfColClasses; iColClass++) {
198 rowBinEdge = (iRowClass + 1) * TopologyDictionary::RowClassSpan;
199 colBinEdge = (iColClass + 1) * TopologyDictionary::ColClassSpan;
200 grNum = LookUp::groupFinder(rowBinEdge, colBinEdge);
201 // Create a structure for a group of rare topologies
202 GroupStruct gr;
203 gr.mHash = (((unsigned long)(grNum)) << 32) & 0xffffffff00000000;
204 gr.mErrX = TopologyDictionary::RowClassSpan * o2::itsmft::SegmentationAlpide::PitchRow / std::sqrt(12 * std::min(10, rowBinEdge));
205 gr.mErrZ = TopologyDictionary::ColClassSpan * o2::itsmft::SegmentationAlpide::PitchCol / std::sqrt(12 * std::min(10, colBinEdge));
206 gr.mErr2X = gr.mErrX * gr.mErrX;
207 gr.mErr2Z = gr.mErrZ * gr.mErrZ;
208 gr.mXCOG = 0;
209 gr.mZCOG = 0;
210 gr.mNpixels = rowBinEdge * colBinEdge;
211 gr.mIsGroup = true;
212 gr.mFrequency = 0.;
214 unsigned char dummyPattern[ClusterPattern::kExtendedPatternBytes] = {0};
215 dummyPattern[0] = (unsigned char)rowBinEdge;
216 dummyPattern[1] = (unsigned char)colBinEdge;
217 int nBits = rowBinEdge * colBinEdge;
218 int nBytes = nBits / 8;
219 for (int iB = 2; iB < nBytes + 2; iB++) {
220 dummyPattern[iB] = (unsigned char)255;
221 }
222 int residualBits = nBits % 8;
223 if (residualBits) {
224 unsigned char tempChar = 0;
225 while (residualBits > 0) {
226 residualBits--;
227 tempChar |= 1 << (7 - residualBits);
228 }
229 dummyPattern[nBytes + 2] = tempChar;
230 }
231 gr.mPattern.setPattern(dummyPattern);
232 // Filling the map for groups
233 tmp_GroupMap[grNum] = std::make_pair(gr, 0);
234 }
235 }
236 int rs;
237 int cs;
238 int index;
239
240 // Updating the counts for the groups of rare topologies
241 for (unsigned int j = (unsigned int)mNCommonTopologies; j < mTopologyFrequency.size(); j++) {
242 unsigned long hash1 = mTopologyFrequency[j].second;
243 rs = mTopologyMap.find(hash1)->second.topology.getRowSpan();
244 cs = mTopologyMap.find(hash1)->second.topology.getColumnSpan();
245 index = LookUp::groupFinder(rs, cs);
246 tmp_GroupMap[index].second += mTopologyFrequency[j].first;
247 }
248
249 for (auto&& p : tmp_GroupMap) {
250 GroupStruct& group = p.second.first;
251 group.mFrequency = ((double)p.second.second) / mTotClusters;
252 mDictionary.mVectorOfIDs.push_back(group);
253 }
254
255 // Sorting the dictionary preserving all unique topologies
256 std::sort(mDictionary.mVectorOfIDs.begin(), mDictionary.mVectorOfIDs.end(), [](const GroupStruct& a, const GroupStruct& b) {
257 return (!a.mIsGroup) && b.mIsGroup ? true : (a.mIsGroup && (!b.mIsGroup) ? false : (a.mFrequency > b.mFrequency));
258 });
259 if (mDictionary.mVectorOfIDs.size() >= CompCluster::InvalidPatternID - 1) {
260 LOGP(warning, "Max allowed {} patterns is reached, stopping", CompCluster::InvalidPatternID - 1);
261 mDictionary.mVectorOfIDs.resize(CompCluster::InvalidPatternID - 1);
262 }
263 // Sorting the dictionary to final form
264 std::sort(mDictionary.mVectorOfIDs.begin(), mDictionary.mVectorOfIDs.end(), [](const GroupStruct& a, const GroupStruct& b) { return a.mFrequency > b.mFrequency; });
265 // Creating the map for common topologies
266 for (int iKey = 0; iKey < mDictionary.getSize(); iKey++) {
267 GroupStruct& gr = mDictionary.mVectorOfIDs[iKey];
268 if (!gr.mIsGroup) {
269 mDictionary.mCommonMap.insert(std::make_pair(gr.mHash, iKey));
270 if (gr.mPattern.getUsedBytes() == 1) {
271 mDictionary.mSmallTopologiesLUT[(gr.mPattern.getColumnSpan() - 1) * 255 + (int)gr.mPattern.mBitmap[2]] = iKey;
272 }
273 } else {
274 mDictionary.mGroupMap.insert(std::make_pair((int)(gr.mHash >> 32) & 0x00000000ffffffff, iKey));
275 }
276 }
277 std::cout << "Dictionay finalised" << std::endl;
278 std::cout << "Number of keys: " << mDictionary.getSize() << std::endl;
279 std::cout << "Number of common topologies: " << mDictionary.mCommonMap.size() << std::endl;
280 std::cout << "Number of groups of rare topologies: " << mDictionary.mGroupMap.size() << std::endl;
281}
282
283std::ostream& operator<<(std::ostream& os, const BuildTopologyDictionary& DB)
284{
285 for (int i = 0; i < DB.mNCommonTopologies; i++) {
286 const unsigned long& hash = DB.mTopologyFrequency[i].second;
287 os << "Hash: " << hash << std::endl;
288 os << "counts: " << DB.mTopologyMap.find(hash)->second.countsTotal;
289 os << " (with bias provided: " << DB.mTopologyMap.find(hash)->second.countsWithBias << ")" << std::endl;
290 os << "sigmaX: " << std::sqrt(DB.mMapInfo.find(hash)->second.mXsigma2) << std::endl;
291 os << "sigmaZ: " << std::sqrt(DB.mMapInfo.find(hash)->second.mZsigma2) << std::endl;
292 os << DB.mTopologyMap.find(hash)->second.topology;
293 }
294 return os;
295}
296
297void BuildTopologyDictionary::printDictionary(const std::string& fname)
298{
299 std::cout << "Saving the the dictionary in binary format: ";
300 std::ofstream out(fname);
301 out << mDictionary;
302 out.close();
303 std::cout << "done!" << std::endl;
304}
305
307{
308 std::cout << "Printing the dictionary: ";
309 std::ofstream out(fname);
310 mDictionary.writeBinaryFile(fname);
311 out.close();
312 std::cout << "done!" << std::endl;
313}
314
316{
317 std::cout << "Saving the the dictionary in a ROOT file: ";
318 TFile output(fname.c_str(), "recreate");
319 output.WriteObjectAny(&mDictionary, mDictionary.Class(), "ccdb_object");
320 output.Close();
321 std::cout << "done!" << std::endl;
322}
323
324} // namespace itsmft
325} // namespace o2
Definition of the ITSMFT compact cluster.
int32_t i
Definition of the BuildTopologyDictionary class.
Definition of the LookUp class.
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.
double num
void accountTopology(const ClusterTopology &cluster, float dX=IgnoreVal, float dZ=IgnoreVal)
void printDictionaryBinary(const std::string &fname)
void printDictionary(const std::string &fname)
void saveDictionaryRoot(const std::string &fname)
int getColumnSpan() const
Returns the number of columns.
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 getUsedBytes() const
Returns the number of bytes used for the pattern.
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 int groupFinder(int nRow, int nCol)
Definition LookUp.cxx:50
static constexpr float PitchCol
static constexpr float PitchRow
static constexpr int ColClassSpan
Column span of the classes of rare topologies.
int getSize() const
Returns the number of elements in the dicionary;.
void writeBinaryFile(const std::string &outputFile)
Prints the dictionary in a binary file.
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.
GLuint index
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLboolean GLuint group
Definition glcorearb.h:3991
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
std::ostream & operator<<(std::ostream &os, const ClusterPattern &pattern)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
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