From 7964061d52fcd22ecdd753433b845b5391ae64a3 Mon Sep 17 00:00:00 2001 From: Luca Barioglio Date: Fri, 25 May 2018 09:37:27 +0200 Subject: [PATCH 1/2] Add ClasterPattern classes and lookup table for small topologies. ClusterPattern includes a bitmap with the number of rows and the number of columns in the first two bytes. The remaining bytes contain the very bitmap of the cluster. The dictionary now contains a lookup table with the group ID corresponding to the topologis whose bitmap can be contained in a single byte. --- .../Detectors/ITSMFT/common/CMakeLists.txt | 4 +- .../DataFormatsITSMFT/ClusterPattern.h | 83 ++++++++++++++++ .../DataFormatsITSMFT/ClusterTopology.h | 32 ++----- .../DataFormatsITSMFT/TopologyDictionary.h | 32 ++++--- .../ITSMFT/common/src/ClusterPattern.cxx | 96 +++++++++++++++++++ .../ITSMFT/common/src/ClusterTopology.cxx | 61 ++++-------- .../common/src/ITSMFTDataFormatsLinkDef.h | 1 + .../ITSMFT/common/src/TopologyDictionary.cxx | 32 ++----- .../BuildTopologyDictionary.h | 9 +- .../include/ITSMFTReconstruction/LookUp.h | 2 +- .../src/BuildTopologyDictionary.cxx | 32 ++++++- .../common/reconstruction/src/LookUp.cxx | 19 +++- 12 files changed, 289 insertions(+), 114 deletions(-) create mode 100644 DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h create mode 100644 DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx diff --git a/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt b/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt index c451f8de12233..e193dc1cd5db1 100644 --- a/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt +++ b/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt @@ -4,12 +4,14 @@ O2_SETUP(NAME ${MODULE_NAME}) set(SRCS src/Cluster.cxx + src/ClusterPattern.cxx src/ClusterTopology.cxx src/TopologyDictionary.cxx ) Set(HEADERS include/${MODULE_NAME}/Cluster.h + include/${MODULE_NAME}/ClusterPattern.h include/${MODULE_NAME}/ClusterTopology.h include/${MODULE_NAME}/TopologyDictionary.h ) @@ -19,5 +21,3 @@ Set(LIBRARY_NAME ${MODULE_NAME}) set(BUCKET_NAME data_format_itsmft_bucket) O2_GENERATE_LIBRARY() - - diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h new file mode 100644 index 0000000000000..d925abe59a6bc --- /dev/null +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h @@ -0,0 +1,83 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file ClusterTopology.h +/// \brief Definition of the ClusterTopology class. +/// +/// \author Luca Barioglio, University and INFN of Torino +/// +/// Short ClusterPattern descritpion +/// +/// This class contains the information of the pattern of a cluster of pixels (bitmask), together with the number of +/// rows and columns of the vinding box. +/// + +#ifndef ALICEO2_ITSMFT_CLUSTERPATTERN_H +#define ALICEO2_ITSMFT_CLUSTERPATTERN_H +#include +#include +#include +#include "DataFormatsITSMFT/Cluster.h" + +namespace o2 +{ +namespace ITSMFT +{ +class ClusterTopology; +class TopologyDictionary; +class BuildTopologyDictionary; + +class ClusterPattern +{ + public: + /// Default constructor + ClusterPattern(); + /// Standard constructor + ClusterPattern(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]); + /// Returns the pattern + void getPattern(unsigned char destination[Cluster::kMaxPatternBytes + 2]) const + { + memcpy(destination, mBitmap, Cluster::kMaxPatternBytes + 2); + } + /// Returns a specific byte of the pattern + unsigned char getByte(int n) const; + /// Returns the number of rows + int getRowSpan() const { return (int)mBitmap[0]; } + /// Returns the number of columns + int getColumnSpan() const { return (int)mBitmap[1]; } + /// Returns the number of bytes used for the pattern + int getUsedBytes() const; + /// Prints the pattern + friend std::ostream& operator<<(std::ostream& os, const ClusterPattern& top); + /// Sets the pattern + void setPattern(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]); + /// Sets the whole bitmask: the number of rows, the number of columns and the pattern + void setPattern(const unsigned char bitmask[Cluster::kMaxPatternBytes + 2]); + + friend ClusterTopology; + friend TopologyDictionary; + friend BuildTopologyDictionary; + + private: + /// Pattern: + /// + /// - 1st byte: number of rows + /// - 2nd byte: number of columns + /// - remainig bytes : pixels of the cluster, where 1 is a fired pixel and 0 + /// is a non-fired pixel. The number of bytes used for the pixels depends on + /// the size of the bounding box + unsigned char + mBitmap[Cluster::kMaxPatternBytes + 2]; ///< Cluster pattern: 1 is a fired pixel and 0 is a non-fired pixel + + ClassDefNV(ClusterPattern, 1); +}; +} +} +#endif /* ALICEO2_ITS_CLUSTERPATTERN_H */ diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h index 0cc7026853bf5..ed9bbabe9ec4e 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h @@ -22,11 +22,7 @@ #ifndef ALICEO2_ITSMFT_CLUSTERTOPOLOGY_H #define ALICEO2_ITSMFT_CLUSTERTOPOLOGY_H -#include -#include -#include -#include -#include "DataFormatsITSMFT/Cluster.h" +#include "DataFormatsITSMFT/ClusterPattern.h" namespace o2 { @@ -40,14 +36,16 @@ class ClusterTopology /// Standard constructor ClusterTopology(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]); + /// Returns a specific byte of the pattern + unsigned char getByte(int n) const { return mPattern.getByte(n); } /// Returns the pattern - const std::array& getPattern() const { return mPattern; } + void getPattern(unsigned char destination[Cluster::kMaxPatternBytes + 2]) const { mPattern.getPattern(destination); } /// Returns the number of rows - int getRowSpan() const { return (int)mPattern[0]; } + int getRowSpan() const { return mPattern.getRowSpan(); } /// Returns the number of columns - int getColumnSpan() const { return (int)mPattern[1]; } + int getColumnSpan() const { return mPattern.getColumnSpan(); } /// Returns the number of used bytes - int getUsedBytes() const { return mNbytes; } + int getUsedBytes() const { return mPattern.getUsedBytes(); } /// Returns the hashcode unsigned long getHash() const { return mHash; } /// Prints the topology @@ -55,23 +53,13 @@ class ClusterTopology /// MurMur2 hash fucntion static unsigned int hashFunction(const void* key, int len); /// Compute the complete hash as defined for mHash - static unsigned long getCompleteHash(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes], - int nBytesUsed); + static unsigned long getCompleteHash(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]); static unsigned long getCompleteHash(const ClusterTopology& topology); /// Sets the pattern void setPattern(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]); private: - /// Pattern: - /// - /// - 1st byte: number of rows - /// - 2nd byte: number of columns - /// - remainig bytes : pixels of the cluster, where 1 is a fired pixel and 0 - /// is a non-fired pixel. The number of pixels used for the pixel depends on - /// the size of the bounding box - std::array - mPattern; ///< Cluster pattern: 1 is a fired pixel and 0 is a non-fired pixel - int mNbytes; ///< Number of bytes that are effectively used in mPattern + ClusterPattern mPattern; ///< Pattern of pixels /// Hashcode computed from the pattern /// /// The first four bytes are computed with MurMur2 hash-function. The remaining @@ -79,7 +67,7 @@ class ClusterTopology /// is less than 32, the remaining bits are set to 0. unsigned long mHash; - ClassDefNV(ClusterTopology, 1); + ClassDefNV(ClusterTopology, 2); }; } // namespace ITSMFT } // namespace o2 diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h index 59996857aba73..05fd2f1ad47a1 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h @@ -15,21 +15,21 @@ /// /// Short TopologyDictionary descritpion /// -/// The entries of the dictionaries are the cluster topologies, with all the indormation +/// The entries of the dictionaries are the cluster topologies, with all the information /// which is common to the clusters with the same topology: /// - number of rows /// - number of columns +/// - pixel bitmask /// - position of the Centre Of Gravity (COG) wrt the bottom left corner pixel of the bounding box /// - error associated to the position of the hit point /// Rare topologies, i.e. with a frequency below a threshold defined a priori, have not their own entries /// in the dictionaries, but are grouped together with topologies with similar dimensions. -/// +/// For the groups of rare topollogies a dummy bitmask is used. #ifndef ALICEO2_ITSMFT_TOPOLOGYDICTIONARY_H #define ALICEO2_ITSMFT_TOPOLOGYDICTIONARY_H -#include +#include "DataFormatsITSMFT/ClusterPattern.h" #include -#include #include #include #include @@ -44,18 +44,23 @@ class TopologyFastSimulation; /// Structure containing the most relevant pieces of information of a topology struct GroupStruct { - unsigned long mHash; ///< Hashcode - float mErrX; ///< Error associated to the hit point in the x direction. - float mErrZ; ///< Error associated to the hit point in the z direction. - float mXCOG; ///< x position of te COG wrt the boottom left corner of the bounding box - float mZCOG; ///< z position of te COG wrt the boottom left corner of the bounding box - int mNpixels; ///< Number of fired pixels - double mFrequency; ///< Frequency of the topology + unsigned long mHash; ///< Hashcode + float mErrX; ///< Error associated to the hit point in the x direction. + float mErrZ; ///< Error associated to the hit point in the z direction. + float mXCOG; ///< x position of te COG wrt the boottom left corner of the bounding box + float mZCOG; ///< z position of te COG wrt the boottom left corner of the bounding box + int mNpixels; ///< Number of fired pixels + ClusterPattern mPattern; ///< Bitmask of pixels. For groups the biggest bounding box for the group is taken, with all + ///the bits set to 1. + double mFrequency; ///< Frequency of the topology }; class TopologyDictionary { public: + + /// Default constructor + TopologyDictionary(); /// constexpr for the definition of the groups of rare topologies static constexpr int NumberOfRowClasses = 7; ///< Number of row classes for the groups of rare topologies static constexpr int NumberOfColClasses = 7; ///< Number of column classes for the groups of rare topologies @@ -67,8 +72,6 @@ class TopologyDictionary friend std::ostream& operator<<(std::ostream& os, const TopologyDictionary& dictionary); /// Prints the dictionary in a binary file void WriteBinaryFile(std::string outputFile); - /// Reads the dictionary from a file - void ReadFile(std::string fileName); /// Reads the dictionary from a binary file void ReadBinaryFile(std::string fileName); friend BuildTopologyDictionary; @@ -77,9 +80,10 @@ class TopologyDictionary private: std::unordered_map mFinalMap; ///< Map of pair + int mSmallTopologiesLUT[8 * 255]; ///< Look-Up Table for the topologies with 1-byte linearised matrix std::vector mVectorOfGroupIDs; ///< Vector of topologies and groups - ClassDefNV(TopologyDictionary, 1); + ClassDefNV(TopologyDictionary, 2); }; } // namespace ITSMFT } // namespace o2 diff --git a/DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx b/DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx new file mode 100644 index 0000000000000..fdc25f9842d84 --- /dev/null +++ b/DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx @@ -0,0 +1,96 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file ClusterTopology.cxx +/// \brief Implementation of the ClusterPattern class. +/// +/// \author Luca Barioglio, University and INFN of Torino +#include "DataFormatsITSMFT/ClusterTopology.h" +#include + +ClassImp(o2::ITSMFT::ClusterPattern) + + namespace o2 +{ + namespace ITSMFT + { + ClusterPattern::ClusterPattern() : mBitmap{ 0 } {} + + ClusterPattern::ClusterPattern(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]) + { + setPattern(nRow, nCol, patt); + } + + unsigned char ClusterPattern::getByte(int n) const + { + if (n < 0 || n > Cluster::kMaxPatternBytes + 1) { + std::cout << "Invalid element of the pattern" << std::endl; + return -1; + } else { + return mBitmap[n]; + } + } + + int ClusterPattern::getUsedBytes() const + { + int nBits = (int)mBitmap[0] * (int)mBitmap[1]; + int nBytes = nBits / 8; + if (nBits % 8 != 0) + nBytes++; + return nBytes; + } + + void ClusterPattern::setPattern(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]) + { + mBitmap[0] = (unsigned char)nRow; + mBitmap[1] = (unsigned char)nCol; + int nBytes = nRow * nCol / 8; + if (((nRow * nCol) % 8) != 0) + nBytes++; + memcpy(&mBitmap[2], patt, nBytes); + } + + void ClusterPattern::setPattern(const unsigned char patt[Cluster::kMaxPatternBytes + 2]) + { + memcpy(&mBitmap[0], patt, Cluster::kMaxPatternBytes + 2); + } + + std::ostream& operator<<(std::ostream& os, const ClusterPattern& pattern) + { + os << "rowSpan: " << pattern.getRowSpan() << " columnSpan: " << pattern.getColumnSpan() + << " #bytes: " << pattern.getUsedBytes() << std::endl; + unsigned char tempChar = 0; + int s = 0; + int ic = 0; + for (unsigned int i = 2; i < pattern.getUsedBytes() + 2; i++) { + tempChar = pattern.mBitmap[i]; + s = 128; // 0b10000000 + while (s > 0) { + if (ic % pattern.getColumnSpan() == 0) + os << "|"; + ic++; + if ((tempChar & s) != 0) + os << '+'; + else + os << ' '; + s /= 2; + if (ic % pattern.getColumnSpan() == 0) + os << "|" << std::endl; + if (ic == (pattern.getRowSpan() * pattern.getColumnSpan())) + break; + } + if (ic == (pattern.getRowSpan() * pattern.getColumnSpan())) + break; + } + os << std::endl; + return os; + } + } +} diff --git a/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx b/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx index f3dee30589c26..5948da5942349 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx @@ -22,7 +22,7 @@ ClassImp(o2::ITSMFT::ClusterTopology) { namespace ITSMFT { - ClusterTopology::ClusterTopology() : mPattern{ 0 }, mHash{ 0 }, mNbytes{ 0 } {} + ClusterTopology::ClusterTopology() : mPattern{}, mHash{ 0 } {} ClusterTopology::ClusterTopology(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]) : mHash{ 0 } { @@ -31,12 +31,7 @@ ClassImp(o2::ITSMFT::ClusterTopology) void ClusterTopology::setPattern(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]) { - mPattern[0] = (unsigned char)nRow; - mPattern[1] = (unsigned char)nCol; - mNbytes = nRow * nCol / 8; - if (((nRow * nCol) % 8) != 0) - mNbytes++; - memcpy(&mPattern[2], patt, mNbytes); + mPattern.setPattern(nRow, nCol, patt); mHash = getCompleteHash(*this); } @@ -82,26 +77,30 @@ ClassImp(o2::ITSMFT::ClusterTopology) } unsigned long ClusterTopology::getCompleteHash(int nRow, int nCol, - const unsigned char patt[Cluster::kMaxPatternBytes], int nBytesUsed) + const unsigned char patt[Cluster::kMaxPatternBytes]) { - unsigned long extended_pattern[Cluster::kMaxPatternBytes + 2] = { 0 }; + unsigned char extended_pattern[Cluster::kMaxPatternBytes + 2] = { 0 }; extended_pattern[0] = (unsigned char)nRow; extended_pattern[1] = (unsigned char)nCol; - memcpy(&extended_pattern[2], patt, nBytesUsed); + int nBits = nRow * nCol; + int nBytes = nBits / 8; + if (nBits % 8 != 0) + nBytes++; + memcpy(&extended_pattern[2], patt, nBytes); - unsigned long partialHash = (unsigned long)hashFunction(extended_pattern, nBytesUsed); + unsigned long partialHash = (unsigned long)hashFunction(extended_pattern, nBytes); // The first four bytes are directly taken from partialHash unsigned long completeHash = partialHash << 32; // The last four bytes of the hash are the first 32 pixels of the topology. // The bits reserved for the pattern that are not used are set to 0. - if (nBytesUsed == 1) { + if (nBytes == 1) { completeHash += ((((unsigned long)extended_pattern[2]) << 24)); - } else if (nBytesUsed == 2) { + } else if (nBytes == 2) { completeHash += ((((unsigned long)extended_pattern[2]) << 24) + (((unsigned long)extended_pattern[3]) << 16)); - } else if (nBytesUsed == 3) { + } else if (nBytes == 3) { completeHash += ((((unsigned long)extended_pattern[2]) << 24) + (((unsigned long)extended_pattern[3]) << 16) + (((unsigned long)extended_pattern[4]) << 8)); - } else if (nBytesUsed >= 4) { + } else if (nBytes >= 4) { completeHash += ((((unsigned long)extended_pattern[2]) << 24) + (((unsigned long)extended_pattern[3]) << 16) + (((unsigned long)extended_pattern[4]) << 8) + ((unsigned long)extended_pattern[5])); } else { @@ -113,9 +112,10 @@ ClassImp(o2::ITSMFT::ClusterTopology) unsigned long ClusterTopology::getCompleteHash(const ClusterTopology& topology) { - std::array patt = topology.getPattern(); + unsigned char patt[Cluster::kMaxPatternBytes + 2]; + topology.getPattern(patt); int nBytesUsed = topology.getUsedBytes(); - unsigned long partialHash = (unsigned long)hashFunction(patt.data(), nBytesUsed); + unsigned long partialHash = (unsigned long)hashFunction(patt, nBytesUsed); // The first four bytes are directly taken from partialHash unsigned long completeHash = partialHash << 32; // The last four bytes of the hash are the first 32 pixels of the topology. @@ -139,32 +139,7 @@ ClassImp(o2::ITSMFT::ClusterTopology) std::ostream& operator<<(std::ostream& os, const ClusterTopology& topology) { - os << "rowSpan: " << topology.getRowSpan() << " columnSpan: " << topology.getColumnSpan() - << " #bytes: " << topology.getUsedBytes() << std::endl; - unsigned char tempChar = 0; - int s = 0; - int ic = 0; - for (unsigned int i = 2; i < topology.getUsedBytes() + 2; i++) { - tempChar = topology.mPattern[i]; - s = 128; // 0b10000000 - while (s > 0) { - if (ic % topology.getColumnSpan() == 0) - os << "|"; - ic++; - if ((tempChar & s) != 0) - os << '+'; - else - os << ' '; - s /= 2; - if (ic % topology.getColumnSpan() == 0) - os << "|" << std::endl; - if (ic == (topology.getRowSpan() * topology.getColumnSpan())) - break; - } - if (ic == (topology.getRowSpan() * topology.getColumnSpan())) - break; - } - os << std::endl; + os << topology.mPattern << std::endl; return os; } } // namespace ITSMFT diff --git a/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h b/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h index 2ee1d58fd0cb4..39f29a05b09f9 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h +++ b/DataFormats/Detectors/ITSMFT/common/src/ITSMFTDataFormatsLinkDef.h @@ -16,6 +16,7 @@ #pragma link C++ class o2::ITSMFT::Cluster + ; #pragma link C++ class std::vector < o2::ITSMFT::Cluster > +; +#pragma link C++ class o2::ITSMFT::ClusterPattern + ; #pragma link C++ class o2::ITSMFT::ClusterTopology + ; #pragma link C++ class o2::ITSMFT::TopologyDictionary + ; diff --git a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx index 805317c38f4ec..c4cac15871f1d 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx @@ -28,11 +28,14 @@ ClassImp(o2::ITSMFT::TopologyDictionary) { namespace ITSMFT { + + TopologyDictionary::TopologyDictionary() : mSmallTopologiesLUT{-1} {} + std::ostream& operator<<(std::ostream& os, const TopologyDictionary& dict) { for (auto& p : dict.mVectorOfGroupIDs) { os << p.mHash << " " << p.mErrX << " " << p.mErrZ << " " << p.mXCOG << " " << p.mZCOG << " " << p.mNpixels << " " - << p.mFrequency << std::endl; + << p.mFrequency << p.mPattern << std::endl; } return os; } @@ -48,35 +51,17 @@ ClassImp(o2::ITSMFT::TopologyDictionary) file_output.write(reinterpret_cast(&p.mZCOG), sizeof(float)); file_output.write(reinterpret_cast(&p.mNpixels), sizeof(int)); file_output.write(reinterpret_cast(&p.mFrequency), sizeof(double)); + file_output.write(reinterpret_cast(&p.mPattern.mBitmap), + sizeof(unsigned char) * (Cluster::kMaxPatternBytes + 2)); } file_output.close(); } - void TopologyDictionary::ReadFile(string fname) - { - mVectorOfGroupIDs.clear(); - mFinalMap.clear(); - std::ifstream in(fname); - GroupStruct gr; - int groupID = 0; - if (!in.is_open()) { - cout << "The file could not be opened" << endl; - exit(1); - } else { - while (in >> gr.mHash >> gr.mErrX >> gr.mErrZ >> gr.mXCOG >> gr.mZCOG >> gr.mNpixels >> gr.mFrequency) { - mVectorOfGroupIDs.push_back(gr); - if (((gr.mHash) & 0xffffffff) != 0) - mFinalMap.insert(std::make_pair(gr.mHash, groupID)); - groupID++; - } - } - in.close(); - } - void TopologyDictionary::ReadBinaryFile(string fname) { mVectorOfGroupIDs.clear(); mFinalMap.clear(); + for(auto &p : mSmallTopologiesLUT) p = -1; std::ifstream in(fname.data(), std::ios::in | std::ios::binary); GroupStruct gr; int groupID = 0; @@ -91,7 +76,10 @@ ClassImp(o2::ITSMFT::TopologyDictionary) in.read(reinterpret_cast(&gr.mZCOG), sizeof(float)); in.read(reinterpret_cast(&gr.mNpixels), sizeof(int)); in.read(reinterpret_cast(&gr.mFrequency), sizeof(double)); + in.read(reinterpret_cast(&gr.mPattern.mBitmap), sizeof(unsigned char) * (Cluster::kMaxPatternBytes + 2)); mVectorOfGroupIDs.push_back(gr); + if (gr.mPattern.getUsedBytes() == 1) + mSmallTopologiesLUT[(gr.mPattern.getRowSpan() - 1) * 255 + (int)gr.mPattern.mBitmap[2]] = groupID; if (((gr.mHash) & 0xffffffff) != 0) mFinalMap.insert(std::make_pair(gr.mHash, groupID)); groupID++; diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h index acce1fe984a2f..2ef60996efa2e 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h @@ -22,9 +22,6 @@ #ifndef ALICEO2_ITSMFT_BUILDTOPOLOGYDICTIONARY_H #define ALICEO2_ITSMFT_BUILDTOPOLOGYDICTIONARY_H #include -#include -#include -#include #include "ITSMFTBase/SegmentationAlpide.h" #include "DataFormatsITSMFT/ClusterTopology.h" #include "DataFormatsITSMFT/TopologyDictionary.h" @@ -49,6 +46,8 @@ struct TopologyInfo { float mZmean; float mZsigma2; int mNpixels; + ClusterPattern mPattern; ///< Bitmask of pixels. For groups the biggest bounding box for the group is taken, with all + ///the bits set to 1. }; class BuildTopologyDictionary @@ -75,7 +74,7 @@ class BuildTopologyDictionary private: TopologyDictionary mDictionary; ///< Dictionary of topologies - std::map> + std::unordered_map> mTopologyMap; ///< Temporary map of type > std::vector> mTopologyFrequency; ///< , needed to define threshold int mTotClusters; @@ -85,7 +84,7 @@ class BuildTopologyDictionary std::unordered_map mMapInfo; - ClassDefNV(BuildTopologyDictionary, 1); + ClassDefNV(BuildTopologyDictionary, 2); }; } // namespace ITSMFT } // namespace o2 diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h index b852b36f1f097..8453663963f3e 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h @@ -33,7 +33,7 @@ class LookUp { public: LookUp(std::string fileName); - int findGroupID(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes], int nBytesUsed); + int findGroupID(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]); int getTopologiesOverThreshold() { return mTopologiesOverThreshold; } private: diff --git a/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx b/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx index d7b7523a9f117..5cff9bd86ed08 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx @@ -33,6 +33,8 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) if (ret.second == true) { //___________________DEFINING_TOPOLOGY_CHARACTERISTICS__________________ TopologyInfo topInf; + unsigned char patt[Cluster::kMaxPatternBytes + 2]; + cluster.getPattern(topInf.mPattern.mBitmap); int& rs = topInf.mSizeX = cluster.getRowSpan(); int& cs = topInf.mSizeZ = cluster.getColumnSpan(); //__________________COG_Deterrmination_____________ @@ -44,7 +46,7 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) int ic = 0; int ir = 0; for (unsigned int i = 2; i < cluster.getUsedBytes() + 2; i++) { - tempChar = cluster.getPattern()[i]; + tempChar = cluster.getByte(i); s = 128; // 0b10000000 while (s > 0) { if ((tempChar & s) != 0) { @@ -182,14 +184,17 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) GroupStruct gr; gr.mHash = mTopologyFrequency[j].second; gr.mFrequency = totFreq; - // rough estimation for the error considering a uniform distribution + // rough estimation for the error considering a8 uniform distribution gr.mErrX = std::sqrt(mMapInfo.find(gr.mHash)->second.mXsigma2); gr.mErrZ = std::sqrt(mMapInfo.find(gr.mHash)->second.mZsigma2); gr.mXCOG = mMapInfo.find(gr.mHash)->second.mCOGx; gr.mZCOG = mMapInfo.find(gr.mHash)->second.mCOGz; gr.mNpixels = mMapInfo.find(gr.mHash)->second.mNpixels; + gr.mPattern = mMapInfo.find(gr.mHash)->second.mPattern; mDictionary.mVectorOfGroupIDs.push_back(gr); mDictionary.mFinalMap.insert(std::make_pair(gr.mHash, j)); + if (gr.mPattern.getUsedBytes() == 1) + mDictionary.mSmallTopologiesLUT[(gr.mPattern.getRowSpan() - 1) * 255 + (int)gr.mPattern.mBitmap[2]] = j; } // groupRareTopologies based on binning over number of rows and columns (TopologyDictionary::NumberOfRowClasses * // NumberOfColClasse) @@ -207,6 +212,26 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) GroupArray[index].mXCOG = rowBinEdge / 2; GroupArray[index].mZCOG = colBinEdge / 2; GroupArray[index].mNpixels = rowBinEdge * colBinEdge; + unsigned char dummyPattern[Cluster::kMaxPatternBytes + 2] = { + 0 + }; /// A dummy pattern with all fired pixels in the bounding box is assigned to groups of rare topologies. + dummyPattern[0] = (unsigned char)rowBinEdge; + dummyPattern[1] = (unsigned char)colBinEdge; + int nBits = rowBinEdge * colBinEdge; + int nBytes = nBits / 8; + for (int iB = 2; iB < nBytes + 2; iB++) { + dummyPattern[iB] = (unsigned char)255; + } + int residualBits = nBits % 8; + if (residualBits) { + unsigned char tempChar = 0; + while (residualBits > 0) { + residualBits--; + tempChar |= 1 << (7 - residualBits); + } + dummyPattern[nBytes + 2] = tempChar; + } + GroupArray[index].mPattern.setPattern(dummyPattern); index++; return; }; @@ -219,7 +244,6 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) } for (int ic = 0; ic < TopologyDictionary::NumberOfColClasses - 1; ic++) { func(TopologyDictionary::MaxRowSpan, (ic + 1) * TopologyDictionary::ColClassSpan - 1, grNum); - unsigned long provvHash = 0; } func(TopologyDictionary::MaxRowSpan, TopologyDictionary::MaxColSpan, grNum); if (grNum != TopologyDictionary::NumberOfColClasses * TopologyDictionary::NumberOfRowClasses) { @@ -252,6 +276,8 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) #ifdef _HISTO_ mHdist.Scale(1. / mHdist.Integral()); #endif + + // Filling Look-up table for small topologies } std::ostream& operator<<(std::ostream& os, const BuildTopologyDictionary& DB) diff --git a/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx b/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx index e238dead080c9..31d6b6ba4d4d7 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx @@ -29,9 +29,24 @@ LookUp::LookUp(std::string fileName) mTopologiesOverThreshold = mDictionary.mFinalMap.size(); } -int LookUp::findGroupID(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes], int nBytesUsed) +int LookUp::findGroupID(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]) { - unsigned long hash = ClusterTopology::getCompleteHash(nRow, nCol, patt, nBytesUsed); + int nBits = nRow * nCol; + int nBytes = nBits / 8; + if (nBits % 8 != 0) + nBytes++; + if (nBytes == 1){ + int ID = mDictionary.mSmallTopologiesLUT[(nRow - 1) * 255 + (int)patt[0]]; + if(ID>=0) return ID; + else{ + int index = (nRow / TopologyDictionary::RowClassSpan) * TopologyDictionary::NumberOfRowClasses + + nCol / TopologyDictionary::ColClassSpan; + if (index >= TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses) + index = TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses; + return (mTopologiesOverThreshold + index); + } + } + unsigned long hash = ClusterTopology::getCompleteHash(nRow, nCol, patt); auto ret = mDictionary.mFinalMap.find(hash); if (ret != mDictionary.mFinalMap.end()) return ret->second; From 53c4f9d74af5ead5a99aa60ade7fc8c8d9fe99d7 Mon Sep 17 00:00:00 2001 From: Luca Barioglio Date: Thu, 31 May 2018 16:59:06 +0200 Subject: [PATCH 2/2] Change rare-topology group creation + add methods in TopologyDictionary The maximum number of rows and columns for groups of rare topology is set to the highest number that can contain the complete pixel bitmap (Cluster::kMaxPatternBits). --- .../DataFormatsITSMFT/ClusterPattern.h | 13 ++- .../DataFormatsITSMFT/ClusterTopology.h | 2 +- .../DataFormatsITSMFT/TopologyDictionary.h | 34 +++++-- .../ITSMFT/common/src/ClusterPattern.cxx | 21 +++-- .../ITSMFT/common/src/ClusterTopology.cxx | 7 +- .../ITSMFT/common/src/TopologyDictionary.cxx | 90 +++++++++++++++++-- .../ITSMFT/ITS/macros/test/CheckTopologies.C | 18 ++-- .../BuildTopologyDictionary.h | 6 +- .../include/ITSMFTReconstruction/LookUp.h | 1 + .../src/BuildTopologyDictionary.cxx | 80 ++++++++++------- .../common/reconstruction/src/LookUp.cxx | 41 +++++---- 11 files changed, 223 insertions(+), 90 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h index d925abe59a6bc..5fd04e4baba5f 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterPattern.h @@ -41,11 +41,10 @@ class ClusterPattern ClusterPattern(); /// Standard constructor ClusterPattern(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]); + /// Maximum number of bytes for the cluster puttern + 2 bytes respectively for the number of rows and columns of the bounding box + static constexpr int kExtendedPatternBytes = Cluster::kMaxPatternBytes + 2; /// Returns the pattern - void getPattern(unsigned char destination[Cluster::kMaxPatternBytes + 2]) const - { - memcpy(destination, mBitmap, Cluster::kMaxPatternBytes + 2); - } + std::array getPattern() const { return mBitmap; } /// Returns a specific byte of the pattern unsigned char getByte(int n) const; /// Returns the number of rows @@ -59,7 +58,7 @@ class ClusterPattern /// Sets the pattern void setPattern(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]); /// Sets the whole bitmask: the number of rows, the number of columns and the pattern - void setPattern(const unsigned char bitmask[Cluster::kMaxPatternBytes + 2]); + void setPattern(const unsigned char bitmask[kExtendedPatternBytes]); friend ClusterTopology; friend TopologyDictionary; @@ -73,8 +72,8 @@ class ClusterPattern /// - remainig bytes : pixels of the cluster, where 1 is a fired pixel and 0 /// is a non-fired pixel. The number of bytes used for the pixels depends on /// the size of the bounding box - unsigned char - mBitmap[Cluster::kMaxPatternBytes + 2]; ///< Cluster pattern: 1 is a fired pixel and 0 is a non-fired pixel + + std::array mBitmap; ///< Cluster pattern: 1 is a fired pixel and 0 is a non-fired pixel ClassDefNV(ClusterPattern, 1); }; diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h index ed9bbabe9ec4e..07f5d014fa22d 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/ClusterTopology.h @@ -39,7 +39,7 @@ class ClusterTopology /// Returns a specific byte of the pattern unsigned char getByte(int n) const { return mPattern.getByte(n); } /// Returns the pattern - void getPattern(unsigned char destination[Cluster::kMaxPatternBytes + 2]) const { mPattern.getPattern(destination); } + std::array getPattern() const { return mPattern.getPattern(); } /// Returns the number of rows int getRowSpan() const { return mPattern.getRowSpan(); } /// Returns the number of columns diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h index 05fd2f1ad47a1..d5c1a2edcc86a 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TopologyDictionary.h @@ -58,22 +58,40 @@ struct GroupStruct { class TopologyDictionary { public: - /// Default constructor TopologyDictionary(); - /// constexpr for the definition of the groups of rare topologies - static constexpr int NumberOfRowClasses = 7; ///< Number of row classes for the groups of rare topologies - static constexpr int NumberOfColClasses = 7; ///< Number of column classes for the groups of rare topologies - static constexpr int RowClassSpan = 5; ///< Row span of the classes of rare topologies - static constexpr int ColClassSpan = 5; ///< Column span of the classes of rare topologies - static constexpr int MaxRowSpan = 32; ///< Maximum row span - static constexpr int MaxColSpan = 32; ///< Maximum column span + /// constexpr for the definition of the groups of rare topologies. + /// The attritbution of the group ID is stringly dependent on the following parameters: it must be a power of 2. + static constexpr int RowClassSpan = 4; ///< Row span of the classes of rare topologies + static constexpr int ColClassSpan = 4; ///< Column span of the classes of rare topologies + static constexpr int MinimumClassArea = RowClassSpan * ColClassSpan; ///< Area of the smallest class of rare topologies (used as reference) + static constexpr int MaxNumberOfClasses = Cluster::kMaxPatternBits / MinimumClassArea; ///< Maximum number of row/column classes for the groups of rare topologies + static constexpr int NumberOfRareGroups = MaxNumberOfClasses * MaxNumberOfClasses; ///< Number of entries corresponding to groups of rare topologies (those whos matrix exceed the max number of bytes are empty). /// Prints the dictionary friend std::ostream& operator<<(std::ostream& os, const TopologyDictionary& dictionary); /// Prints the dictionary in a binary file void WriteBinaryFile(std::string outputFile); /// Reads the dictionary from a binary file void ReadBinaryFile(std::string fileName); + /// Returns the x position of the COG for the n_th element + float GetXcog(int n); + /// Returns the error on the x position of the COG for the n_th element + float GetErrX(int n); + /// Returns the z position of the COG for the n_th element + float GetZcog(int n); + /// Returns the error on the z position of the COG for the n_th element + float GetErrZ(int n); + /// Returns the hash of the n_th element + unsigned long GetHash(int n); + /// Returns the number of fired pixels of the n_th element + int GetNpixels(int n); + /// Returns the pattern of the topology + ClusterPattern GetPattern(int n); + /// Returns the frequency of the n_th element; + double GetFrequency(int n); + /// Returns the number of elements in the dicionary; + int GetSize() { return (int)mVectorOfGroupIDs.size(); } + friend BuildTopologyDictionary; friend LookUp; friend TopologyFastSimulation; diff --git a/DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx b/DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx index fdc25f9842d84..346790210e735 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/ClusterPattern.cxx @@ -57,9 +57,9 @@ ClassImp(o2::ITSMFT::ClusterPattern) memcpy(&mBitmap[2], patt, nBytes); } - void ClusterPattern::setPattern(const unsigned char patt[Cluster::kMaxPatternBytes + 2]) + void ClusterPattern::setPattern(const unsigned char patt[ClusterPattern::kExtendedPatternBytes]) { - memcpy(&mBitmap[0], patt, Cluster::kMaxPatternBytes + 2); + memcpy(&mBitmap[0], patt, ClusterPattern::kExtendedPatternBytes); } std::ostream& operator<<(std::ostream& os, const ClusterPattern& pattern) @@ -73,21 +73,26 @@ ClassImp(o2::ITSMFT::ClusterPattern) tempChar = pattern.mBitmap[i]; s = 128; // 0b10000000 while (s > 0) { - if (ic % pattern.getColumnSpan() == 0) + if (ic % pattern.getColumnSpan() == 0) { os << "|"; + } ic++; - if ((tempChar & s) != 0) + if ((tempChar & s) != 0) { os << '+'; - else + } else { os << ' '; + } s /= 2; - if (ic % pattern.getColumnSpan() == 0) + if (ic % pattern.getColumnSpan() == 0) { os << "|" << std::endl; - if (ic == (pattern.getRowSpan() * pattern.getColumnSpan())) + } + if (ic == (pattern.getRowSpan() * pattern.getColumnSpan())) { break; + } } - if (ic == (pattern.getRowSpan() * pattern.getColumnSpan())) + if (ic == (pattern.getRowSpan() * pattern.getColumnSpan())) { break; + } } os << std::endl; return os; diff --git a/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx b/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx index 5948da5942349..d5469c0e8ac76 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/ClusterTopology.cxx @@ -79,7 +79,7 @@ ClassImp(o2::ITSMFT::ClusterTopology) unsigned long ClusterTopology::getCompleteHash(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]) { - unsigned char extended_pattern[Cluster::kMaxPatternBytes + 2] = { 0 }; + unsigned char extended_pattern[ClusterPattern::kExtendedPatternBytes] = { 0 }; extended_pattern[0] = (unsigned char)nRow; extended_pattern[1] = (unsigned char)nCol; int nBits = nRow * nCol; @@ -112,10 +112,9 @@ ClassImp(o2::ITSMFT::ClusterTopology) unsigned long ClusterTopology::getCompleteHash(const ClusterTopology& topology) { - unsigned char patt[Cluster::kMaxPatternBytes + 2]; - topology.getPattern(patt); + auto patt = topology.getPattern(); int nBytesUsed = topology.getUsedBytes(); - unsigned long partialHash = (unsigned long)hashFunction(patt, nBytesUsed); + unsigned long partialHash = (unsigned long)hashFunction(patt.data(), nBytesUsed); // The first four bytes are directly taken from partialHash unsigned long completeHash = partialHash << 32; // The last four bytes of the hash are the first 32 pixels of the topology. diff --git a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx index c4cac15871f1d..e4c6ede6bee17 100644 --- a/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx +++ b/DataFormats/Detectors/ITSMFT/common/src/TopologyDictionary.cxx @@ -29,13 +29,16 @@ ClassImp(o2::ITSMFT::TopologyDictionary) namespace ITSMFT { - TopologyDictionary::TopologyDictionary() : mSmallTopologiesLUT{-1} {} + TopologyDictionary::TopologyDictionary() : mSmallTopologiesLUT{ -1 } {} std::ostream& operator<<(std::ostream& os, const TopologyDictionary& dict) { for (auto& p : dict.mVectorOfGroupIDs) { - os << p.mHash << " " << p.mErrX << " " << p.mErrZ << " " << p.mXCOG << " " << p.mZCOG << " " << p.mNpixels << " " - << p.mFrequency << p.mPattern << std::endl; + os << "Hash: " << p.mHash << " ErrX: " << p.mErrX << " ErrZ : " << p.mErrZ << " xCOG: " << p.mXCOG << " zCOG: " << p.mZCOG << " Npixles: " << p.mNpixels << " Frequency: " + << p.mFrequency << std::endl + << p.mPattern << std::endl + << "*********************************************************" << std::endl + << std::endl; } return os; } @@ -52,7 +55,7 @@ ClassImp(o2::ITSMFT::TopologyDictionary) file_output.write(reinterpret_cast(&p.mNpixels), sizeof(int)); file_output.write(reinterpret_cast(&p.mFrequency), sizeof(double)); file_output.write(reinterpret_cast(&p.mPattern.mBitmap), - sizeof(unsigned char) * (Cluster::kMaxPatternBytes + 2)); + sizeof(unsigned char) * (ClusterPattern::kExtendedPatternBytes)); } file_output.close(); } @@ -61,7 +64,8 @@ ClassImp(o2::ITSMFT::TopologyDictionary) { mVectorOfGroupIDs.clear(); mFinalMap.clear(); - for(auto &p : mSmallTopologiesLUT) p = -1; + for (auto& p : mSmallTopologiesLUT) + p = -1; std::ifstream in(fname.data(), std::ios::in | std::ios::binary); GroupStruct gr; int groupID = 0; @@ -76,7 +80,7 @@ ClassImp(o2::ITSMFT::TopologyDictionary) in.read(reinterpret_cast(&gr.mZCOG), sizeof(float)); in.read(reinterpret_cast(&gr.mNpixels), sizeof(int)); in.read(reinterpret_cast(&gr.mFrequency), sizeof(double)); - in.read(reinterpret_cast(&gr.mPattern.mBitmap), sizeof(unsigned char) * (Cluster::kMaxPatternBytes + 2)); + in.read(reinterpret_cast(&gr.mPattern.mBitmap), sizeof(unsigned char) * (ClusterPattern::kExtendedPatternBytes)); mVectorOfGroupIDs.push_back(gr); if (gr.mPattern.getUsedBytes() == 1) mSmallTopologiesLUT[(gr.mPattern.getRowSpan() - 1) * 255 + (int)gr.mPattern.mBitmap[2]] = groupID; @@ -87,5 +91,79 @@ ClassImp(o2::ITSMFT::TopologyDictionary) } in.close(); } + + float TopologyDictionary::GetXcog(int n) + { + if (n < 0 || n >= (int)mVectorOfGroupIDs.size()) { + printf("Incorrect element\n"); + exit(1); + } else + return mVectorOfGroupIDs[n].mXCOG; + } + float TopologyDictionary::GetErrX(int n) + { + if (n < 0 || n >= (int)mVectorOfGroupIDs.size()) { + printf("Incorrect element\n"); + exit(1); + } else + return mVectorOfGroupIDs[n].mErrX; + } + + float TopologyDictionary::GetZcog(int n) + { + if (n < 0 || n >= (int)mVectorOfGroupIDs.size()) { + printf("Incorrect element\n"); + exit(1); + } else + return mVectorOfGroupIDs[n].mZCOG; + } + + float TopologyDictionary::GetErrZ(int n) + { + if (n < 0 || n >= (int)mVectorOfGroupIDs.size()) { + printf("Incorrect element\n"); + exit(1); + } else + return mVectorOfGroupIDs[n].mErrZ; + } + + unsigned long TopologyDictionary::GetHash(int n) + { + if (n < 0 || n >= (int)mVectorOfGroupIDs.size()) { + printf("Incorrect element\n"); + exit(1); + } else + return mVectorOfGroupIDs[n].mHash; + } + + int TopologyDictionary::GetNpixels(int n) + { + if (n < 0 || n >= (int)mVectorOfGroupIDs.size()) { + printf("Incorrect element\n"); + exit(1); + } else + return mVectorOfGroupIDs[n].mNpixels; + } + + ClusterPattern TopologyDictionary::GetPattern(int n) + { + if (n < 0 || n >= (int)mVectorOfGroupIDs.size()) { + printf("Incorrect element\n"); + exit(1); + } else + return mVectorOfGroupIDs[n].mPattern; + } + + double TopologyDictionary::GetFrequency(int n) + { + if (n < 0 || n >= (int)mVectorOfGroupIDs.size()) { + printf("Incorrect element\n"); + exit(1); + } else if (n == 0) { + return mVectorOfGroupIDs[n].mFrequency; + } else { + return mVectorOfGroupIDs[n].mFrequency - mVectorOfGroupIDs[n - 1].mFrequency; + } + } } // namespace ITSMFT } diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C index 93083ca3b7a7a..99477543a2501 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C +++ b/Detectors/ITSMFT/ITS/macros/test/CheckTopologies.C @@ -134,21 +134,21 @@ void CheckTopologies(Int_t nEvents = 10, TString mcEngine = "TGeant3") completeDictionary.accountTopology(topology, dx, dz); } } - completeDictionary.setThreshold(0.00001); + completeDictionary.setThreshold(0.0001); completeDictionary.groupRareTopologies(); completeDictionary.printDictionaryBinary("complete_dictionary.bin"); - ofstream completeDictionaryOutput("complete_dictionary.txt"); - completeDictionaryOutput << completeDictionary; - noiseDictionary.setThreshold(0.00001); + completeDictionary.printDictionary("complete_dictionary.txt"); + completeDictionary.saveDictionaryRoot("complete_dictionary.root"); + noiseDictionary.setThreshold(0.0001); noiseDictionary.groupRareTopologies(); noiseDictionary.printDictionaryBinary("noise_dictionary.bin"); - ofstream noiseDictionaryOutput("noise_dictionary.txt"); - noiseDictionaryOutput << noiseDictionary; - signalDictionary.setThreshold(0.00001); + noiseDictionary.printDictionary("noise_dictionary.txt"); + noiseDictionary.saveDictionaryRoot("noise_dictionary.root"); + signalDictionary.setThreshold(0.0001); signalDictionary.groupRareTopologies(); signalDictionary.printDictionaryBinary("signal_dictionary.bin"); - ofstream signalDictionaryOutput("signal_dictionary.txt"); - signalDictionaryOutput << signalDictionary; + signalDictionary.printDictionary("signal_dictionary.txt"); + signalDictionary.saveDictionaryRoot("signal_dictionary.root"); TFile histogramOutput("histograms.root", "recreate"); TCanvas* cComplete = new TCanvas("cComplete", "Distribution of all the topologies"); diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h index 2ef60996efa2e..ab5b094c60ceb 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/BuildTopologyDictionary.h @@ -22,6 +22,7 @@ #ifndef ALICEO2_ITSMFT_BUILDTOPOLOGYDICTIONARY_H #define ALICEO2_ITSMFT_BUILDTOPOLOGYDICTIONARY_H #include +#include #include "ITSMFTBase/SegmentationAlpide.h" #include "DataFormatsITSMFT/ClusterTopology.h" #include "DataFormatsITSMFT/TopologyDictionary.h" @@ -67,6 +68,7 @@ class BuildTopologyDictionary friend std::ostream& operator<<(std::ostream& os, const BuildTopologyDictionary& BD); void printDictionary(std::string fname); void printDictionaryBinary(std::string fname); + void saveDictionaryRoot(const char* filename); int getTotClusters() const { return mTotClusters; } int getNotInGroups() const { return mNotInGroups; } @@ -74,8 +76,8 @@ class BuildTopologyDictionary private: TopologyDictionary mDictionary; ///< Dictionary of topologies - std::unordered_map> - mTopologyMap; ///< Temporary map of type > + std::map> + mTopologyMap; ///< Temporary map of type > std::vector> mTopologyFrequency; ///< , needed to define threshold int mTotClusters; int mNumberOfGroups; diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h index 8453663963f3e..a7a4d773be2db 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/LookUp.h @@ -33,6 +33,7 @@ class LookUp { public: LookUp(std::string fileName); + static int groupFinder(int nRow, int nCol); int findGroupID(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]); int getTopologiesOverThreshold() { return mTopologiesOverThreshold; } diff --git a/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx b/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx index 5cff9bd86ed08..bcc9d1c0b9d33 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/BuildTopologyDictionary.cxx @@ -14,7 +14,9 @@ /// \author Luca Barioglio, University and INFN of Torino #include "ITSMFTReconstruction/BuildTopologyDictionary.h" +#include "ITSMFTReconstruction/LookUp.h" #include +#include ClassImp(o2::ITSMFT::BuildTopologyDictionary) @@ -33,8 +35,7 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) if (ret.second == true) { //___________________DEFINING_TOPOLOGY_CHARACTERISTICS__________________ TopologyInfo topInf; - unsigned char patt[Cluster::kMaxPatternBytes + 2]; - cluster.getPattern(topInf.mPattern.mBitmap); + topInf.mPattern.setPattern(cluster.getPattern().data()); int& rs = topInf.mSizeX = cluster.getRowSpan(); int& cs = topInf.mSizeZ = cluster.getColumnSpan(); //__________________COG_Deterrmination_____________ @@ -121,14 +122,15 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) std::sort(mTopologyFrequency.begin(), mTopologyFrequency.end(), [](const std::pair& couple1, const std::pair& couple2) { return (couple1.first > couple2.first); }); - if (ngr < 10 || + int maxNumberOfGroups = Cluster::kMaxPatternBits / (TopologyDictionary::RowClassSpan * TopologyDictionary::ColClassSpan) * (1 + ceil(log(Cluster::kMaxPatternBits / (TopologyDictionary::RowClassSpan * TopologyDictionary::ColClassSpan)))); + if (ngr < maxNumberOfGroups || ngr > (mTopologyFrequency.size() - - TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses)) { + maxNumberOfGroups)) { std::cout << "BuildTopologyDictionary::setNGroups : Invalid number of groups" << std::endl; exit(1); } mNumberOfGroups = mNotInGroups = - ngr - TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses; + ngr - maxNumberOfGroups; mDictionary.mFinalMap.clear(); mFrequencyThreshold = ((double)mTopologyFrequency[mNotInGroups - 1].first) / mTotClusters; } @@ -168,8 +170,8 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) #ifdef _HISTO_ mHdist = TH1F("mHdist", "Groups distribution", - mNumberOfGroups + TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses, -0.5, - mNumberOfGroups + TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses - 0.5); + mNumberOfGroups + TopologyDictionary::NumberOfRareGroups, -0.5, + mNumberOfGroups + TopologyDictionary::NumberOfRareGroups - 0.5); mHdist.GetXaxis()->SetTitle("GroupID"); mHdist.SetFillColor(kRed); mHdist.SetFillStyle(3005); @@ -198,12 +200,13 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) } // groupRareTopologies based on binning over number of rows and columns (TopologyDictionary::NumberOfRowClasses * // NumberOfColClasse) - mNumberOfGroups += TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses; + + mNumberOfGroups += TopologyDictionary::NumberOfRareGroups; // array of groups - std::array GroupArray; - std::array + std::array GroupArray; + std::array groupCounts{ 0 }; - auto func = [&GroupArray](int rowBinEdge, int colBinEdge, int& index) { + auto createGroupEntry = [&GroupArray](int rowBinEdge, int colBinEdge, int& index) { unsigned long provvHash = 0; provvHash = (((unsigned long)(index + 1)) << 32) & 0xffffffff00000000; GroupArray[index].mHash = provvHash; @@ -212,7 +215,7 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) GroupArray[index].mXCOG = rowBinEdge / 2; GroupArray[index].mZCOG = colBinEdge / 2; GroupArray[index].mNpixels = rowBinEdge * colBinEdge; - unsigned char dummyPattern[Cluster::kMaxPatternBytes + 2] = { + unsigned char dummyPattern[ClusterPattern::kExtendedPatternBytes] = { 0 }; /// A dummy pattern with all fired pixels in the bounding box is assigned to groups of rare topologies. dummyPattern[0] = (unsigned char)rowBinEdge; @@ -235,21 +238,33 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) index++; return; }; + auto createPlaceHolder = [&GroupArray](int& index) { // Filling the dictionary with place-holders for entries of impossible groups due to pattern size. + GroupArray[index].mHash = 0; + GroupArray[index].mErrX = 0; + GroupArray[index].mErrZ = 0; + GroupArray[index].mXCOG = 0; + GroupArray[index].mZCOG = 0; + GroupArray[index].mNpixels = 0; + unsigned char dummyPattern[ClusterPattern::kExtendedPatternBytes] = { + 0 + }; + dummyPattern[0] = (unsigned char)TopologyDictionary::RowClassSpan; + dummyPattern[1] = (unsigned char)TopologyDictionary::ColClassSpan; + GroupArray[index].mPattern.setPattern(dummyPattern); + index++; + return; + }; + int grNum = 0; - for (int ir = 0; ir < TopologyDictionary::NumberOfRowClasses - 1; ir++) { - for (int ic = 0; ic < TopologyDictionary::NumberOfColClasses - 1; ic++) { - func((ir + 1) * TopologyDictionary::RowClassSpan - 1, (ic + 1) * TopologyDictionary::ColClassSpan - 1, grNum); + for (int iRow = 0; iRow < TopologyDictionary::MaxNumberOfClasses; iRow++) { + for (int iCol = 0; iCol < TopologyDictionary::MaxNumberOfClasses; iCol++) { + if ((iRow + 1) * (iCol + 1) <= TopologyDictionary::MaxNumberOfClasses) { + createGroupEntry((iRow + 1) * TopologyDictionary::RowClassSpan, (iCol + 1) * TopologyDictionary::ColClassSpan, grNum); + } else + createPlaceHolder(grNum); } - func((ir + 1) * TopologyDictionary::RowClassSpan - 1, TopologyDictionary::MaxColSpan, grNum); - } - for (int ic = 0; ic < TopologyDictionary::NumberOfColClasses - 1; ic++) { - func(TopologyDictionary::MaxRowSpan, (ic + 1) * TopologyDictionary::ColClassSpan - 1, grNum); - } - func(TopologyDictionary::MaxRowSpan, TopologyDictionary::MaxColSpan, grNum); - if (grNum != TopologyDictionary::NumberOfColClasses * TopologyDictionary::NumberOfRowClasses) { - std::cout << "Wrong number of groups" << std::endl; - exit(1); } + int rs; int cs; int index; @@ -258,14 +273,11 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) unsigned long hash1 = mTopologyFrequency[j].second; rs = mTopologyMap.find(hash1)->second.first.getRowSpan(); cs = mTopologyMap.find(hash1)->second.first.getColumnSpan(); - index = (rs / TopologyDictionary::RowClassSpan) * TopologyDictionary::NumberOfRowClasses + - cs / TopologyDictionary::ColClassSpan; - if (index > TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses - 1) - index = TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses - 1; + index = LookUp::groupFinder(rs, cs); groupCounts[index] += mTopologyFrequency[j].first; } - for (int i = 0; i < TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses; i++) { + for (int i = 0; i < TopologyDictionary::MaxNumberOfClasses * TopologyDictionary::MaxNumberOfClasses; i++) { totFreq += ((double)groupCounts[i]) / mTotClusters; GroupArray[i].mFrequency = totFreq; #ifdef _HISTO_ @@ -277,7 +289,7 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) mHdist.Scale(1. / mHdist.Integral()); #endif - // Filling Look-up table for small topologies + // Filling Look-up table for small topologies } std::ostream& operator<<(std::ostream& os, const BuildTopologyDictionary& DB) @@ -306,5 +318,13 @@ ClassImp(o2::ITSMFT::BuildTopologyDictionary) mDictionary.WriteBinaryFile(fname); out.close(); } + + void BuildTopologyDictionary::saveDictionaryRoot(const char* filename) + { + TFile output(filename, "recreate"); + output.WriteObjectAny(&mDictionary, mDictionary.Class(), "TopologyDictionary"); + output.Close(); + } + } // namespace ITSMFT } diff --git a/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx b/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx index 31d6b6ba4d4d7..1516d794f79ce 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/LookUp.cxx @@ -29,32 +29,43 @@ LookUp::LookUp(std::string fileName) mTopologiesOverThreshold = mDictionary.mFinalMap.size(); } +int LookUp::groupFinder(int nRow, int nCol) +{ + int row_index = nRow / TopologyDictionary::RowClassSpan; + if (nRow % TopologyDictionary::RowClassSpan == 0) { + row_index--; + } + int col_index = nCol / TopologyDictionary::ColClassSpan; + if (nCol % TopologyDictionary::RowClassSpan == 0) { + col_index--; + } + if (row_index > TopologyDictionary::MaxNumberOfClasses || col_index > TopologyDictionary::MaxNumberOfClasses) { + return TopologyDictionary::NumberOfRareGroups - 1; + } else { + return row_index * TopologyDictionary::MaxNumberOfClasses + col_index; + } +} + int LookUp::findGroupID(int nRow, int nCol, const unsigned char patt[Cluster::kMaxPatternBytes]) { int nBits = nRow * nCol; - int nBytes = nBits / 8; - if (nBits % 8 != 0) - nBytes++; - if (nBytes == 1){ + // Small topology + if (nBits < 9) { int ID = mDictionary.mSmallTopologiesLUT[(nRow - 1) * 255 + (int)patt[0]]; - if(ID>=0) return ID; - else{ - int index = (nRow / TopologyDictionary::RowClassSpan) * TopologyDictionary::NumberOfRowClasses + - nCol / TopologyDictionary::ColClassSpan; - if (index >= TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses) - index = TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses; + if (ID >= 0) + return ID; + else { //small rare topology (inside groups) + int index = groupFinder(nRow, nCol); return (mTopologiesOverThreshold + index); } } + // Big topology unsigned long hash = ClusterTopology::getCompleteHash(nRow, nCol, patt); auto ret = mDictionary.mFinalMap.find(hash); if (ret != mDictionary.mFinalMap.end()) return ret->second; - else { - int index = (nRow / TopologyDictionary::RowClassSpan) * TopologyDictionary::NumberOfRowClasses + - nCol / TopologyDictionary::ColClassSpan; - if (index >= TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses) - index = TopologyDictionary::NumberOfRowClasses * TopologyDictionary::NumberOfColClasses; + else { // Big rare topology (inside groups) + int index = groupFinder(nRow, nCol); return (mTopologiesOverThreshold + index); } }