Newer
Older
TB_Chris / TbIO / src / .svn / text-base / TbEventBuilder.cpp.svn-base
  1. #include <algorithm>
  2.  
  3. // Gaudi
  4. #include "GaudiKernel/IEventProcessor.h"
  5. #include "GaudiAlg/ISequencerTimerTool.h"
  6.  
  7. // Tb/TbKernel
  8. #include "TbKernel/TbFunctors.h"
  9. #include "TbKernel/TbConstants.h"
  10.  
  11. // Local
  12. #include "TbEventBuilder.h"
  13. #include "TbRawFile.h"
  14.  
  15. #include <chrono>
  16. #include <ctime>
  17.  
  18. DECLARE_ALGORITHM_FACTORY(TbEventBuilder)
  19.  
  20. const int64_t TbEventBuilder::m_maxTimeDifference = std::pow(2, 40);
  21.  
  22. //=============================================================================
  23. // Standard constructor
  24. //=============================================================================
  25. TbEventBuilder::TbEventBuilder(const std::string& name,
  26. ISvcLocator* pSvcLocator)
  27. : TbAlgorithm(name, pSvcLocator),
  28. m_streams(), m_triggers(), m_hits() {
  29.  
  30. declareProperty("HitLocation",
  31. m_hitLocation = LHCb::TbHitLocation::Default);
  32. declareProperty("TriggerLocation",
  33. m_triggerLocation = LHCb::TbTriggerLocation::Default);
  34.  
  35. // Length of event in global time units.
  36. declareProperty("EventLength", m_tick = 10 * Tb::SpidrTime);
  37. // Length to look into 'future' events to correct
  38. // for time misordering around event boundaries
  39. declareProperty("CacheLength", m_cachelength = 20 * Tb::SpidrTime);
  40.  
  41. // The time by which events 'overlap' to prevent tracks / clusters
  42. // being cut between different events. Implementation is rather
  43. // convoluted, relies on track identification and global event defintion
  44. // via the TbTimingSvc
  45. declareProperty("OverlapTime", m_overlapTime = 0 * Tb::ToA);
  46.  
  47. // Min. number of planes with at least one hit required to make an event
  48. declareProperty("MinPlanesWithHits", m_nMinPlanesWithHits = 1);
  49. // Print frequency
  50. declareProperty("PrintFreq", m_printFreq = 100);
  51. // Size of the header, if not set is read in
  52. declareProperty("HeaderSize", m_headerSize = 0);
  53. // Flag to print out the header information
  54. declareProperty("PrintHeader", m_printHeader = false);
  55. // Flag to switch monitoring print-out and histograms.
  56. declareProperty("Monitoring", m_monitoring = false);
  57. // Time to start data processing, in s
  58. declareProperty("StartTime", m_startTime = 0);
  59. // Time to end data processing, in ms
  60. declareProperty("EndTime", m_endTime = 0);
  61. // Flag to produce Equalisation maps
  62. declareProperty("EqualisationHistos", m_equal = false );
  63. // Maximum number of packets that can be lost before
  64. // considered a critical failure
  65. declareProperty("MaxLostPackets", m_maxLostPackets = 1000);
  66. // Maximum number of timing packets that not read
  67. // before considered a critical failure
  68. declareProperty("MaxLostTimers", m_maxLostTimers = 10);
  69. // Force the cache to update every cycle, as opposed to
  70. // waiting until the first packet is in view
  71. declareProperty("ForceCaching", m_forceCaching = false);
  72. declareProperty("IgnoreGlobalClock", m_ignoreGlobalClock = false );
  73. }
  74.  
  75. //=============================================================================
  76. // Destructor
  77. //=============================================================================
  78. TbEventBuilder::~TbEventBuilder() {}
  79.  
  80. //=============================================================================
  81. // Initialisation
  82. //=============================================================================
  83. StatusCode TbEventBuilder::initialize() {
  84. // Initialise the base class.
  85. StatusCode sc = TbAlgorithm::initialize();
  86. if (sc.isFailure()) return sc;
  87.  
  88. // Prepare the hit containers.
  89. m_hits.resize(m_nPlanes, nullptr);
  90. m_triggers.resize(m_nPlanes, nullptr);
  91. // Setup the raw stream tools.
  92. for (unsigned int i = 0; i < m_nDevices; ++i){
  93. const std::string toolname = "TbRawStream/TbRawStream"+ std::to_string(i);
  94. m_streams.push_back(tool<TbRawStream>(toolname));
  95. if (!m_streams[i]) return Error("Cannot initialise " + toolname);
  96. m_streams[i]->setDevice(i);
  97. }
  98. // Setup the header decoder tool.
  99. m_headerDecoder = tool<TbHeaderDecoder>("TbHeaderDecoder");
  100. if (!m_headerDecoder) return Error("Cannot initialise header decoder.");
  101. m_headerDecoder->print(m_printHeader);
  102. // Propagate the overlap time to the timing service.
  103. timingSvc()->setOverlap(m_overlapTime);
  104. // Get the list of input data
  105. auto files = dataSvc()->getInputFiles();
  106. for (const auto& filename : files) {
  107. // Check the filename.
  108. const size_t pos = filename.find(".dat");
  109. const size_t dash = filename.find_last_of("-");
  110. if (pos == std::string::npos) {
  111. warning() << "Skipping " << filename << " (not a .dat file)" << endmsg;
  112. continue;
  113. }
  114. if (!(pos - dash > 1)) {
  115. warning() << "Unexpected filename (" << filename << ")" << endmsg;
  116. warning() << "Skipping " << filename << endmsg;
  117. continue;
  118. }
  119. TbRawFile* f = new TbRawFile(filename, m_headerDecoder);
  120. if (!f->good()) {
  121. if (!f->is_open()) {
  122. error() << "Cannot open " << filename << endmsg;
  123. } else {
  124. f->close();
  125. }
  126. warning() << "Skipping " << filename << endmsg;
  127. delete f;
  128. continue;
  129. }
  130. const std::string id = f->id();
  131. const unsigned int plane = geomSvc()->plane(id);
  132. if (plane == 999) {
  133. warning() << id << " is not listed in the alignment file" << endmsg;
  134. warning() << "Skipping " << filename << endmsg;
  135. f->close();
  136. delete f;
  137. continue;
  138. }
  139. const unsigned int deviceIndex = geomSvc()->deviceIndex(id);
  140. if (deviceIndex == 999) {
  141. warning() << id << " is not listed in the alignment file" << endmsg;
  142. warning() << "Skipping " << filename << endmsg;
  143. f->close();
  144. delete f;
  145. continue;
  146. }
  147. if (m_streams[deviceIndex]->files().empty()) {
  148. info() << id << " (device " << deviceIndex
  149. << ") is mapped to plane " << plane << endmsg;
  150. }
  151. unsigned int col = 0;
  152. auto chips = geomSvc()->module(plane)->chips();
  153. for (auto chip : chips) {
  154. if (chip.id == id) {
  155. col = chip.col;
  156. }
  157. }
  158. m_streams[deviceIndex]->setPlane(plane);
  159. m_streams[deviceIndex]->setDevice(deviceIndex);
  160. m_streams[deviceIndex]->setOffset(col);
  161. m_streams[deviceIndex]->addFile(f);
  162. }
  163. // Make sure that there are data files for all planes.
  164. for (unsigned int i = 0; i < m_nDevices; ++i) {
  165. if (m_streams[i]->files().empty()) {
  166. return Error("No input files for device " + std::to_string(i));
  167. }
  168. }
  169.  
  170. // Convert start and end times to FToA.
  171. m_startTime *= Tb::millisecond * 1000;
  172. m_endTime *= Tb::millisecond;
  173. for (auto& f : m_streams) {
  174. std::sort(f->files().begin(), f->files().end(), lessBySplitIndex());
  175. f->prepare();
  176. m_nDataInFiles += f->size();
  177. // Convert starting time to FToA times
  178. if (m_startTime != 0) f->fastForward(m_startTime);
  179. }
  180. info() << "Total data size: " << m_nDataInFiles << " packets" << endmsg;
  181. m_clock = m_tick + m_startTime;
  182. return StatusCode::SUCCESS;
  183. }
  184.  
  185. //=============================================================================
  186. // Main execution
  187. //=============================================================================
  188. StatusCode TbEventBuilder::execute() {
  189.  
  190. std::clock_t c_end = std::clock();
  191. std::chrono::_V2::system_clock::time_point t_end = std::chrono::high_resolution_clock::now();
  192. if (m_nPackets != 0) {
  193. double time = std::chrono::duration<double, std::milli>(t_end-t_start).count() ;
  194. plot2D(m_nPackets, time, "RateVsTime",0.,1000000.,0.,3000.,100,100);
  195. plot2D(m_nPackets, time / (double)m_nPackets, "RateVsTimePerPacket",0.,1000000.,0.,0.01,100,100);
  196. //info() << " packets = " << m_nPackets << " time = " << time << endmsg;
  197. m_nPackets = 0;
  198. }
  199. /*
  200. std::cout << std::fixed << std::setprecision(2) << "CPU time used: "
  201. << 1000.0 * (c_end-c_start) / CLOCKS_PER_SEC << " ms\n"
  202. << "Wall clock time passed: "
  203. << std::chrono::duration<double, std::milli>(t_end-t_start).count()
  204. << " ms\n";
  205. */
  206.  
  207. c_start = c_end;
  208. t_start = t_end;
  209.  
  210. // Create containers for hits and triggers.
  211. for (unsigned int i = 0; i < m_nPlanes; ++i) {
  212. const std::string ext = std::to_string(i);
  213. LHCb::TbHits* hits = new LHCb::TbHits();
  214. put(hits, m_hitLocation + ext);
  215. m_hits[i] = hits;
  216. LHCb::TbTriggers* triggers = new LHCb::TbTriggers();
  217. put(triggers, m_triggerLocation + ext);
  218. m_triggers[i] = triggers;
  219. }
  220. bool done = false;
  221. bool eof = true;
  222. bool eot = false;
  223. while (!done) {
  224. eof = true;
  225. // Update the event boundaries.
  226. if (UNLIKELY(msgLevel(MSG::DEBUG))) {
  227. debug() << "Event definition: " << m_clock - m_tick
  228. << " to " << m_clock + m_overlapTime
  229. << endmsg;
  230. }
  231. timingSvc()->setEventDefinition(m_clock - m_tick,
  232. m_clock + m_overlapTime);
  233. for (unsigned int i = 0 ; i < m_nPlanes; ++i) {
  234. m_hits[i]->clear();
  235. m_triggers[i]->clear();
  236. }
  237. for (auto f : m_streams) {
  238. eof &= f->eos();
  239. fill(f, m_hits[f->plane()], m_triggers[f->plane()], eot);
  240. }
  241. unsigned int nPlanesWithHits = 0;
  242. bool gotTrigger = false;
  243. for (unsigned int i = 0; i < m_nPlanes; ++i) {
  244. if (!m_triggers[i]->empty()) {
  245. gotTrigger = true;
  246. break;
  247. }
  248. if (!m_hits[i]->empty()) ++nPlanesWithHits;
  249. }
  250. if (gotTrigger || nPlanesWithHits >= m_nMinPlanesWithHits) {
  251. done = true;
  252. } else {
  253. ++m_nNoiseEvents;
  254. }
  255. m_clock += m_tick;
  256. if (eof) break;
  257. }
  258. // Sort hits and triggers by time.
  259. for (unsigned int i = 0; i < m_nPlanes; ++i) {
  260. std::sort(m_hits[i]->begin(), m_hits[i]->end(),
  261. TbFunctors::LessByTime<const LHCb::TbHit*>());
  262. std::sort(m_triggers[i]->begin(), m_triggers[i]->end(),
  263. TbFunctors::LessByTime<const LHCb::TbTrigger*>());
  264. m_nPackets += m_hits[i]->size() ;
  265. }
  266. // Increment the event counter.
  267. ++m_nEvents;
  268. if (m_nEvents % m_printFreq == 0) {
  269. info() << format(" %8u events read, %12u hits, %12u triggers",
  270. m_nEvents, m_nHitsRead, m_nTriggersRead) << endmsg;
  271. if (m_monitoring) {
  272. info() << "Hits: ";
  273. for (unsigned int i = 0; i < m_nPlanes; ++i) {
  274. info() << format(" %12d", m_hits[i]->size());
  275. }
  276. info() << endmsg << "Cache: ";
  277. for (unsigned int i = 0; i < m_nPlanes; ++i) {
  278. info() << format(" %12d", m_streams[i]->hitCache().size());
  279. }
  280. info() << endmsg << "Triggers: ";
  281. for (unsigned int i = 0; i < m_nPlanes; ++i) {
  282. info() << format(" %12d", m_triggers[i]->size());
  283. }
  284. info() << endmsg << "Cache: ";
  285. for (unsigned int i = 0; i < m_nPlanes; ++i) {
  286. info() << format(" %12d", m_streams[i]->trgCache().size());
  287. }
  288. info() << endmsg;
  289. }
  290. }
  291. bool emptyCache = true;
  292. for (const auto& f : m_streams) {
  293. if (!f->hitCache().empty() || !f->trgCache().empty()) {
  294. emptyCache = false;
  295. break;
  296. }
  297. }
  298. // Check if there are any events left to process.
  299. if (((m_nData == m_nDataInFiles || eof) && emptyCache) || eot) {
  300. // Terminate the application.
  301. SmartIF<IEventProcessor> app(serviceLocator()->service("ApplicationMgr"));
  302. if (app) app->stopRun();
  303. }
  304. if (m_nLostTimers > m_maxLostTimers) {
  305. return Error("More than " + std::to_string(m_maxLostTimers) +
  306. " clock packets dropped. Critical problem with global clock");
  307. }
  308. if (m_nLostPackets > m_maxLostPackets) {
  309. return Error("More than " + std::to_string(m_maxLostPackets) +
  310. " packets dropped. Critical problem with timing");
  311. }
  312. return StatusCode::SUCCESS;
  313. }
  314.  
  315. //=============================================================================
  316. // Add hits and triggers to the containers
  317. //=============================================================================
  318. bool TbEventBuilder::fill(TbRawStream* f, LHCb::TbHits* hits,
  319. LHCb::TbTriggers* triggers,
  320. bool& eot) {
  321. if (!dumpCache(f, hits) && !m_forceCaching) {
  322. if (UNLIKELY(msgLevel(MSG::DEBUG))) {
  323. debug() << "Event boundary: " << m_clock << endmsg;
  324. if (f->hitCache().size() > 0) {
  325. debug() << "First hit in cache:" << f->hitCache().front()->time()
  326. << endmsg;
  327. }
  328. if (f->trgCache().size() > 0) {
  329. debug() << "First trigger in cache: " << f->trgCache().front()->time()
  330. << endmsg;
  331. }
  332. }
  333. dumpCache(f, triggers);
  334. return false;
  335. }
  336. dumpCache(f, triggers);
  337. const unsigned int device = f->device();
  338. uint64_t currentTime = 0;
  339. while (likely(currentTime < m_clock + m_cachelength && !f->eos())) {
  340. const uint64_t packet = f->getNext();
  341. ++m_nData;
  342. const unsigned int header = 0xF & (packet >> 60);
  343. if (likely(header == 0xA || header == 0xB)) {
  344. // Pixel packets.
  345. ++m_nHitsRead;
  346. // Get the pixel adress.
  347. const unsigned int pixelAddress = 0xFFFF & (packet >> 44);
  348. // Skip masked pixels.
  349. if (unlikely(pixelSvc()->isMasked(pixelAddress, device))) continue;
  350. LHCb::TbHit* hit = decodeTPX3Hit( packet, pixelAddress, device , f->col() );
  351. hit->setCharge(pixelSvc()->charge(hit->ToT(), pixelAddress, device));
  352. extendTimeStamp(hit, m_ignoreGlobalClock ? f->m_tpx3Timer : f->timer());
  353. pixelSvc()->applyPhaseCorrection(hit);
  354. writePacket(hit, f, hits);
  355. currentTime = hit->time();
  356. //info() << std::dec << (double)prevTime / (double)Tb::second << " " << (double)currentTime / (double)Tb::second << " " << f->hClock() << endmsg;
  357. syncTPX3( currentTime, f ) ;
  358. if (UNLIKELY(m_monitoring)) {
  359. plot(hit->time() / Tb::millisecond, "HitDataRate",
  360. "Rate of hit packets", 0.0, 620000.0, 6200000);
  361. }
  362. } else if ((header == 0x6 || header == 0x4) &&
  363. (( packet >> 56) & 0xF) == 0xF) {
  364. // New trigger packets
  365. LHCb::TbTrigger* trigger = new LHCb::TbTrigger(packet);
  366. extendTimeStamp(trigger, f->timer());
  367. trigger->setPlane(f->plane());
  368. writePacket(trigger, f, triggers);
  369. ++m_nTriggersRead;
  370. if (m_monitoring) {
  371. plot(trigger->time() / Tb::millisecond, "TriggerDataRate",
  372. "Rate of trigger packets", 0.0, 620000.0, 620000);
  373. }
  374. } else if (header == 0x4 && ! m_ignoreGlobalClock ) {
  375. // Timing packets
  376. int state = f->addTimingPacket(packet);
  377. if (state == 2)
  378. {
  379. warning() << "Jump in timing of greater than 6.7s detected."
  380. << format("Dropping timing packet: 0x%x", packet)
  381. << endmsg;
  382. warning() << "Will attempt to resynchronise using a different SPIDR's"
  383. << " global clock" << endmsg;
  384. attemptResync( f , packet );
  385. if( m_nLostTimers > m_maxLostTimers ) return true;
  386. // If fail to add as a timing packet, data packet unknown
  387. }
  388. else if (state == 0) {
  389. ++m_unknownPackets;
  390. if (UNLIKELY(msgLevel(MSG::DEBUG))) {
  391. debug() << format("Timing packet with subheader 0x%x, packet = 0x%x",
  392. ((packet >> 56) & 0xF), packet)
  393. << endmsg;
  394. }
  395. }
  396. }
  397. else {
  398. // Packet is neither hit, nor a trigger, nor a timing packet.
  399. ++m_unknownPackets;
  400. if (UNLIKELY(msgLevel(MSG::DEBUG))) {
  401. warning() << format("Packet with header 0x%x, packet = 0x%x",
  402. header, packet) << endmsg;
  403. }
  404. }
  405. }
  406. std::sort(f->hitCache().begin(), f->hitCache().end(),
  407. TbFunctors::LessByTimeBP<const LHCb::TbHit*>());
  408. std::sort(f->trgCache().begin(), f->trgCache().end(),
  409. TbFunctors::LessByTimeBP<const LHCb::TbTrigger*>());
  410.  
  411. if (m_endTime != 0 && currentTime > m_endTime) eot = true;
  412. if (!hits->empty() || !triggers->empty() || f->eos()) return true;
  413. return false;
  414. }
  415.  
  416. //=============================================================================
  417. // Finalisation
  418. //=============================================================================
  419. void TbEventBuilder::syncTPX3(const uint64_t& thisPacketTime, TbRawStream* f) {
  420.  
  421. int timerMsbs = 0x3 & ( f->m_tpx3Timer >> 40 );
  422. int thisMsb = 0x3 & ( thisPacketTime >> 40 );
  423. constexpr uint64_t one = (uint64_t)(1) << 40;
  424.  
  425. if( thisMsb == timerMsbs+1 || thisMsb == timerMsbs-3){
  426. info() << "Updating clock " << (double)(f->m_tpx3Timer + one)/(double)Tb::second << endmsg;
  427. f->m_tpx3Timer += one;
  428. }
  429. if( thisMsb > timerMsbs ){
  430. info() << thisMsb << " " << timerMsbs << endmsg;
  431. }
  432. }
  433.  
  434. bool TbEventBuilder::attemptResync(TbRawStream* f, const uint64_t& packet) {
  435.  
  436. for (unsigned int chip = 0 ; chip != m_nPlanes; ++chip) {
  437. int64_t dt = (int64_t)f->timer() - (int64_t)m_streams[chip]->timer();
  438. if (std::abs(dt) > m_maxTimeDifference) {
  439. f->setLSB(m_streams[chip]->lsb());
  440. f->setGlobalClock(m_streams[chip]->timer());
  441. const int state = f->addTimingPacket(packet);
  442. if (state != 2) {
  443. info() << "Resync of device " << chip << " successful!" << endmsg;
  444. return true;
  445. }
  446. }
  447. }
  448. warning() << "Resynchronisation of device fails" << endmsg;
  449. // Empty the cache.
  450. for (auto it = f->hitCache().begin(); it != f->hitCache().end(); ++it) {
  451. if (*it) delete *it;
  452. }
  453. f->hitCache().clear();
  454. for (auto it = f->trgCache().begin(); it != f->trgCache().end(); ++it) {
  455. if (*it) delete *it;
  456. }
  457. f->trgCache().clear();
  458. m_nLostTimers++;
  459. return false;
  460. }
  461.  
  462. StatusCode TbEventBuilder::finalize() {
  463.  
  464. for (auto& f : m_streams) {
  465. info() << format("Plane %2u: %12u packets in file, %12u hits in cache",
  466. f->plane(), f->size(), f->hitCache().size()) << endmsg;
  467. for (auto it = f->hitCache().begin(); it != f->hitCache().end(); ++it) {
  468. if (*it) delete *it;
  469. }
  470. for (auto it = f->trgCache().begin(); it != f->trgCache().end(); ++it) {
  471. if (*it) delete *it;
  472. }
  473. f->close();
  474. }
  475. info() << "Fraction of data read: " << (double)m_nData /
  476. (double)m_nDataInFiles << endmsg;
  477. info() << "Number of packets lost: " << m_nLostPackets << endmsg;
  478. info() << "Unknown packets: " << m_unknownPackets << endmsg;
  479. if (m_nNoiseEvents > 0) {
  480. info() << "Skipped " << m_nNoiseEvents << " noise events." << endmsg;
  481. }
  482. // Finalise the base class.
  483. return TbAlgorithm::finalize();
  484. }
  485.  
  486. //=============================================================================
  487. // Dump cached packets into the current event
  488. //=============================================================================
  489. template <typename T>
  490. bool TbEventBuilder::dumpCache(
  491. TbRawStream* stream, KeyedContainer<T, Containers::HashMap>* container) {
  492.  
  493. // Load the hits/triggers stored in the cache.
  494. std::vector<T*>* cache = stream->cache<T*>();
  495. auto it = cache->begin();
  496. const auto end = cache->end();
  497. for (; it != end; ++it) {
  498. const auto time = (*it)->time();
  499. if (unlikely(time >= m_clock + m_overlapTime)) break;
  500. if (unlikely(time < m_clock - m_tick ) ) {
  501. // Packet is earlier than the current event.
  502. // If this happens, the cache may be too short.
  503. warning() << format("Packet 0x%016llX", (*it)->data()) << " is "
  504. << " ns before event low edge! Current event definition: "
  505. << (m_clock - m_tick) / Tb::SpidrTime << " to "
  506. << (m_clock + m_overlapTime) / Tb::SpidrTime << endmsg;
  507. ++m_nLostPackets;
  508. delete *it;
  509. if (m_nLostPackets > m_maxLostPackets) {
  510. error() << "Large number of packets lost -> critical failure" << endmsg;
  511. return false;
  512. }
  513. continue;
  514. }
  515. (*it)->setHtime(timingSvc()->globalToLocal(time));
  516. // Move packet to the TES.
  517. container->insert(*it);
  518. }
  519. cache->erase(cache->begin(), it);
  520. if (container->empty() && !cache->empty()) return false;
  521. return true;
  522. }
  523.  
  524. //=============================================================================
  525. // Extend the timestamp of a packet
  526. //=============================================================================
  527. template <typename T>
  528. void TbEventBuilder::extendTimeStamp(T* packet, uint64_t global_time) {
  529.  
  530. const uint64_t packet_time = packet->time();
  531. const int diff = (0x3 & (global_time >> 40)) - (0x3 & (packet_time >> 40));
  532. constexpr uint64_t one = (uint64_t)(1) << 40;
  533. // Calculate the difference between the bits that should match between
  534. // the spidr time and the global time, if they do not match, increment or
  535. // decrement the global time so that they match and add the 18 m.s.f.
  536. // of the global time to the packet time
  537. if (diff == 1 || diff == -3) {
  538. global_time = global_time - one;
  539. } else if (diff == -1 || diff == 3) {
  540. global_time = global_time + one;
  541. }
  542. packet->setTime((0x3FFFFFFFFFF & packet_time) +
  543. (global_time & 0xFFFFC0000000000));
  544. }
  545.  
  546. LHCb::TbHit* TbEventBuilder::decodeTPX3Hit( const uint64_t& packet,const unsigned int& pixelAddress, const unsigned int& device , const unsigned int& fCol ){
  547.  
  548. LHCb::TbHit* hit = new LHCb::TbHit();
  549. hit->setDevice(device);
  550. hit->setData(packet);
  551. hit->setPixelAddress(pixelAddress);
  552. // Decode the pixel address, first get the double column.
  553. const unsigned int dcol = (0xFE00 & pixelAddress) >> 8;
  554. // Get the super pixel address.
  555. const unsigned int spix = (0x01F8 & pixelAddress) >> 1;
  556. // Get the address of the pixel within the super pixel.
  557. const unsigned int pix = (0x0007 & pixelAddress);
  558. // Calculate and store the row and column numbers.
  559. const unsigned int col = dcol + pix / 4;
  560. const unsigned int row = spix + (pix & 0x3);
  561. hit->setCol(col);
  562. hit->setRow(row);
  563. hit->setScol(col + fCol);
  564. const unsigned int data = (packet & 0x00000FFFFFFF0000) >> 16;
  565. // Extract and store the ToT and the corresponding charge.
  566. const unsigned int tot = (data & 0x00003FF0) >> 4;
  567. hit->setToT(tot);
  568. // hit->setCharge(pixelSvc()->charge(tot, pixelAddress, device));
  569. // Get the time stamps.
  570. const uint64_t spidrTime = packet & 0x000000000000FFFF;
  571. const uint64_t ftoa = data & 0x0000000F;
  572. const uint64_t toa = (data & 0x0FFFC000) >> 14;
  573. // Calculate the global timestamp.
  574. const uint64_t fulltime = ((spidrTime << 18) + (toa << 4) + (15 - ftoa)) << 8;
  575. hit->setTime(fulltime);
  576.  
  577. return hit;
  578. }
  579.