Belle II Software  release-08-01-10
SVDOnlineToOfflineMap.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 "svd/online/SVDOnlineToOfflineMap.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 
21  : m_MapUniqueName("")
22  , m_currentChipInfo()
23  , m_currentSensorInfo()
24 {
25 
26  // Create an empty property tree object
27 
28  ptree propertyTree;
29 
30  // Load the XML file into the property tree. If reading fails
31  // (cannot open file, parse error), an exception is thrown.
32  string xmlFullPath = FileSystem::findFile(xmlFilename);
33 
34  if (! FileSystem::fileExists(xmlFullPath)) {
35  B2ERROR("The xml filename: " << xmlFilename << endl <<
36  "resolved to: " << xmlFullPath << endl <<
37  "by FileSystem::findFile does not exist." << endl <<
38  "SVD online to offline map cannot be initialized." << endl <<
39  "Be aware: no SVDShaperDigit will be produced by this module." << endl
40  );
41  return;
42  }
43 
44  try {
45  read_xml(xmlFullPath, propertyTree);
46  } catch (std::exception const& ex) {
47  B2ERROR("STD excpetion rised during xml parsing " << ex.what() << endl <<
48  "SVD online to offline map cannot be initialized." << endl <<
49  "Be aware: no SVDShaperDigits will be produced by this module." << endl);
50  return;
51  } catch (...) {
52  B2ERROR("Unknown excpetion rised during xml parsing "
53  "SVD online to offline map cannot be initialized." << endl <<
54  "Be aware: no SVDShaperDigits will be produced by this module." << endl);
55  return;
56  }
57 
58  try {
59  // traverse pt: let us navigate through the daughters of <SVD>
60  for (ptree::value_type const& v : propertyTree.get_child("SVD")) {
61  if (v.first == "unique") {
62  m_MapUniqueName = v.second.get<string>("<xmlattr>.name");
63  B2INFO("Loading the offline -> online SVD map named " << m_MapUniqueName);
64  }
65  // if the daughter is a <layer> then read it!
66  if (v.first == "layer")
67  ReadLayer(v.second.get<int>("<xmlattr>.n"), v.second);
68  }
69  } catch (...) {
70  B2ERROR("Unknown excpetion rised during map initialization! "
71  "SVD online to offline map corrupted." << endl <<
72  "Be aware: the SVDShaperDigits will be unreliable." << endl);
73  // To Do: rise an exception so that the calling module will skip the
74  // SVDShaperDigits filling
75  return;
76  }
77 }
78 
79 const SVDOnlineToOfflineMap::SensorInfo& SVDOnlineToOfflineMap::getSensorInfo(unsigned char FADC, unsigned char APV25)
80 {
81 
82  ChipID id(FADC, APV25);
83  auto sensorIter = m_sensors.find(id);
84 
85  if (sensorIter == m_sensors.end()) {
87 
88  if (!(nBadMappingErrors % m_errorRate)) B2ERROR("Combination not found in the SVD On-line to Off-line map:" << LogVar("FADC",
89  int(FADC)) << LogVar("APV", int(APV25)));
90 
94  return m_currentSensorInfo;
95  }
96  m_currentSensorInfo = sensorIter->second;
97  return m_currentSensorInfo;
98 }
99 
100 
101 
102 const SVDOnlineToOfflineMap::ChipInfo& SVDOnlineToOfflineMap::getChipInfo(unsigned short layer, unsigned short ladder,
103  unsigned short dssd, bool side, unsigned short strip)
104 {
105  SensorID id(layer, ladder, dssd, side);
106  auto chipIter = m_chips.find(id);
107 
108  if (chipIter == m_chips.end()) B2WARNING(" The following combination: sensorID: " << layer << "." << ladder << "." << dssd <<
109  ", isU=" << side << ", strip=" << strip <<
110  " - is not found in the SVD Off-line to On-line map! The payload retrieved from database may be wrong! ");
111 
112 
113  vector<ChipInfo> vecChipInfo = chipIter->second;
114 
115  ChipInfo info = {0, 0, 0, 0, 0};
116  ChipInfo* pinfo = &info;
117 
118  for (std::vector<ChipInfo>::iterator it = vecChipInfo.begin() ; it != vecChipInfo.end(); ++it) {
119  ChipInfo& chipInfo = *it;
120  unsigned short channelFirst = min(chipInfo.stripFirst, chipInfo.stripLast);
121  unsigned short channelLast = max(chipInfo.stripFirst, chipInfo.stripLast);
122 
123  if (strip >= channelFirst and strip <= channelLast) {
124  pinfo = &chipInfo;
125  pinfo->apvChannel = abs(strip - (pinfo->stripFirst));
126  }
127  }
128  if (pinfo->fadc == 0) B2WARNING("The strip number " << strip << " is not found in the SVDOnlineToOfflineMap for sensor " << layer <<
129  "." << ladder << "." << dssd << " on side " << (side ? "u" : "v") << "! Related APV chip is excluded in the hardware mapping.");
130 
131  m_currentChipInfo = *pinfo;
132  return m_currentChipInfo;
133 }
134 
135 bool SVDOnlineToOfflineMap::isAPVinMap(unsigned short layer, unsigned short ladder,
136  unsigned short dssd, bool side, unsigned short strip)
137 {
138  SensorID id(layer, ladder, dssd, side);
139  auto chipIter = m_chips.find(id);
140 
141  if (chipIter == m_chips.end()) return false;
142 
143  vector<ChipInfo> vecChipInfo = chipIter->second;
144 
145  ChipInfo info = {0, 0, 0, 0, 0};
146  ChipInfo* pinfo = &info;
147 
148  for (std::vector<ChipInfo>::iterator it = vecChipInfo.begin() ; it != vecChipInfo.end(); ++it) {
149  ChipInfo& chipInfo = *it;
150  unsigned short channelFirst = min(chipInfo.stripFirst, chipInfo.stripLast);
151  unsigned short channelLast = max(chipInfo.stripFirst, chipInfo.stripLast);
152 
153  if (strip >= channelFirst and strip <= channelLast) {
154  pinfo = &chipInfo;
155  pinfo->apvChannel = abs(strip - (pinfo->stripFirst));
156  }
157  }
158  if (pinfo->fadc == 0) return false;
159 
160  return true;
161 }
162 
163 bool SVDOnlineToOfflineMap::isAPVinMap(VxdID sensorID, bool side, unsigned short strip)
164 {
165  return isAPVinMap(sensorID.getLayerNumber(), sensorID.getLadderNumber(), sensorID.getSensorNumber(), side, strip);
166 }
167 
168 
170  unsigned char APV25, unsigned char channel, short samples[6], float time)
171 {
172  // Issue a warning, we'll be sending out a null pointer.
173  if (channel > 127) {
174  B2WARNING(" channel out of range (0-127):" << LogVar("channel", int(channel)));
175  return nullptr;
176  }
177  const SensorInfo& info = getSensorInfo(FADC, APV25);
178  short strip = getStripNumber(channel, info);
179 
181  copy(samples, samples + SVDShaperDigit::c_nAPVSamples, rawSamples.begin());
182 
183  // create SVDShaperDigit only for existing sensor
184  if (info.m_sensorID) {
185  return new SVDShaperDigit(info.m_sensorID, info.m_uSide, strip, rawSamples, time);
186  } else {
187  return nullptr;
188  }
189 }
190 
191 
192 void
193 SVDOnlineToOfflineMap::ReadLayer(int nlayer, ptree const& xml_layer)
194 {
195  // traverse xml_layer: let us navigate through the daughters of <layer>
196  for (ptree::value_type const& v : xml_layer) {
197  // if the daughter is a <ladder> then read it!
198  if (v.first == "ladder") {
199  ReadLadder(nlayer, v.second.get<int>("<xmlattr>.n"), v.second);
200  }
201  }
202 }
203 
204 void
205 SVDOnlineToOfflineMap::ReadLadder(int nlayer, int nladder, ptree const& xml_ladder)
206 {
207  // traverse xml_ladder: let us navigate through the daughters of <ladder>
208  for (ptree::value_type const& v : xml_ladder) {
209  // if the daughter is a <sensor> then read it!
210  if (v.first == "sensor") {
211  ReadSensor(nlayer, nladder, v.second.get<int>("<xmlattr>.n"), v.second);
212  }
213  }
214 }
215 
216 void
217 SVDOnlineToOfflineMap::ReadSensor(int nlayer, int nladder, int nsensor, ptree const& xml_sensor)
218 {
219  // traverse xml_sensor: let us navigate through the daughters of <sensor>
220  for (ptree::value_type const& v : xml_sensor) {
221  // if the daughter is one side <> then read it!
222  if (v.first == "side") {
223  std::string tagSide = v.second.get<std::string>("<xmlattr>.side");
224 
225  bool isOnSideU = (tagSide == "U" || tagSide == "u");
226  bool isOnSideV = (tagSide == "V" || tagSide == "v");
227 
228  if ((! isOnSideU) && (! isOnSideV)) {
229  B2ERROR("Side '" << tagSide << "' on layer " << nlayer
230  << " ladder " << nladder << " sensor " << nsensor
231  << " is neither 'U' nor 'V'");
232  }
233 
234  ReadSensorSide(nlayer, nladder, nsensor, isOnSideU, v.second);
235  }
236  }
237 
238 }
239 
240 void
241 SVDOnlineToOfflineMap::ReadSensorSide(int nlayer, int nladder, int nsensor, bool isU,
242  ptree const& xml_side)
243 {
244 
245  // traverse xml_sensor: let us navigate through the daughters of <side>
246 
247 
248  vector<ChipInfo> vecInfo; // for packer
249  SensorID sid(nlayer, nladder, nsensor, isU);
250 
251  for (ptree::value_type const& v : xml_side) {
252  // if the daughter is a <chip>
253 
254  if (v.first == "chip") {
255  auto tags = v.second;
256  unsigned char chipN = tags.get<unsigned char>("<xmlattr>.n");
257  unsigned char FADCn = tags.get<unsigned char>("<xmlattr>.FADCn");
258 
259  //storing info on FADC numbers and related APV chips
260  FADCnumbers.insert(FADCn);
261  APVforFADCmap.insert(std::pair<unsigned char, unsigned char>(FADCn, chipN));
262 
263  ChipID cid(FADCn, chipN);
264 
265  auto sensorIter = m_sensors.find(cid);
266 
267  if (sensorIter != m_sensors.end()) {
268  B2WARNING("Repeated insertion for FADC " << FADCn << " and APV "
269  << chipN << ", layer/ladder/sensor " << nlayer << "/" << nladder
270  << "/" << nsensor << ", side " << (isU ? "u" : "v"));
271  }
272  unsigned short stripNumberCh0 = tags.get<unsigned short>("<xmlattr>.strip_number_of_ch0");
273  unsigned short stripNumberCh127 = tags.get<unsigned short>("<xmlattr>.strip_number_of_ch127");
274 
275 
276  SensorInfo sinfo;
277  sinfo.m_sensorID = VxdID(nlayer, nladder, nsensor);
278  sinfo.m_uSide = isU;
279  sinfo.m_parallel = (stripNumberCh127 > stripNumberCh0);
280  sinfo.m_channel0 = stripNumberCh0;
281  sinfo.m_channel127 = stripNumberCh127;
282 
283  m_sensors[cid] = sinfo;
284 
285  // for packer
286  ChipInfo cinfo;
287  cinfo.fadc = FADCn;
288  cinfo.apv = chipN;
289  cinfo.stripFirst = stripNumberCh0;
290  cinfo.stripLast = stripNumberCh127;
291  cinfo.apvChannel = 0;
292 
293  vecInfo.push_back(cinfo);
294 
295  } //chip
296 
297  } // for daughters
298 
299  m_chips[sid] = vecInfo; // for packer
300 }
301 
303 {
304  unsigned short it = 0;
305 
306  for (auto ifadc = FADCnumbers.begin(); ifadc != FADCnumbers.end(); ++ifadc) {
307  map2[it] = *ifadc;
308  map1[*ifadc] = it++;
309  }
310 }
311 
313 {
314 
315 
317 
318  for (auto layer : geoCache.getLayers(VXD::SensorInfoBase::SVD))
319  for (auto ladder : geoCache.getLadders(layer))
320  for (Belle2::VxdID sensor : geoCache.getSensors(ladder))
321  for (int view = 0; view < 2; view++) {
322 
323  int nAPVs = 6;
324  if (layer.getLayerNumber() != 3 && view == 0)
325  nAPVs = 4;
326 
327  //loop on all APVs of the side
328  for (int apv = 0; apv < nAPVs; apv++) {
329  B2DEBUG(29, "checking " << sensor.getLayerNumber() << "." << sensor.getLadderNumber() << "." << sensor.getSensorNumber() <<
330  ", view = " << view << ", apv = " << apv);
331  if (! isAPVinMap(sensor, view, apv * 128 + 63.5)) {
332  missingAPV tmp_missingAPV;
333  tmp_missingAPV.m_sensorID = sensor;
334  tmp_missingAPV.m_isUSide = view;
335  tmp_missingAPV.m_halfStrip = apv * 128 + 63.5;
336 
337  m_missingAPVs.push_back(tmp_missingAPV);
338  B2DEBUG(29, "FOUND MISSING APV: " << sensor << ", " << view << ", " << apv);
339  }
340 
341  }
342 
343  }
344 
345 }
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
Class to hold FADC+APV25 numbers.
Class to hold numbers related to sensor.
void prepareListOfMissingAPVs()
prepares the list of the missing APVs using the channel mapping
std::unordered_map< unsigned short, unsigned short > FADCmap
FADC map typedef.
const SensorInfo & getSensorInfo(unsigned char FADC, unsigned char APV25)
Get SensorInfo for a given FADC/APV combination.
SensorInfo m_currentSensorInfo
current sensor info
void ReadSensor(int nLayer, int nLadder, int nSensor, boost::property_tree::ptree const &xml_sensor)
Read from the ptree xml_sensor the sensor nSensor in ladder nLadder in layer nLayer.
SVDShaperDigit * NewShaperDigit(unsigned char FADC, unsigned char APV25, unsigned char channel, short samples[6], float time=0.0)
Return a pointer to a new SVDShpaerDigit whose VxdID, isU and cellID is set.
std::unordered_multimap< unsigned char, unsigned char > APVforFADCmap
map containing FADC numbers assigned to multiple APVs, from xml file
int m_errorRate
The suppression factor of BadMapping ERRORs messages to be shown.
const ChipInfo & getChipInfo(unsigned short layer, unsigned short ladder, unsigned short dssd, bool side, unsigned short strip)
Get ChipInfo for a given layer/ladder/dssd/side/strip combination.
unsigned int nBadMappingErrors
Counter of the BadMapping errors.
SVDOnlineToOfflineMap()=delete
No default constructor.
std::unordered_map< ChipID::baseType, SensorInfo > m_sensors
m_sensors[ChipID(FADC,APV25)] gives the SensorInfo for the given APV25 on the given FADC (Unpacker)
void ReadLadder(int nLayer, int nLadder, boost::property_tree::ptree const &xml_ladder)
Read from the ptree xml_ladde the ladder nLadder in layer nLayer.
std::unordered_set< unsigned char > FADCnumbers
container for FADC numbers from current mapping file
ChipInfo m_currentChipInfo
internal instance of chipinfo used by the getter
void ReadLayer(int nLayer, boost::property_tree::ptree const &xml_layer)
Read from the ptree v in the xml file the layer nLayer.
std::string m_MapUniqueName
Human readable unique name of this map.
std::unordered_map< SensorID::baseType, std::vector< ChipInfo > > m_chips
needed for the packer, map of VxdID to chips
void ReadSensorSide(int nLayer, int nLadder, int nSensor, bool isU, boost::property_tree::ptree const &xml_side)
Read from the ptree xml_side the U-side, if isU, (the V-side otherwise) of the sensor nSensor in ladd...
void prepFADCmaps(FADCmap &, FADCmap &)
function that maps FADC numbers as 0-(nFADCboards-1) from FADCnumbers unordered_set
bool isAPVinMap(unsigned short layer, unsigned short ladder, unsigned short dssd, bool side, unsigned short strip)
is the APV of the strips in the map? for a given layer/ladder/dssd/side/strip combination.
short getStripNumber(unsigned char channel, const SensorInfo &info) const
Convert APV channel number to a strip number using a ChipInfo object.
std::vector< missingAPV > m_missingAPVs
list of the missing APVs
The SVD ShaperDigit class.
static const std::size_t c_nAPVSamples
Number of APV samples stored.
std::array< APVRawSampleType, c_nAPVSamples > APVRawSamples
array of APVRawSamplesType objects
Class to faciliate easy access to sensor information of the VXD like coordinate transformations or pi...
Definition: GeoCache.h:39
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
baseType getSensorNumber() const
Get the sensor id.
Definition: VxdID.h:100
baseType getLadderNumber() const
Get the ladder id.
Definition: VxdID.h:98
baseType getLayerNumber() const
Get the layer id.
Definition: VxdID.h:96
Class to store variables with their name which were sent to the logging service.
Abstract base class for different kinds of events.
Struct to hold data about an APV25 chip.
unsigned short stripLast
last strip number
unsigned short stripFirst
first strip number
Struct to hold data about a sensor.
unsigned short m_channel127
Strip corresponding to channel 127.
unsigned short m_channel0
Strip corresponding to channel 0.
struct to hold missing APVs informations
float m_halfStrip
floating strip in the middle of the APV
bool m_isUSide
True if u-side of the sensor.