Belle II Software  release-05-02-19
SectorGraph.h
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2015 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Jakob Lettenbichler (jakob.lettenbichler@oeaw.ac.at) *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #pragma once
12 
13 #include <framework/logging/Logger.h>
14 #include <tracking/trackFindingVXD/sectorMapTools/SubGraphID.h>
15 #include <tracking/trackFindingVXD/sectorMapTools/SubGraph.h>
16 
17 #include <string>
18 #include <vector>
19 #include <unordered_map>
20 #include <utility> // std::pair, std::move
21 
22 
23 namespace Belle2 {
30  template<class FilterType> class SectorGraph {
31  protected:
32  std::unordered_map<SubGraphID, SubGraph<FilterType>> m_subgraphs;
34  std::vector<FilterType> m_filterIDs;
35  public:
36 
38  explicit SectorGraph(std::vector<FilterType>& fIDs) : m_filterIDs(fIDs)
39  { if (m_filterIDs.empty()) { B2FATAL("SectorGraph-constructor: passed filterIDs are empty, this is an illegal usage of this class!"); } }
40 
42  using Iterator = typename std::unordered_map<SubGraphID, SubGraph<FilterType>>::iterator;
43 
45  Iterator find(SubGraphID idChain) { return m_subgraphs.find(idChain); }
46 
48  Iterator begin() { return m_subgraphs.begin(); }
49 
51  Iterator end() { return m_subgraphs.end(); }
52 
54  unsigned size() const { return m_subgraphs.size(); }
55 
57  unsigned long nFoundTotal() const
58  {
59  unsigned long nFound = 0;
60  for (auto& pack : m_subgraphs) { nFound += pack.second.getFound(); }
61  return nFound;
62  }
63 
66  {
67  if (m_subgraphs.find(newID) != end())
68  { B2WARNING("SectorGraph::add: given ID " << newID.print() << " is already in graph, not added again..."); return end(); }
69  std::pair<Iterator, bool> pos = m_subgraphs.insert({newID, SubGraph<FilterType>(newID, m_filterIDs)});
70  B2DEBUG(1, "SectorGraph::add: new subgraph added: " << pos.first->second.print());
71  return pos.first;
72  }
73 
75  std::string print(bool fullPrint = true) const
76  {
77  unsigned nSubgraphs = m_subgraphs.size();
78  std::string out = "graph has got " + std::to_string(nSubgraphs) + " entries:\n";
79  out += "now printing " + (fullPrint ? std::string("full") : std::string("short version of the")) + " graph:\n";
80  for (const auto& entry : m_subgraphs) {
81  if (!fullPrint and nSubgraphs % 100 != 0) continue; // printing only 100 subgraphs of mainGraph for the short version.
82  out += entry.second.print() + "\n";
83  }
84  return out;
85  }
86 
88  unsigned pruneGraph(double rarenessCut)
89  {
90  //sanity checks:
91  if (rarenessCut < 0 or rarenessCut >= 1)
92  { B2WARNING("pruneGraph: rarenessCut is rubbish: " << rarenessCut << ", stopping prune-process."); return 0; }
93  if (rarenessCut == 0) { B2DEBUG(1, "pruneGraph: nothing to be done, stopping prune-process."); return 0; }
94 
96  // .first counts total number of occurances of branches of this trunk (= outer sector(s))
97  // .second is a vector of pointers to the subgraphs of that trunk.
98  std::vector< std::pair<unsigned, std::vector<SubGraph<FilterType>*> >> trunks;
99 
100  // find those sharing a trunk (trunkTotal) and cluster them in these trunks:
101  for (auto& subGraphEntry : m_subgraphs) {
102  SubGraph<FilterType>& graph = subGraphEntry.second;
103  bool found = false;
104  for (auto& trunk : trunks) {
105  if (graph.checkSharesTrunk(*(trunk.second.at(0)))) {
106  trunk.first += graph.getFound();
107  trunk.second.push_back(&graph);
108  found = true;
109  continue;
110  }
111 
112  if (found) continue;
113  trunks.push_back({graph.getFound(), {&graph} });
114  }
115  }
116 
117  unsigned long nFoundB4 = nFoundTotal(), nKilled = 0;
118  unsigned sizeb4 = size();
119  B2DEBUG(1, "pruneGraph - before pruning: graph of size " << sizeb4 << " has " << trunks.size() << " trunks with " << nFoundB4 <<
120  " total found.");
121 
122  // collect subGraphs (=branches) to be deleted:
123  std::vector<SubGraph<FilterType>*> deadBranches;
124  for (auto& trunk : trunks) {
125  double trunkCut = rarenessCut * double(trunk.first);
126 
127  // sort branches of trunk by rareness (rarest one first):
128  std::sort(trunk.second.begin(),
129  trunk.second.end(),
130  [](const SubGraph<FilterType>* a, const SubGraph<FilterType>* b)
131  -> bool { return a->getFound() < b->getFound(); });
132 
133  // skip trunk, if there are no rare branches.
134  auto pos = trunk.second.begin();
135  if (double((**pos).getFound()) >= trunkCut) continue;
136 
137  // collect branches to be killed starting with the smallest one and stop when reaching those which have been slipping above the threshold in the process:
138  while (pos != trunk.second.end()) {
139  // mark the most rarest entry:
140  deadBranches.push_back(*pos);
141  trunkCut -= double((**pos).getFound()) * rarenessCut;
142 
143  // reached the point when all graphs left are now good enough for us: -> stopping loop.
144  if (double((**pos).getFound()) >= trunkCut) break;
145  ++pos;
146  }
147  } // looping over trunks
148 
149  if (deadBranches.empty()) { B2DEBUG(1, "pruneGraph: no rare branches found - stopping pruning process."); return 0; }
150 
151  // kill selected ones:
152  for (auto* graph : deadBranches) {
153  nKilled += graph->getFound();
154  m_subgraphs.erase(graph->getID());
155  }
156 
157  B2DEBUG(1, "pruneGraph - after pruning graph with size (before/after " << sizeb4 << "/" << size() <<
158  ") and nFound (before/after/killed " << nFoundB4 << "/" << nFoundTotal() << "/" << nKilled);
159 
160  return nKilled;
161  }
162 
163 
167  void updateSubLayerIDs()
168  {
169  unsigned nUpdated = 0, // counts sectors which shall be updated
170  nFound = 0, // counts sectors which were found (without double entry removal)
171  nGraphsUpdated = 0; // counts graphs which were updated
172 
173  // collects the secIDs which have got inner sectors on same sensor:
174  std::vector<unsigned> idsFound;
175  std::string idsPrinted;
176 
177  // collect all SecIDs where SubLayer has to be updated.
178  for (auto& subGraphEntry : m_subgraphs) {
179  SubGraphID graphID = subGraphEntry.second.getID();
180  std::vector<unsigned> found = graphID.hasSharedLayer();
181  if (found.empty()) continue;
182  idsFound.insert(idsFound.end(), found.begin(), found.end());
183  }
184  for (unsigned id : idsFound) { idsPrinted += FullSecID(id).getFullSecString() + " "; }
185  B2DEBUG(1, "updateSubLayerIDs: before unique of found ids, following IDs are recorded: \n" << idsPrinted);
186  nFound += idsFound.size();
187  std::sort(idsFound.begin(), idsFound.end());
188  idsFound.erase(std::unique(idsFound.begin(), idsFound.end()), idsFound.end());
189  nUpdated += idsFound.size();
190 
191  idsPrinted = "";
192  for (unsigned id : idsFound) { idsPrinted += FullSecID(id).getFullSecString() + " "; }
193  B2DEBUG(1, "updateSubLayerIDs: before updating Subgraphs, following IDs have to be updated: \n" << idsPrinted);
194 
195 
196  // update all subGraphIDs where subLayerID has to be increased:
197  for (auto& subGraphEntry : m_subgraphs) {
198  SubGraph<FilterType>& graph = subGraphEntry.second;
199  unsigned nSecsUpdated = graph.idCheckAndUpdate(idsFound);
200  if (nSecsUpdated == 0) {
201  B2DEBUG(50, "updateSubLayerIDs: was _not_ updated: " << graph.getID().print());
202  continue;
203  }
204  nGraphsUpdated++;
205  B2DEBUG(50, "updateSubLayerIDs: was updated " << nSecsUpdated << " times: " << graph.getID().print());
206  }
207 
208  B2DEBUG(1, "updateSubLayerIDs: nSectors found/updated: " << nFound << "/" << nUpdated << ", nSubgraphs updated: " <<
209  nGraphsUpdated);
210 
211  // create new map of Subgraphs with updated LayerIDs
212  // subGraph: copy with updated iD.
213  // SubGraphID: a.isElementOf(SubGraphID& b) <- checks if given sectorPack ( >= 1 sector) is part of a, ignores subLayerID.
214  // SubGraphID: a.replaceElement(SubGraphID& b) <- checks if given sectorPack ( >= 1 sector) is part of a, ignores subLayerID. if yes, replaces element(s). WARNING only works with complete replacement of SubGraphID (entries are const).
215  // SubGraphID: a.areTheSameSectors(SubGraphID& b) <- checks if sectors are identical (while ignoring the subLayerID)
216  // SubGraphID: a.sharesLayer() <- returns IDs of entries being inner friend of sectors on same layer.
217 
218  // return new map of Subgraphs.
219  }
220 
222  std::vector<FullSecID> getAllFullSecIDsOfSensor(VxdID sensor)
223  {
224  std::vector<FullSecID> foundIDs;
225 
226  for (auto& subGraph : m_subgraphs) {
227  std::vector<FullSecID> sectorsFound = subGraph.second.getSectorsOfSensor(sensor);
228  if (sectorsFound.empty()) continue;
229  foundIDs.insert(foundIDs.end(), sectorsFound.begin(), sectorsFound.end());
230  }
231  B2DEBUG(1, "getAllFullSecIDsOfSensor: VxdID " << sensor << " has " << foundIDs.size() << " sectors in this graph");
232  return foundIDs;
233  }
234 
236  const std::vector<FilterType>& getFilterTypes() const { return m_filterIDs; }
237  };
239 }
240 
Belle2::SectorGraph::m_subgraphs
std::unordered_map< SubGraphID, SubGraph< FilterType > > m_subgraphs
contains all subgraphs.
Definition: SectorGraph.h:40
Belle2::SectorGraph::print
std::string print(bool fullPrint=true) const
returns a string giving an overview of the graph.
Definition: SectorGraph.h:83
Belle2::SectorGraph::size
unsigned size() const
returns number of collected subgraphs so far.
Definition: SectorGraph.h:62
Belle2::SectorGraph::find
Iterator find(SubGraphID idChain)
find entry.
Definition: SectorGraph.h:53
Belle2::SubGraph::checkSharesTrunk
bool checkSharesTrunk(const SubGraph< FilterType > &b) const
if both graphs have got the same IDs except the last one, they share a trunk.
Definition: SubGraph.h:90
Belle2::SubGraphID::hasSharedLayer
std::vector< unsigned > hasSharedLayer() const
returns raw IDs of entries being outer friend of sectors on same layer.
Definition: SubGraphID.h:163
Belle2::Iterator
map< unsigned, const TOPSampleTimes * >::const_iterator Iterator
Iteratior for m_map.
Definition: TOPCalTimebase.cc:25
Belle2::FullSecID
Class to identify a sector inside of the VXD.
Definition: FullSecID.h:43
Belle2::SectorGraph::SectorGraph
SectorGraph(std::vector< FilterType > &fIDs)
constructor expects filterIDs.
Definition: SectorGraph.h:46
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::SectorGraph::nFoundTotal
unsigned long nFoundTotal() const
returns number of occurances for all subGraphs found together.
Definition: SectorGraph.h:65
Belle2::SectorGraph::pruneGraph
unsigned pruneGraph(double rarenessCut)
returns removed occurances.
Definition: SectorGraph.h:96
Belle2::SubGraph
contains all relevant stuff needed for dealing with a subGraph.
Definition: SubGraph.h:40
Belle2::SectorGraph::end
Iterator end()
returns end of subGraphs.
Definition: SectorGraph.h:59
Belle2::SectorGraph::begin
Iterator begin()
returns begin of subGraphs.
Definition: SectorGraph.h:56
Belle2::SectorGraph::getFilterTypes
const std::vector< FilterType > & getFilterTypes() const
returns a const reference to the filterTypes stored in this graph
Definition: SectorGraph.h:244
Belle2::SectorGraph::updateSubLayerIDs
void updateSubLayerIDs()
finds sectors having inner sectors in same layer and update them in the subGraph-ID.
Definition: SectorGraph.h:175
Belle2::SectorGraph::Iterator
typename std::unordered_map< SubGraphID, SubGraph< FilterType > >::iterator Iterator
for better readability.
Definition: SectorGraph.h:50
Belle2::SectorGraph::m_filterIDs
std::vector< FilterType > m_filterIDs
ids of all filterTypes to be stored by subGraphs.
Definition: SectorGraph.h:42
Belle2::SectorGraph::getAllFullSecIDsOfSensor
std::vector< FullSecID > getAllFullSecIDsOfSensor(VxdID sensor)
returns a Vector containing all FullSecIDs found for given sensor.
Definition: SectorGraph.h:230
Belle2::FullSecID::getFullSecString
std::string getFullSecString() const
returns the FullSecID coded as string compatible to secIDs stored in the xml-sectormaps
Definition: FullSecID.cc:119
Belle2::SubGraphID::print
std::string print() const
returns string of entries.
Definition: SubGraphID.h:111
Belle2::SubGraphID
stores the ID of a subgraph, which is basically a chain of FullSecID coded as unsigned ints.
Definition: SubGraphID.h:34
Belle2::SectorGraph::add
Iterator add(SubGraphID &newID)
add new subgraph if not added already.
Definition: SectorGraph.h:73