Belle II Software  release-08-01-10
PXDIgnoredPixelsMap.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <pxd/online/PXDIgnoredPixelsMap.h>
10 #include <boost/property_tree/xml_parser.hpp>
11 #include <framework/logging/Logger.h>
12 #include <framework/utilities/FileSystem.h>
13 #include <vxd/geometry/GeoCache.h>
14 
15 using namespace Belle2;
16 using namespace std;
17 using boost::property_tree::ptree;
18 
19 
20 PXDIgnoredPixelsMap::PXDIgnoredPixelsMap(const string& xmlFilename):
21  m_Map(0), m_MapSingles(0), m_lastSensorID(0), m_lastSensorVCells(0)
22 {
23  // If the xmlFilename is empty, the user apparently doesn't want the map.
24  // So keep low-profile, don't bother.
25  if (xmlFilename == "") {
26  B2DEBUG(10, "No xml list of ignored pixels specified.");
27  return;
28  }
29  // Create an empty property tree object
30 
31  ptree propertyTree;
32 
33  // Load the XML file into the property tree. If reading fails
34  // (cannot open file, parse error), an exception is thrown.
35  string xmlFullPath = FileSystem::findFile(xmlFilename);
36 
37  if (! FileSystem::fileExists(xmlFullPath)) {
38  B2WARNING("The xml filename: " << xmlFilename << endl <<
39  "resolved to: " << xmlFullPath << endl <<
40  "by FileSystem::findFile does not exist." << endl <<
41  "PXD ignored pixels map cannot be initialized." << endl
42  );
43  return;
44  }
45 
46  try {
47  read_xml(xmlFullPath, propertyTree);
48  } catch (std::exception const& ex) {
49  B2WARNING("STD excpetion raised during xml parsing " << ex.what() << endl <<
50  "PXD ignored pixels map cannot be initialized." << endl);
51  return;
52  } catch (...) {
53  B2WARNING("Unknown excpetion raised during xml parsing "
54  "PXD ignored pixels map cannot be initialized." << endl);
55  return;
56  }
57 
58  try {
59  // traverse the xml tree: navigate through the daughters of <PXD>
60  VxdID sensorID;
61  for (ptree::value_type const& layer : propertyTree.get_child("PXD"))
62  if (layer.first == "layer") {
63  sensorID.setLayerNumber(static_cast<unsigned short>(layer.second.get<int>("<xmlattr>.n")));
64  for (ptree::value_type const& ladder : layer.second)
65  if (ladder.first == "ladder") {
66  sensorID.setLadderNumber(static_cast<unsigned short>(ladder.second.get<int>("<xmlattr>.n")));
67  for (ptree::value_type const& sensor : ladder.second)
68  if (sensor.first == "sensor") {
69  sensorID.setSensorNumber(static_cast<unsigned short>(sensor.second.get<int>("<xmlattr>.n")));
72  const VXD::SensorInfoBase& info = VXD::GeoCache::getInstance().get(sensorID);
73  for (ptree::value_type const& tag : sensor.second) {
74  if (tag.first == "pixels") {
75  auto limits = tag.second;
76  // All possible attributes, default = -1 (att not present)
77  short uStart = limits.get<short>("<xmlattr>.uStart", -1);
78  short uEnd = limits.get<short>("<xmlattr>.uEnd", -1);
79  short vStart = limits.get<short>("<xmlattr>.vStart", -1);
80  short vEnd = limits.get<short>("<xmlattr>.vEnd", -1);
81 
82  // Fill remaining range parameters
83  if (uStart != -1 && vStart != -1 && uEnd == -1 && vEnd == -1) {
84  // mask one pixel
85  uEnd = uStart;
86  vEnd = vStart;
87  } else if (uStart != -1 && vStart == -1 && uEnd == -1 && vEnd == -1) {
88  // mask column u ... all v rows
89  uEnd = uStart;
90  vStart = 0;
91  vEnd = info.getVCells() - 1;
92  } else if (uStart == -1 && vStart != -1 && uEnd == -1 && vEnd == -1) {
93  // mask row v ... all u columns
94  vEnd = vStart;
95  uStart = 0;
96  uEnd = info.getUCells() - 1;
97  } else if (uStart != -1 && vStart == -1 && uEnd != -1 && vEnd == -1) {
98  // columns from ... to ... (all rows there)
99  vStart = 0;
100  vEnd = info.getVCells() - 1;
101  } else if (uStart == -1 && vStart != -1 && uEnd == -1 && vEnd != -1) {
102  // rows from ... to ... (all columns there)
103  uStart = 0;
104  uEnd = info.getUCells() - 1;
105  } else if (uStart != -1 && vStart != -1 && uEnd != -1 && vEnd != -1) {
106  // already ok, rectangular area
107  } else {
108  // do not accept other combinations
109  continue;
110  }
111  // ensure positive and meaningfull values
112  unsigned short uS(uStart);
113  unsigned short vS(vStart);
114  unsigned short uE(uEnd);
115  unsigned short vE(vEnd);
116  if (uE >= info.getUCells()) uE = info.getUCells() - 1;
117  if (vE >= info.getVCells()) vE = info.getVCells() - 1;
118  if (vS > vE) vS = vE;
119  if (uS > uE) uS = uE;
120  // area of the masked range
121  unsigned int area = (uE - uS + 1) * (vE - vS + 1);
122  if (area == 1) {
123  // Single pixel masking:
124  // We store pixels by unique id in hash table
125  unsigned int uid = uStart * info.getVCells() + vStart;
126  // uid will be used to generate hash in unordered_set for quick access
127  singles.insert(uid);
128  } else {
129  // lambda function to decide if (u,v) is inside this range
131  [ = ](unsigned int u, unsigned int v) -> bool
132  { return (uS <= u && u <= uE && vS <= v && v <= vE); };
133  // area is used to sort ranges from largest to smallest
134  ranges.insert(std::make_pair(area, range_mask));
135  }
136  }
137  }
138  m_Map.insert(std::pair<unsigned short, PXDIgnoredPixelsMap::IgnoredPixelsRangeSet>(sensorID.getID(), ranges));
139  m_MapSingles.insert(std::pair<unsigned short, PXDIgnoredPixelsMap::IgnoredSinglePixelsSet>(sensorID.getID(), singles));
140  } // if sensor
141  } // if ladder
142  } // if sensor
143  } catch (...) {
144  B2WARNING("Unknown exception raised during map initialization! "
145  "PXD ignored pixels map may be corrupted." << endl);
146  return;
147  }
148 }
149 
150 const std::set<PXDIgnoredPixelsMap::map_pixel> PXDIgnoredPixelsMap::getIgnoredPixels(VxdID id)
151 {
152  // Merely for testing...
153  // This function is quite ineffective, but it is not supposed to be run often
154  // Also, it currently returns copy of the (possibly very big) set of masked pixels
155  std::set<PXDIgnoredPixelsMap::map_pixel> pixels;
157 
158  // This is quite slow solution but it merges duplicate maskings in the set
159  for (int pixelU = 0; pixelU < info.getUCells(); pixelU++) {
160  for (int pixelV = 0; pixelV < info.getVCells(); pixelV++) {
161  PXDIgnoredPixelsMap::map_pixel px(pixelU, pixelV);
162  if (!pixelOK(id, px))
163  pixels.insert(px);
164  }
165  }
166  return pixels;
167 }
168 
170 {
171  // If sensor id changed from last query, swich to temp maps
172  // of the new sensor. Otherwise clear temp maps, as there is nothing to mask
173  if (id != m_lastSensorID) {
174  m_lastSensorID = id;
176  auto mapIter = m_Map.find(id);
177  auto mapIterSingles = m_MapSingles.find(id);
178 
179  if (mapIter != m_Map.end())
180  m_lastIgnored = mapIter->second;
181  else
182  m_lastIgnored.clear();
183 
184  if (mapIterSingles != m_MapSingles.end())
185  m_lastIgnoredSingles = mapIterSingles->second;
186  else
187  m_lastIgnoredSingles.clear();
188 
189  if (mapIter == m_Map.end() && mapIterSingles == m_MapSingles.end()) {
190  // Sensor has no masked ranges or single pixels in the maps => pixel ok
191  return true;
192  }
193  }
194 
195  const unsigned int u = pixel.first;
196  const unsigned int v = pixel.second;
197 
198  // loop over masked ranges for the sensor
199  // (iter over multimap ordered by masked area)
200  for (auto iter = m_lastIgnored.begin(); iter != m_lastIgnored.end(); ++iter) {
201  // call the lambda function of masked range to check if pixel is inside
202  if (iter->second(u, v))
203  return false;
204  }
205  // Look if this is a single masked pixel
206  // (lookup in hash table)
208  return false;
209 
210  // Pixel not found in the mask => pixel OK
211  return true;
212 }
213 
214 
215 
216 
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
Definition: FileSystem.cc:148
static bool fileExists(const std::string &filename)
Check if the file with given filename exists.
Definition: FileSystem.cc:32
std::unordered_set< unsigned int > IgnoredSinglePixelsSet
Structure to hold set of masked single pixels indexed by their unique id (unsigned int),...
std::pair< unsigned short, unsigned short > map_pixel
Simple structure for a pixel, u = map_pixel.first, v = map_pixel.second.
std::unordered_map< unsigned short, IgnoredSinglePixelsSet > m_MapSingles
Structure holding sets of ingored single pixels for all sensors by sensor id (unsigned short).
std::unordered_map< unsigned short, IgnoredPixelsRangeSet > m_Map
Structure holding sets of ignored pixel ranges for all sensors by sensor id (unsigned short).
std::multimap< unsigned int, pixel_range_test_prototype, std::greater< unsigned int > > IgnoredPixelsRangeSet
Structure to hold set of masked pixel ranges ordered from largest to smallest by their area (unsigned...
IgnoredSinglePixelsSet m_lastIgnoredSingles
Set of ignored single pixels for the most currently queried sensor.
unsigned short m_lastSensorVCells
The most currently queried sensor number of V pixels (for quick pixel uid evaluation)
IgnoredPixelsRangeSet m_lastIgnored
Set of ignored pixel ranges for the most currently queried sensor.
PXDIgnoredPixelsMap()=delete
No default constructor.
VxdID m_lastSensorID
The most currently queried sensor number.
std::function< bool(unsigned short, unsigned short) > pixel_range_test_prototype
Prototype for lambda function used to check if a pixel is in masked range.
bool pixelOK(VxdID id, map_pixel pixel)
Check whether a pixel on a given sensor is OK or not.
const std::set< map_pixel > getIgnoredPixels(VxdID id)
Get the set of ignored pixels for a sensor.
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
static const SensorInfoBase & get(Belle2::VxdID id)
Return a reference to the SensorInfo of a given SensorID.
Definition: GeoCache.h:139
Base class to provide Sensor Information for PXD and SVD.
int getVCells() const
Return number of pixel/strips in v direction.
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
baseType getID() const
Get the unique id.
Definition: VxdID.h:94
void setSensorNumber(baseType sensor)
Set the sensor id.
Definition: VxdID.h:111
void setLadderNumber(baseType ladder)
Set the ladder id.
Definition: VxdID.h:109
void setLayerNumber(baseType layer)
Set the layer id.
Definition: VxdID.h:107
Abstract base class for different kinds of events.