EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TPCFEETestRecov1.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TPCFEETestRecov1.cc
1 /*
2  * TPCFEETestRecov1.cc
3  *
4  * Created on: Sep 19, 2018
5  * Author: jinhuang
6  */
7 
8 #include "TPCFEETestRecov1.h"
9 
10 #include "TPCDaqDefs.h"
11 
12 #include <g4detectors/PHG4Cell.h>
16 #include <g4main/PHG4Hit.h>
18 
21 #include <fun4all/Fun4AllServer.h>
22 #include <fun4all/PHTFileServer.h>
23 
26 #include <phool/PHCompositeNode.h>
27 #include <phool/getClass.h>
28 
29 #include <Event/Event.h>
30 #include <Event/EventTypes.h>
31 #include <Event/packet.h>
32 //#include <Event/packetConstants.h>
33 #include <Event/oncsSubConstants.h>
34 
35 #include <TClonesArray.h>
36 #include <TFile.h>
37 #include <TH1D.h>
38 #include <TH2D.h>
39 #include <TString.h>
40 #include <TTree.h>
41 #include <TVector3.h>
42 
43 #include <CLHEP/Units/SystemOfUnits.h>
44 
45 #include <boost/bimap.hpp>
46 #include <boost/bind.hpp>
47 #include <boost/format.hpp>
48 #include <boost/graph/adjacency_list.hpp>
49 #include <boost/graph/connected_components.hpp>
50 
51 #include <algorithm>
52 #include <array>
53 #include <cassert>
54 #include <cmath>
55 #include <iostream>
56 #include <limits>
57 #include <map>
58 #include <sstream>
59 #include <stdexcept>
60 #include <tuple>
61 
62 using namespace std;
63 using namespace TPCDaqDefs::FEEv1;
64 
65 TPCFEETestRecov1::TPCFEETestRecov1(const std::string& outputfilename)
66  : SubsysReco("TPCFEETestRecov1")
67  , m_outputFileName(outputfilename)
68  , m_eventT(nullptr)
69  , m_peventHeader(&m_eventHeader)
70  , m_nClusters(-1)
71  , m_IOClusters(nullptr)
72  , m_chanT(nullptr)
73  , m_pchanHeader(&m_chanHeader)
74  , m_chanData(kSAMPLE_LENGTH, 0)
75  , m_clusteringZeroSuppression(50)
76  , m_nPreSample(5)
77  , m_nPostSample(5)
78  , m_XRayLocationX(-1)
79  , m_XRayLocationY(-1)
80  , m_pdfMaker(nullptr)
81 {
82 }
83 
85 {
86  if (m_IOClusters)
87  {
88  m_IOClusters->Clear();
89  delete m_IOClusters;
90  }
91 
92  if (m_pdfMaker)
93  {
94  delete m_pdfMaker;
95  }
96 }
97 
99 {
102  m_clusters.clear();
104 
105  m_nClusters = -1;
106  assert(m_IOClusters);
107  m_IOClusters->Clear();
108 
110 }
111 
113 {
115 }
116 
118 {
119  if (Verbosity() >= VERBOSITY_SOME)
120  {
121  cout << "TPCFEETestRecov1::get_HistoManager - Making PHTFileServer " << m_outputFileName
122  << endl;
123 
125  }
127 
129  assert(hm);
130 
131  TH1D* h = new TH1D("hNormalization", //
132  "Normalization;Items;Summed quantity", 10, .5, 10.5);
133  int i = 1;
134  h->GetXaxis()->SetBinLabel(i++, "Event count");
135  h->GetXaxis()->SetBinLabel(i++, "Collision count");
136  h->GetXaxis()->SetBinLabel(i++, "TPC G4Hit");
137  h->GetXaxis()->SetBinLabel(i++, "TPC G4Hit Edep");
138  h->GetXaxis()->SetBinLabel(i++, "TPC Pad Hit");
139  h->GetXaxis()->SetBinLabel(i++, "TPC Charge e");
140  h->GetXaxis()->SetBinLabel(i++, "TPC Charge fC");
141  h->GetXaxis()->LabelsOption("v");
142  hm->registerHisto(h);
143 
144  m_eventT = new TTree("eventT", "TPC FEE per-event Tree");
145  assert(m_eventT);
146  m_eventT->Branch("evthdr", &m_peventHeader);
147  m_eventT->Branch("nClusters", &m_nClusters, "nClusters/I");
148  m_IOClusters = new TClonesArray("TPCFEETestRecov1::ClusterData", 1000);
149  m_eventT->Branch("Clusters", &m_IOClusters);
150 
151  m_chanT = new TTree("chanT", "TPC FEE per-channel Tree");
152  assert(m_chanT);
153  m_chanT->Branch("event", &m_eventHeader.event, "event/I");
154  m_chanT->Branch("chanhdr", &m_pchanHeader);
155  m_chanT->Branch("adc", m_chanData.data(), str(boost::format("adc[%d]/i") % kSAMPLE_LENGTH).c_str());
156 
157  // for (unsigned int layer = m_minLayer; layer <= m_maxLayer; ++layer)
158  // {
159  // const PHG4CylinderCellGeom* layer_geom = seggeo->GetLayerCellGeom(layer);
160 
161  // const string histNameCellHit(boost::str(boost::format{"hCellHit_Layer%1%"} % layer));
162  // const string histNameCellCharge(boost::str(boost::format{"hCellCharge_Layer%1%"} % layer));
163 
164  // }
165 
166  // hm->registerHisto(new TH2D("hLayerCellHit", //
167  // "Number of ADC time-bin hit per channel;Layer ID;Hit number",
168  // m_maxLayer - m_minLayer + 1, m_minLayer - .5, m_maxLayer + .5,
169  // 300, -.5, 299.5));
170  // hm->registerHisto(new TH2D("hLayerCellCharge", //
171  // "Charge integrated over drift window per channel;Layer ID;Charge [fC]",
172  // m_maxLayer - m_minLayer + 1, m_minLayer - .5, m_maxLayer + .5,
173  // 1000, 0, 1e7 * eplus / (1e-15 * coulomb)));
174  //
175  // hm->registerHisto(new TH2D("hLayerSumCellHit", //
176  // "Number of ADC time-bin hit integrated over channels per layer;Layer ID;Hit number",
177  // m_maxLayer - m_minLayer + 1, m_minLayer - .5, m_maxLayer + .5,
178  // 10000, -.5, 99999.5));
179  // hm->registerHisto(new TH2D("hLayerSumCellCharge", //
180  // "Charge integrated over drift window and channel per layer;Layer ID;Charge [fC]",
181  // m_maxLayer - m_minLayer + 1, m_minLayer - .5, m_maxLayer + .5,
182  // 10000, 0, 1000 * 4e6 * eplus / (1e-15 * coulomb)));
183 
185 }
186 
188 {
189  if (Verbosity() >= VERBOSITY_SOME)
190  {
191  cout << "TPCFEETestRecov1::End - write to " << m_outputFileName << endl;
192  }
194 
196  assert(hm);
197  for (unsigned int i = 0; i < hm->nHistos(); i++)
198  hm->getHisto(i)->Write();
199 
200  // help index files with TChain
201  TTree* T_Index = new TTree("T_Index", "T_Index");
202  assert(T_Index);
203  T_Index->Write();
204 
205  m_eventT->Write();
206  m_chanT->Write();
207 
208  if (m_pdfMaker)
209  {
210  delete m_pdfMaker;
211  m_pdfMaker = nullptr;
212  }
214 }
215 
217 {
219  assert(hm);
220  TH1D* h_norm = dynamic_cast<TH1D*>(hm->getHisto("hNormalization"));
221  assert(h_norm);
222 
223  Event* event = findNode::getClass<Event>(topNode, "PRDF");
224  if (event == nullptr)
225  {
226  if (Verbosity() >= VERBOSITY_SOME)
227  cout << "GenericUnpackPRDF::Process_Event - Event not found" << endl;
229  }
230 
231  if (Verbosity() >= VERBOSITY_SOME)
232  event->identify();
233 
234  // search for data event
235  if (event->getEvtType() == BEGRUNEVENT)
236  {
237  get_motor_loc(event);
238 
240  }
241  if (event->getEvtType() != DATAEVENT)
243 
244  m_eventHeader.run = event->getRunNumber();
245  m_eventHeader.event = event->getEvtSequence();
246 
249 
250  if (m_pdfMaker)
251  {
252  m_pdfMaker->MakeSectionPage(str(boost::format("ADC signal fits for Run %1% and event %2%") % m_eventHeader.run % m_eventHeader.event));
253  }
254 
255  Packet* p = event->getPacket(kPACKET_ID, ID4EVT);
256  if (p == nullptr)
258 
259  if (Verbosity() >= VERBOSITY_SOME) p->identify();
260 
261  if (Verbosity() >= VERBOSITY_MORE)
262  {
263  cout << "TPCFEETestRecov1::process_event - p->iValue(0) = "
264  << p->iValue(0) << ", p->iValue(1) = " << p->iValue(1)
265  << ", p->iValue(2) = " << p->iValue(2)
266  << ", p->iValue(3) = " << p->iValue(3) << endl;
267  p->dump();
268  }
269 
271  bool first_channel = true;
272  for (unsigned int channel = 0; channel < kN_CHANNELS; channel++)
273  {
275 
276  m_chanHeader.size = p->iValue(channel * kPACKET_LENGTH + 1) & 0xffff; // number of words until the next channel (header included). this is the real packet_length
277  m_chanHeader.packet_type = p->iValue(channel * kPACKET_LENGTH + 2) & 0xffff; // that's the Elink packet type
278  m_chanHeader.bx_counter = ((p->iValue(channel * kPACKET_LENGTH + 4) & 0xffff) << 4) | (p->iValue(channel * kPACKET_LENGTH + 5) & 0xffff);
279  m_chanHeader.sampa_address = (p->iValue(channel * kPACKET_LENGTH + 3) >> 5) & 0xf;
280  m_chanHeader.sampa_channel = p->iValue(channel * kPACKET_LENGTH + 3) & 0x1f;
282 
283  const pair<int, int> pad = SAMPAChan2PadXY(m_chanHeader.fee_channel);
284 
285  m_chanHeader.pad_x = pad.first;
286  m_chanHeader.pad_y = pad.second;
287 
288  if (first_channel)
289  {
290  first_channel = false;
292  }
294  {
296 
297  // printf("TPCFEETestRecov1::process_event - ERROR: Malformed packet, event number %i, reason: bx_counter mismatch (expected 0x%x, got 0x%x)\n", m_eventHeader.event, m_eventHeader.bx_counter, m_chanHeader.bx_counter);
298  //
299  // event->identify();
300  // p->identify();
301  // return Fun4AllReturnCodes::DISCARDEVENT;
302  }
303 
305  {
306  printf("TPCFEETestRecov1::process_event - ERROR: Malformed packet, event number %i, reason: bad channel (got %i, sampa_addr: %i, sampa_chan: %i)\n", m_eventHeader.event, m_chanHeader.fee_channel, m_chanHeader.sampa_address, m_chanHeader.sampa_channel);
307 
308  event->identify();
309  p->identify();
311  }
312 
313  // SampaChannel *chan = fee_data->append(new SampaChannel(fee_channel, bx_counter, packet_type));
314 
315  assert(m_chanData.size() == kSAMPLE_LENGTH);
316  fill(m_chanData.begin(), m_chanData.end(), 0);
317  for (unsigned int sample = 0; sample < kSAMPLE_LENGTH; sample++)
318  {
319  // chan->append(p->iValue(channel * PACKET_LENGTH + 9 + sample) & 0xffff);
320  uint32_t value = p->iValue(channel * kPACKET_LENGTH + 9 + sample) & 0xffff;
321  m_chanData[sample] = value;
322  }
323 
324  if (Verbosity() >= VERBOSITY_MORE)
325  {
326  cout << "TPCFEETestRecov1::process_event - "
327  << "m_chanHeader.m_size = " << int(m_chanHeader.size) << ", "
328  << "m_chanHeader.m_packet_type = " << int(m_chanHeader.packet_type) << ", "
329  << "m_chanHeader.m_bx_counter = " << int(m_chanHeader.bx_counter) << ", "
330  << "m_chanHeader.m_sampa_address = " << int(m_chanHeader.sampa_address) << ", "
331  << "m_chanHeader.m_sampa_channel = " << int(m_chanHeader.sampa_channel) << ", "
332  << "m_chanHeader.m_fee_channel = " << int(m_chanHeader.fee_channel) << ": "
333  << " ";
334 
335  for (unsigned int sample = 0; sample < kSAMPLE_LENGTH; sample++)
336  {
337  cout << "data[" << sample << "] = " << int(m_chanData[sample]) << " ";
338  }
339 
340  cout << endl;
341  }
342 
343  // fill event data
345  {
346  vector<int>& paddata = m_padPlaneData.getPad(m_chanHeader.pad_x, m_chanHeader.pad_y);
347 
348  for (unsigned int sample = 0; sample < kSAMPLE_LENGTH; sample++)
349  {
350  paddata[sample] = int(m_chanData[sample]);
351  }
352 
353  auto pedestal_max = roughZeroSuppression(paddata);
354  m_chanHeader.pedestal = pedestal_max.first;
355  m_chanHeader.max = pedestal_max.second;
356  }
357  // output per-channel TTree
358  m_chanT->Fill();
359  }
360 
361  Clustering();
362 
363  h_norm->Fill("Event count", 1);
364  m_eventT->Fill();
365 
367 }
368 
370 {
371  // find cluster
373  const multimap<int, PadPlaneData::SampleID>& groups = m_padPlaneData.getGroups();
374 
375  // export clusters
376  assert(m_clusters.size() == 0); //already cleared.
377  for (const auto& iter : groups)
378  {
379  const int& i = iter.first;
380  const PadPlaneData::SampleID& id = iter.second;
381  m_clusters[i].padxs.insert(id.padx);
382  m_clusters[i].padys.insert(id.pady);
383  m_clusters[i].samples.insert(id.sample);
384  }
385 
386  // process cluster
387  for (auto& iter : m_clusters)
388  {
389  ClusterData& cluster = iter.second;
390 
391  assert(cluster.padxs.size() > 0);
392  assert(cluster.padys.size() > 0);
393  assert(cluster.samples.size() > 0);
394 
395  cluster.min_sample = max(0, *cluster.samples.begin() - m_nPreSample);
396  cluster.max_sample = min((int) (kSAMPLE_LENGTH) -1, *cluster.samples.rbegin() + m_nPostSample);
397  const int n_sample = cluster.max_sample - cluster.min_sample + 1;
398 
399  cluster.sum_samples.assign(n_sample, 0);
400  for (int pad_x = *cluster.padxs.begin(); pad_x <= *cluster.padxs.rbegin(); ++pad_x)
401  {
402  cluster.padx_samples[pad_x].assign(n_sample, 0);
403  }
404  for (int pad_y = *cluster.padys.begin(); pad_y <= *cluster.padys.rbegin(); ++pad_y)
405  {
406  cluster.pady_samples[pad_y].assign(n_sample, 0);
407  }
408 
409  for (int pad_x = *cluster.padxs.begin(); pad_x <= *cluster.padxs.rbegin(); ++pad_x)
410  {
411  for (int pad_y = *cluster.padys.begin(); pad_y <= *cluster.padys.rbegin(); ++pad_y)
412  {
413  assert(m_padPlaneData.IsValidPad(pad_x, pad_y));
414 
415  vector<int>& padsamples = m_padPlaneData.getPad(pad_x, pad_y);
416 
417  for (int i = 0; i < n_sample; ++i)
418  {
419  int adc = padsamples.at(cluster.min_sample + i);
420  cluster.sum_samples[i] += adc;
421  cluster.padx_samples[pad_x][i] += adc;
422  cluster.pady_samples[pad_y][i] += adc;
423  }
424 
425  } // for (int pad_y = *cluster.padys.begin(); pad_y<=*cluster.padys.rbegin() ;++pady)
426 
427  } // for (int pad_x = *cluster.padxs.begin(); pad_x<=*cluster.padxs.rbegin() ;++padx)
428 
429  if (m_pdfMaker)
430  {
431  m_pdfMaker->MakeSectionPage(str(boost::format("Event %1% Cluster %2%: sum all channel fit followed by fit of X/Y components") % m_eventHeader.event % iter.first));
432  }
433 
434  // fit - overal cluster
435  map<int, double> parameters_constraints;
436  {
437  double peak = NAN;
438  double peak_sample = NAN;
439  double pedstal = NAN;
440  map<int, double> parameters_io;
442  peak_sample, pedstal, parameters_io, Verbosity());
443 
444  parameters_constraints[1] = parameters_io[1];
445  parameters_constraints[2] = parameters_io[2];
446  parameters_constraints[3] = parameters_io[3];
447  parameters_constraints[5] = parameters_io[5];
448  parameters_constraints[6] = parameters_io[6];
449 
450  cluster.peak = peak;
451  cluster.peak_sample = peak_sample;
452  cluster.pedstal = pedstal;
453  }
454 
455  // fit - X
456  {
457  double sum_peak = 0;
458  double sum_peak_padx = 0;
459  for (int pad_x = *cluster.padxs.begin(); pad_x <= *cluster.padxs.rbegin(); ++pad_x)
460  {
461  double peak = NAN;
462  double peak_sample = NAN;
463  double pedstal = NAN;
464  map<int, double> parameters_io(parameters_constraints);
465 
466  SampleFit_PowerLawDoubleExp(cluster.padx_samples[pad_x], peak,
467  peak_sample, pedstal, parameters_io, Verbosity());
468 
469  cluster.padx_peaks[pad_x] = peak;
470  sum_peak += peak;
471  sum_peak_padx += peak * pad_x;
472  }
473  cluster.avg_padx = sum_peak_padx / sum_peak;
474  cluster.size_pad_x = cluster.padxs.size();
475  }
476 
477  // fit - Y
478  {
479  double sum_peak = 0;
480  double sum_peak_pady = 0;
481  for (int pad_y = *cluster.padys.begin(); pad_y <= *cluster.padys.rbegin(); ++pad_y)
482  {
483  double peak = NAN;
484  double peak_sample = NAN;
485  double pedstal = NAN;
486  map<int, double> parameters_io(parameters_constraints);
487 
488  SampleFit_PowerLawDoubleExp(cluster.pady_samples[pad_y], peak,
489  peak_sample, pedstal, parameters_io, Verbosity());
490 
491  cluster.pady_peaks[pad_y] = peak;
492  sum_peak += peak;
493  sum_peak_pady += peak * pad_y;
494  }
495  cluster.avg_pady = sum_peak_pady / sum_peak;
496  cluster.size_pad_y = cluster.padys.size();
497  }
498  } // for (auto& iter : m_clusters)
499 
500  // sort by energy
501  map<double, int> cluster_energy;
502  for (auto& iter : m_clusters)
503  {
504  //reverse energy sorting
505  cluster_energy[-iter.second.peak] = iter.first;
506  }
507 
508  // save clusters
509  m_nClusters = 0;
510  assert(m_IOClusters);
511  for (const auto& iter : cluster_energy)
512  {
513  ClusterData& cluster = m_clusters[iter.second];
514 
515  // super awkward ways of ROOT filling TClonesArray
516  new ((*m_IOClusters)[m_nClusters++]) ClusterData(cluster);
517  }
518 }
519 
523 {
524 }
525 
527 {
528  for (auto& padrow : m_data)
529  {
530  for (auto& pad : padrow)
531  {
532  fill(pad.begin(), pad.end(), 0);
533  }
534  }
535 
536  m_groups.clear();
537 }
538 
539 bool TPCFEETestRecov1::PadPlaneData::IsValidPad(const int pad_x, const int pad_y)
540 {
541  return (pad_x >= 0) and
542  (pad_x < int(kMaxPadX)) and
543  (pad_y >= 0) and
544  (pad_y < int(kMaxPadY));
545 }
546 
547 vector<int>& TPCFEETestRecov1::PadPlaneData::getPad(const int pad_x, const int pad_y)
548 {
549  assert(pad_x >= 0);
550  assert(pad_x < int(kMaxPadX));
551  assert(pad_y >= 0);
552  assert(pad_y < int(kMaxPadY));
553 
554  return m_data[pad_y][pad_x];
555 }
556 
557 std::pair<int, int> TPCFEETestRecov1::roughZeroSuppression(std::vector<int>& data)
558 {
559  std::vector<int> sorted_data(data);
560 
561  sort(sorted_data.begin(), sorted_data.end());
562 
563  const int pedestal = sorted_data[sorted_data.size() / 2];
564  const int max = sorted_data.back();
565 
566  for (auto& d : data)
567  d -= pedestal;
568 
569  return make_pair(pedestal, max);
570 }
571 
573 {
574  if (s1.pady == s2.pady)
575  {
576  if (s1.padx == s2.padx)
577  {
578  return s1.sample < s2.sample;
579  }
580  else
581  return s1.padx < s2.padx;
582  }
583  else
584  return s1.pady < s2.pady;
585 }
586 
588 void TPCFEETestRecov1::PadPlaneData::Clustering(int zero_suppression, bool verbosity)
589 {
590  using namespace boost;
591  typedef adjacency_list<vecS, vecS, undirectedS> Graph;
592  typedef bimap<Graph::vertex_descriptor, SampleID> VertexList;
593 
594  Graph G;
595  VertexList vertex_list;
596 
597  for (unsigned int pady = 0; pady < kMaxPadY; ++pady)
598  {
599  for (unsigned int padx = 0; padx < kMaxPadX; ++padx)
600  {
601  for (unsigned int sample = 0; sample < kSAMPLE_LENGTH; sample++)
602  {
603  if (m_data[pady][padx][sample] > zero_suppression)
604  {
605  SampleID id{(int) (pady), (int) (padx), (int) (sample)};
606  Graph::vertex_descriptor v = boost::add_vertex(G);
607  vertex_list.insert(VertexList::value_type(v, id));
608 
609  add_edge(v, v, G);
610  }
611  } // for (unsigned int sample = 0; sample < kSAMPLE_LENGTH; sample++)
612  }
613  } // for (unsigned int pady = 0; pady < kMaxPadY; ++pady)
614 
615  // connect 3-D adjacent samples
616  vector<SampleID> search_directions;
617  search_directions.push_back(SampleID{0, 0, 1});
618  search_directions.push_back(SampleID{0, 1, 0});
619  search_directions.push_back(SampleID{1, 0, 0});
620 
621  for (const auto& it : vertex_list.right)
622  {
623  const SampleID id = it.first;
624  const Graph::vertex_descriptor v = it.second;
625 
626  for (const SampleID& search_direction : search_directions)
627  {
628  // const SampleID next_id = id + search_direction;
629  SampleID next_id(id);
630  next_id.adjust(search_direction);
631 
632  auto next_it = vertex_list.right.find(next_id);
633  if (next_it != vertex_list.right.end())
634  {
635  add_edge(v, next_it->second, G);
636  }
637  }
638 
639  } // for (const auto & it : vertex_list)
640 
641  // Find the connections between the vertices of the graph (vertices are the rawhits,
642  // connections are made when they are adjacent to one another)
643  std::vector<int> component(num_vertices(G));
644  connected_components(G, &component[0]);
645 
646  // Loop over the components(vertices) compiling a list of the unique
647  // connections (ie clusters).
648  set<int> comps; // Number of unique components
649  assert(m_groups.size() == 0); // no overwrite
650 
651  for (unsigned int i = 0; i < component.size(); i++)
652  {
653  comps.insert(component[i]);
654  m_groups.insert(make_pair(component[i], vertex_list.left.find(vertex(i, G))->second));
655  }
656 
657  //debug prints
658  if (verbosity)
659  for (const int& comp : comps)
660  {
661  cout << "TPCFEETestRecov1::PadPlaneData::Clustering - find cluster " << comp << " containing ";
662  const auto range = m_groups.equal_range(comp);
663 
664  for (auto iter = range.first; iter != range.second; ++iter)
665  {
666  const SampleID& id = iter->second;
667  cout << "adc[" << id.pady << "][" << id.padx << "][" << id.sample << "] = " << m_data[id.pady][id.padx][id.sample] << ", ";
668  }
669  cout << endl;
670  } // for (const int& comp : comps)
671 }
672 
675 {
676  static string histname("TPCFEETestRecov1_HISTOS");
677 
679  Fun4AllHistoManager* hm = se->getHistoManager(histname);
680 
681  if (not hm)
682  {
683  cout
684  << "TPCFEETestRecov1::get_HistoManager - Making Fun4AllHistoManager "
685  << histname << endl;
686  hm = new Fun4AllHistoManager(histname);
687  se->registerHistoManager(hm);
688  }
689 
690  assert(hm);
691 
692  return hm;
693 }
694 
696 {
697  assert(evt);
698 
699  Packet* motor_loc_p = evt->getPacket(910, IDCSTR);
700 
701  if (motor_loc_p)
702  {
703  string content;
704 
705  for (int i = 0; i < motor_loc_p->getLength(); i++)
706  {
707  content.push_back((char) motor_loc_p->iValue(i));
708  }
709 
710  stringstream is(content);
712 
713  if (is.fail())
714  {
715  cout << "TPCFEETestRecov1::get_motor_loc - failed to load motor location from record [" << content << "]" << endl;
716  }
717  else if (Verbosity())
718  cout << "TPCFEETestRecov1::get_motor_loc - received motor location " << m_XRayLocationX << ", " << m_XRayLocationY << " from record [" << content << "]" << endl;
719  }
720 }