CRTFragment.cc
Go to the documentation of this file.
1 /* Author: Matthew Strait <mstrait@fnal.gov> */
2 
3 #include "CRTFragment.hh"
4 
5 #include <ostream>
6 
7 namespace CRT
8 {
9  // Return the module number for this fragment. A CRT fragment consists
10  // of a set of hits sharing a time stamp from one module.
11  uint16_t Fragment::module_num() const
12  {
13  return header()->module_num;
14  }
15 
16  // Return the number of hits claimed in the header of this fragment
17  size_t Fragment::num_hits() const
18  {
19  return header()->nhit;
20  }
21 
22  // Return the value of the 50MHz counter that holds the raw internal CRT time
23  uint64_t Fragment::raw_backend_time() const
24  {
25  return header()->raw_backend_time;
26  }
27 
28  // Return the value of the 50MHz counter that holds the global ProtoDUNE time
29  uint64_t Fragment::fifty_mhz_time() const
30  {
31  return header()->fifty_mhz_time;
32  }
33 
34  // Return the channel number of the ith hit. That hit must exist.
35  uint8_t Fragment::channel(const int i) const
36  {
37  return hit(i)->channel;
38  }
39 
40  // Return the ADC value of the ith hit. That hit must exist.
41  int16_t Fragment::adc(const int i) const
42  {
43  return hit(i)->adc;
44  }
45 
46  // Print the header to stdout, even if it is bad, but not if it
47  // isn't all there.
49  {
50  if(size() < sizeof(header_t)){
51  std::cerr << "CRT fragment smaller (" << size() << "B) than header ("
52  << sizeof(header_t) << "B), can't print\n";
53  return;
54  }
55 
56  std::cout << "CRT header: Magic = '" << header()->magic << "'\n"
57  << " n hit = " << +(header()->nhit) << "\n"
58  << " module = " << header()->module_num << "\n"
59  << " 50Mhz time = " << header()->fifty_mhz_time
60  << " (0x" << std::hex << header()->fifty_mhz_time << std::dec << ")\n"
61  << " raw time = " << header()->raw_backend_time << " (0x"
62  << std::hex << header()->raw_backend_time << std::dec << ")\n";
63  }
64 
65  // Print the given hit to stdout, even if it is bad, but not if it
66  // isn't all there.
67  void Fragment::print_hit(const int i) const
68  {
69  // Is pointer arithmetic valid in the case that we're checking for? Not
70  // sure what the standard says, but I think that practically this should
71  // work.
72  if((uint8_t *)hit(i) + sizeof(hit_t) > thefrag.dataEndBytes()){
73  std::cerr << "Hit " << i << " would be past end of fragment, can't print\n";
74  return;
75  }
76 
77  std::cout << "CRT hit " << i << ": Magic = '" << hit(i)->magic << "'\n"
78  << " channel = " << +(hit(i)->channel) << "\n"
79  << " ADC = " << hit(i)->adc << "\n";
80  }
81 
82  // Print all the hits
83  void Fragment::print_hits() const
84  {
85  for(int i = 0; i < header()->nhit; i++)
86  print_hit(i);
87  puts("");
88  }
89 
90  // Returns true if the header contains sensible values. Otherwise,
91  // prints a complaint and returns false. Assumes header is complete
92  // (check good_size() first).
93  bool Fragment::good_header() const
94  {
95  const header_t * const h = header();
96  if(h->magic != 'M'){
97  std::cerr << "CRT header has wrong magic: " << h->magic << "\n";
98  return false;
99  }
100  if(h->nhit == 0){
101  std::cerr << "CRT event has no hits\n";
102  return false;
103  }
104  if(h->nhit > 64){
105  std::cerr << "CRT event has more hits (" << h->nhit << ") than channels (64)\n";
106  return false;
107  }
108  return true;
109  }
110 
111  // Returns true if the hit contains sensible values. Otherwise,
112  // prints a complaint and returns false. Assumes hit exists and
113  // is complete (check good_size() first).
114  bool Fragment::good_hit(const int i) const
115  {
116  const hit_t * const h = hit(i);
117  if(h->magic != 'H'){
118  std::cerr << "CRT hit has wrong magic: " << h->magic << "\n";
119  return false;
120  }
121  if(h->channel >= 64){
122  std::cerr << "CRT hit has bad channel " << h->channel << " >= 64\n";
123  return false;
124  }
125  if(h->adc >= 4096){
126  // It is a 12-bit ADC. This number probably represents the raw
127  // ADC value before pedestal subtraction, but in any case, the
128  // pedestal is positive, so the value still can't exceed 4095.
129  std::cerr << "CRT hit has bad ADC value " << h->adc << " >= 4096\n";
130  return false;
131  }
132  return true;
133  }
134 
135  // Return the size of the CRT fragment in bytes.
136  unsigned int Fragment::size() const
137  {
138  return thefrag.dataEndBytes() - thefrag.dataBeginBytes();
139  }
140 
141  // Returns true if the fragment is as big as the header says it is,
142  // and false if it isn't, or it doesn't even have a full header.
143  // i.e. if this is false, you're going to seg fault (or wish you had)
144  // if you read the fragment.
145  bool Fragment::good_size() const
146  {
147  if(size() < sizeof(header_t)){
148  std::cerr << "CRT fragment isn't as big (" << size() << "B) as header (" << sizeof(header_t) << "B)\n";
149  return false;
150  }
151 
152  const unsigned int expect_size =
153  (sizeof(header_t) + header()->nhit * sizeof(hit_t)
154  + sizeof(artdaq::RawDataType) - 1)
155  /sizeof(artdaq::RawDataType)
156  *sizeof(artdaq::RawDataType);
157 
158  if(size() != expect_size){
159  std::cerr << "CRT fragment: N hit (" << header()->nhit << " -> " << expect_size << "B) mismatches size "
160  << size() << "B\n";
161  for(char * c = (char *) thefrag.dataBeginBytes();
162  c < (char *)thefrag.dataEndBytes();
163  c++){
164  std::cerr << (unsigned char)*c << "/"
165  << (isprint((unsigned char)*c)?(unsigned char)*c:'.');
166  if((c - (char*)thefrag.dataBeginBytes())%0x08 == 0x07)
167  std::cerr << " ";
168  if((c - (char*)thefrag.dataBeginBytes())%0x10 == 0x0f)
169  std::cerr << "\n";
170  }
171  std::cerr << "\n";
172  return false;
173  }
174  return true;
175  }
176 
177  // Return true if the fragment contains a complete and sensible event.
178  bool Fragment::good_event() const
179  {
180  if(!good_size()) return false;
181 
182  if(!good_header()) return false;
183 
184  for(unsigned int i = 0; i < header()->nhit; i++)
185  if(!good_hit(i))
186  return false;
187 
188  return true;
189  }
190 
191  // Return a pointer to hit 'i'. Not range checked.
192  const CRT::Fragment::hit_t * Fragment::hit(const int i) const
193  {
194  return reinterpret_cast<const hit_t *>
195  (thefrag.dataBeginBytes() + sizeof(header_t) + i*sizeof(hit_t));
196  }
197 
198  // Return a pointer to the header
200  {
201  return reinterpret_cast<const header_t *>(thefrag.dataBeginBytes());
202  }
203 }
uint64_t fifty_mhz_time() const
Definition: CRTFragment.cc:29
void print_hit(const int i) const
Definition: CRTFragment.cc:67
unsigned int size() const
Definition: CRTFragment.cc:136
void print_header() const
Definition: CRTFragment.cc:48
uint64_t raw_backend_time() const
Definition: CRTFragment.cc:23
int16_t adc(const int i) const
Definition: CRTFragment.cc:41
QTextStream & hex(QTextStream &s)
size_t num_hits() const
Definition: CRTFragment.cc:17
bool good_hit(const int i) const
Definition: CRTFragment.cc:114
bool good_event() const
Definition: CRTFragment.cc:178
uint8_t channel(const int i) const
Definition: CRTFragment.cc:35
QTextStream & dec(QTextStream &s)
const header_t * header() const
Definition: CRTFragment.cc:199
uint16_t module_num() const
Definition: CRTFragment.cc:11
bool good_size() const
Definition: CRTFragment.cc:145
void print_hits() const
Definition: CRTFragment.cc:83
bool good_header() const
Definition: CRTFragment.cc:93
artdaq::Fragment const & thefrag
Definition: CRTFragment.hh:108
const hit_t * hit(const int i) const
Definition: CRTFragment.cc:192