LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
RawDataDrawer.cxx
Go to the documentation of this file.
1 
54 #include <algorithm> // std::fill(), std::find_if(), ...
55 #include <cmath> // std::abs(), ...
56 #include <cstddef> // std::ptrdiff_t
57 #include <limits> // std::numeric_limits<>
58 #include <memory> // std::unique_ptr()
59 #include <tuple>
60 #include <type_traits> // std::add_const_t<>, ...
61 #include <typeinfo> // to use typeid()
62 #include <utility> // std::move()
63 
64 #include "TBox.h"
65 #include "TFrame.h"
66 #include "TH1F.h"
67 #include "TVirtualPad.h"
68 
71 #include "lardataalg/Utilities/StatCollector.h" // lar::util::MinMaxCollector<>
73 #include "lardataobj/RawData/raw.h"
74 #include "lareventdisplay/EventDisplay/ChangeTrackers.h" // util::PlaneDataChangeTracker_t
78 #include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h"
79 #include "larevt/CalibrationDBI/Interface/ChannelStatusService.h"
80 #include "larevt/CalibrationDBI/Interface/DetPedestalProvider.h"
81 #include "larevt/CalibrationDBI/Interface/DetPedestalService.h"
83 
90 #include "cetlib_except/demangle.h"
92 
93 namespace {
94  template <typename Stream, typename T>
95  void PrintRange(Stream&& out, std::string header, lar::util::MinMaxCollector<T> const& range)
96  {
97  out << header << ": " << range.min() << " -- " << range.max() << " ("
98  << (range.has_data() ? "valid" : "invalid") << ")";
99  } // PrintRange()
100 } // local namespace
101 
102 // internal use classes declaration;
103 // it can't live in the header because it uses C++11/14
104 namespace details {
106  template <typename T>
108  public:
109  using value_type = T;
110  using const_value_type = std::add_const_t<value_type>;
111  using reference = std::add_lvalue_reference_t<value_type>;
112  using const_reference = std::add_lvalue_reference_t<const_value_type>;
113  using pointer = std::add_pointer_t<value_type>;
114  using const_pointer = std::add_pointer_t<const_value_type>;
115 
118 
121  const_reference operator*() const { return *pData; }
122  reference operator*() { return *pData; }
123 
124  const_pointer operator->() const { return pData; }
125  pointer operator->() { return pData; }
127 
129  operator bool() const { return hasData(); }
130 
132  bool operator!() const { return !hasData(); }
133 
135  bool hasData() const { return bool(pData); }
136 
138  bool owned() const { return bOwned && hasData(); }
139 
141  void SetData(pointer data, bool owned)
142  {
143  Clear();
144  bOwned = owned;
145  pData = data;
146  }
148  void AcquireData(pointer data) { SetData(data, true); }
150  void PointToData(pointer data) { SetData(data, false); }
152  void PointToData(reference data) { SetData(&data, false); }
154  void StealData(std::remove_const_t<T>&& data) { AcquireData(new T(std::move(data))); }
156  void NewData(T const& data) { AcquireData(new T(data)); }
158  void Clear()
159  {
160  if (bOwned) delete pData;
161  pData = nullptr;
162  bOwned = false;
163  } // Clear()
164 
165  protected:
166  bool bOwned = false;
167  pointer pData = nullptr;
168  }; // class PointerToData_t<>
169 }
170 
171 namespace evd {
172  namespace details {
173 
176  public:
178  art::Ptr<raw::RawDigit> DigitPtr() const { return digit; }
179 
181  raw::RawDigit const& Digit() const { return *digit; }
182 
184  raw::ChannelID_t Channel() const { return digit ? digit->Channel() : raw::InvalidChannelID; }
185 
187  short MinCharge() const { return SampleInfo().min_charge; }
188 
190  short MaxCharge() const { return SampleInfo().max_charge; }
191 
193  // short AverageCharge() const { return SampleInfo().average_charge; }
194 
196  raw::RawDigit::ADCvector_t const& Data() const;
197 
199  void Fill(art::Ptr<raw::RawDigit> const& src);
200 
202  void Clear();
203 
205  template <typename Stream>
206  void Dump(Stream&& out) const;
207 
208  private:
209  struct SampleInfo_t {
210  short min_charge = std::numeric_limits<short>::max();
211  short max_charge = std::numeric_limits<short>::max();
212  };
213 
215 
217  mutable ::details::PointerToData_t<raw::RawDigit::ADCvector_t const> data;
218 
220  mutable std::unique_ptr<SampleInfo_t> sample_info;
221 
223  void UncompressData() const;
224 
226  void CollectSampleInfo() const;
227 
229  SampleInfo_t const& SampleInfo() const;
230 
231  }; // class RawDigitInfo_t
232 
235  public:
237  std::vector<RawDigitInfo_t> const& Digits() const { return digits; }
238 
240  RawDigitInfo_t const* FindChannel(raw::ChannelID_t channel) const;
241 
243  size_t MaxSamples() const { return max_samples; }
244 
246  bool empty() const { return digits.empty(); }
247 
249  void Clear();
250 
252  void Refill(art::Handle<std::vector<raw::RawDigit>>& rdcol);
253 
255  void Invalidate();
256 
259  bool Update(art::Event const& evt, CacheID_t const& new_timestamp);
260 
262  template <typename Stream>
263  void Dump(Stream&& out) const;
264 
265  private:
267 
268  bool bUpToDate = false;
269  std::vector<raw::RawDigit> const* digits = nullptr;
270 
271  BoolWithUpToDateMetadata() = default;
272  BoolWithUpToDateMetadata(bool uptodate, std::vector<raw::RawDigit> const* newdigits)
273  : bUpToDate(uptodate), digits(newdigits)
274  {}
275 
276  operator bool() const { return bUpToDate; }
277  }; // struct BoolWithUpToDateMetadata
278 
279  std::vector<RawDigitInfo_t> digits;
280 
282 
283  size_t max_samples = 0;
284 
286  BoolWithUpToDateMetadata CheckUpToDate(CacheID_t const& ts,
287  art::Event const* evt = nullptr) const;
288 
289  static std::vector<raw::RawDigit> const* ReadProduct(art::Event const& evt,
290  art::InputTag label);
291 
292  }; // struct RawDigitCacheDataClass
293 
295  RawDigitCacheDataClass const& cache)
296  {
297  return cache.Digits().cbegin();
298  }
300  RawDigitCacheDataClass const& cache)
301  {
302  return cache.Digits().cend();
303  }
304 
307  public:
309  GridAxisClass() { Init(0, 0., 0.); }
310 
312  GridAxisClass(size_t nDiv, float new_min, float new_max) { Init(nDiv, new_min, new_max); }
313 
315  std::ptrdiff_t GetCell(float coord) const;
317  std::ptrdiff_t operator()(float coord) const { return GetCell(coord); }
319 
321  bool hasCell(std::ptrdiff_t iCell) const
322  {
323  return (iCell >= 0) && ((size_t)iCell < NCells());
324  }
325 
327  bool hasCoord(float coord) const { return (coord >= Min()) && (coord < Max()); }
328 
330  float Min() const { return min; }
332  float Max() const { return max; }
334 
336  float Length() const { return max - min; }
337 
339  size_t NCells() const { return n_cells; }
340 
342  bool isEmpty() const { return max == min; }
343 
345  float CellSize() const { return cell_size; }
346 
348  float LowerEdge(std::ptrdiff_t iCell) const { return Min() + CellSize() * iCell; }
349 
351  float UpperEdge(std::ptrdiff_t iCell) const { return LowerEdge(iCell + 1); }
352 
354  bool Init(size_t nDiv, float new_min, float new_max);
355 
357  bool SetLimits(float new_min, float new_max);
358 
361  bool SetMinCellSize(float min_size);
362 
365  bool SetMaxCellSize(float max_size);
366 
369  bool SetCellSizeBoundary(float min_size, float max_size)
370  {
371  return SetMinCellSize(min_size) || SetMaxCellSize(max_size);
372  }
373 
374  template <typename Stream>
375  void Dump(Stream&& out) const;
376 
377  private:
378  size_t n_cells;
379  float min, max;
380 
381  float cell_size;
382 
383  }; // GridAxisClass
384 
387  public:
389  CellGridClass() : wire_axis(), tdc_axis() {}
390 
392  CellGridClass(unsigned int nWires, unsigned int nTDC);
393 
395  CellGridClass(float min_wire,
396  float max_wire,
397  unsigned int nWires,
398  float min_tdc,
399  float max_tdc,
400  unsigned int nTDC);
401 
403  size_t NCells() const { return wire_axis.NCells() * tdc_axis.NCells(); }
404 
406  GridAxisClass const& WireAxis() const { return wire_axis; }
407 
409  GridAxisClass const& TDCAxis() const { return tdc_axis; }
410 
412  std::ptrdiff_t GetCell(float wire, float tick) const;
413 
415  std::tuple<float, float, float, float> GetCellBox(std::ptrdiff_t iCell) const;
416 
418  bool hasWire(float wire) const { return wire_axis.hasCoord(wire); }
420  bool hasWire(int wire) const { return hasWire((float)wire); }
422 
424  bool hasTick(float tick) const { return tdc_axis.hasCoord(tick); }
426  bool hasTick(int tick) const { return hasTick((float)tick); }
428 
431  template <typename CONT>
432  bool Add(CONT& cont, float wire, float tick, typename CONT::value_type v)
433  {
434  std::ptrdiff_t cell = GetCell(wire, tick);
435  if (cell < 0) return false;
436  cont[(size_t)cell] += v;
437  return true;
438  } // Add()
439 
443  void SetWireRange(unsigned int nWires) { SetWireRange(0., (float)nWires, nWires); }
444 
446  void SetWireRange(float min_wire, float max_wire) { wire_axis.SetLimits(min_wire, max_wire); }
447 
449  void SetWireRange(float min_wire, float max_wire, unsigned int nWires)
450  {
451  wire_axis.Init(nWires, min_wire, max_wire);
452  }
453 
455  void SetWireRange(float min_wire, float max_wire, unsigned int nWires, float min_size)
456  {
457  wire_axis.Init(nWires, min_wire, max_wire);
458  wire_axis.SetMinCellSize(min_size);
459  }
460 
462  void SetTDCRange(unsigned int nTDC) { SetTDCRange(0., (float)nTDC, nTDC); }
463 
465  void SetTDCRange(float min_tdc, float max_tdc, unsigned int nTDC)
466  {
467  tdc_axis.Init(nTDC, min_tdc, max_tdc);
468  }
469 
471  void SetTDCRange(float min_tdc, float max_tdc) { tdc_axis.SetLimits(min_tdc, max_tdc); }
472 
474  void SetTDCRange(float min_tdc, float max_tdc, unsigned int nTDC, float min_size)
475  {
476  tdc_axis.Init(nTDC, min_tdc, max_tdc);
477  tdc_axis.SetMinCellSize(min_size);
478  }
479 
481 
483  bool SetMinWireCellSize(float min_size) { return wire_axis.SetMinCellSize(min_size); }
484 
486  bool SetMinTDCCellSize(float min_size) { return tdc_axis.SetMinCellSize(min_size); }
487 
489  template <typename Stream>
490  void Dump(Stream&& out) const;
491 
492  private:
495  }; // CellGridClass
496 
497  //--------------------------------------------------------------------------
500  public:
502  : detProp{dp}
503  , wirePitch{art::ServiceHandle<geo::Geometry const>()->WirePitch(pid)}
504  , electronsToADC{dp.ElectronsToADC()}
505  {}
506 
508  double operator()(float adc) const
509  {
510  if (adc < 0.) return 0.;
511  double const dQdX = adc / wirePitch / electronsToADC;
512  return detProp.BirksCorrection(dQdX);
513  }
514 
515  private:
517  double wirePitch;
518  double electronsToADC;
519 
520  }; // ADCCorrectorClass
521  //--------------------------------------------------------------------------
522  } // namespace details
523 } // namespace evd
524 
525 namespace evd {
526 
527  // empty vector
528  std::vector<raw::RawDigit> const RawDataDrawer::EmptyRawDigits;
529 
530  //......................................................................
531  RawDataDrawer::RawDataDrawer()
532  : digit_cache(new details::RawDigitCacheDataClass)
533  , fStartTick(0)
534  , fTicks(2048)
535  , fCacheID(new details::CacheID_t)
536  , fDrawingRange(new details::CellGridClass)
537  {
539 
541  geo::TPCID tpcid(rawopt->fCryostat, rawopt->fTPC);
542 
543  fStartTick = rawopt->fStartTick;
544  fTicks = rawopt->fTicks;
545 
546  // set the list of bad channels in this detector
547  unsigned int nplanes = geo->Nplanes(tpcid);
548  fWireMin.resize(nplanes, -1);
549  fWireMax.resize(nplanes, -1);
550  fTimeMin.resize(nplanes, -1);
551  fTimeMax.resize(nplanes, -1);
552  fRawCharge.resize(nplanes, 0);
553  fConvertedCharge.resize(nplanes, 0);
554  }
555 
556  //......................................................................
558  {
559  delete digit_cache;
560  delete fDrawingRange;
561  delete fCacheID;
562  }
563 
564  //......................................................................
565  void RawDataDrawer::SetDrawingLimits(float low_wire,
566  float high_wire,
567  float low_tdc,
568  float high_tdc)
569  {
570  MF_LOG_DEBUG("RawDataDrawer") << __func__ << "() setting drawing range as wires ( " << low_wire
571  << " - " << high_wire << " ), ticks ( " << low_tdc << " - "
572  << high_tdc << " )";
573 
574  // we need to set the minimum cell size to 1, otherwise some cell will not
575  // cover any wire/tick and they will be always empty
576  if (PadResolution) {
577  // TODO implement support for swapping axes here
578  unsigned int wire_pixels = PadResolution.width;
579  unsigned int tdc_pixels = PadResolution.height;
580  fDrawingRange->SetWireRange(low_wire, high_wire, wire_pixels, 1.F);
581  fDrawingRange->SetTDCRange(low_tdc, high_tdc, tdc_pixels, 1.F);
582  }
583  else {
584  MF_LOG_DEBUG("RawDataDrawer") << "Pad size not available -- using existing cell size";
585  fDrawingRange->SetWireRange(low_wire, high_wire);
587  fDrawingRange->SetTDCRange(low_tdc, high_tdc);
589  }
590 
591  } // RawDataDrawer::SetDrawingLimits()
592 
594  {
595  SetDrawingLimits(fWireMin[plane], fWireMax[plane], fTimeMin[plane], fTimeMax[plane]);
596  } // RawDataDrawer::SetDrawingLimitsFromRoI()
597 
598  void RawDataDrawer::ExtractRange(TVirtualPad* pPad,
599  std::vector<double> const* zoom /* = nullptr */)
600  {
601  mf::LogDebug log("RawDataDrawer");
602  log << "ExtractRange() on pad '" << pPad->GetName() << "'";
603 
604  TFrame const* pFrame = pPad->GetFrame();
605  if (pFrame) {
606  // these coordinates are used to find the actual extent of pad in pixels
607  double low_wire = pFrame->GetX1(), high_wire = pFrame->GetX2();
608  double low_tdc = pFrame->GetY1(), high_tdc = pFrame->GetY2();
609  double const wire_pixels = pPad->XtoAbsPixel(high_wire) - pPad->XtoAbsPixel(low_wire);
610  double const tdc_pixels = -(pPad->YtoAbsPixel(high_tdc) - pPad->YtoAbsPixel(low_tdc));
611 
612  PadResolution.width = (unsigned int)wire_pixels;
613  PadResolution.height = (unsigned int)tdc_pixels;
614 
615  log << "\n frame window is " << PadResolution.width << "x" << PadResolution.height
616  << " pixel big and";
617  // those coordinates also are a (unreliable) estimation of the zoom;
618  // if we have a better one, let's use it
619  // (this does not change the size of the window in terms of pixels)
620  if (zoom) {
621  log << ", from external source,";
622  low_wire = (*zoom)[0];
623  high_wire = (*zoom)[1];
624  low_tdc = (*zoom)[2];
625  high_tdc = (*zoom)[3];
626  }
627 
628  log << " spans wires " << low_wire << "-" << high_wire << " and TDC " << low_tdc << "-"
629  << high_tdc;
630 
631  // TODO support swapping axes here:
632  // if (rawopt.fAxisOrientation < 1) { normal ; } else { swapped; }
633 
634  fDrawingRange->SetWireRange(low_wire, high_wire, (unsigned int)wire_pixels, 1.0);
635  fDrawingRange->SetTDCRange(low_tdc, high_tdc, (unsigned int)tdc_pixels, 1.0);
636  }
637  else {
638  // keep the old frame (if any)
639  log << "\n no frame!";
640  }
641 
642  } // RawDataDrawer::ExtractRange()
643 
644  //......................................................................
646  public:
647  OperationBaseClass(geo::PlaneID const& pid, RawDataDrawer* data_drawer = nullptr)
648  : pRawDataDrawer(data_drawer), planeID(pid)
649  {}
650 
651  virtual ~OperationBaseClass() = default;
652 
653  virtual bool Initialize() { return true; }
654 
655  virtual bool ProcessWire(geo::WireID const&) { return true; }
656  virtual bool ProcessTick(size_t) { return true; }
657 
658  virtual bool Operate(geo::WireID const& wireID, size_t tick, float adc) = 0;
659 
660  virtual bool Finish() { return true; }
661 
662  virtual std::string Name() const { return cet::demangle_symbol(typeid(*this).name()); }
663 
664  bool operator()(geo::WireID const& wireID, size_t tick, float adc)
665  {
666  return Operate(wireID, tick, adc);
667  }
668 
669  geo::PlaneID const& PlaneID() const { return planeID; }
670  RawDataDrawer* RawDataDrawerPtr() const { return pRawDataDrawer; }
671 
672  protected:
673  RawDataDrawer* pRawDataDrawer = nullptr;
674 
675  private:
677  }; // class RawDataDrawer::OperationBaseClass
678 
679  //......................................................................
681  std::vector<std::unique_ptr<RawDataDrawer::OperationBaseClass>> operations;
682 
683  public:
684  ManyOperations(geo::PlaneID const& pid, RawDataDrawer* data_drawer = nullptr)
685  : OperationBaseClass(pid, data_drawer)
686  {}
687 
688  bool Initialize() override
689  {
690  bool bAllOk = true;
691  for (std::unique_ptr<OperationBaseClass> const& op : operations)
692  if (!op->Initialize()) bAllOk = false;
693  return bAllOk;
694  }
695 
696  bool ProcessWire(geo::WireID const& wireID) override
697  {
698  for (std::unique_ptr<OperationBaseClass> const& op : operations)
699  if (op->ProcessWire(wireID)) return true;
700  return false;
701  }
702  bool ProcessTick(size_t tick) override
703  {
704  for (std::unique_ptr<OperationBaseClass> const& op : operations)
705  if (op->ProcessTick(tick)) return true;
706  return false;
707  }
708 
709  bool Operate(geo::WireID const& wireID, size_t tick, float adc) override
710  {
711  for (std::unique_ptr<OperationBaseClass> const& op : operations)
712  if (!op->Operate(wireID, tick, adc)) return false;
713  return true;
714  }
715 
716  bool Finish() override
717  {
718  bool bAllOk = true;
719  for (std::unique_ptr<OperationBaseClass> const& op : operations)
720  if (!op->Finish()) bAllOk = false;
721  return bAllOk;
722  }
723 
724  std::string Name() const override
725  {
726  std::string msg = cet::demangle_symbol(typeid(*this).name());
727  msg += (" [running " + std::to_string(operations.size()) + " operations:");
728  for (auto const& op : operations) { // it's unique_ptr<OperationBaseClass>
729  if (op)
730  msg += " " + op->Name();
731  else
732  msg += " <invalid>";
733  }
734  return msg + " ]";
735  }
736 
737  OperationBaseClass* Operator(size_t iOp) { return operations.at(iOp).get(); }
738  OperationBaseClass const* Operator(size_t iOp) const { return operations.at(iOp).get(); }
739 
740  void AddOperation(std::unique_ptr<OperationBaseClass> new_op)
741  {
742  if (!new_op) return;
743  if (PlaneID() != new_op->PlaneID()) {
745  << "RawDataDrawer::ManyOperations(): trying to run operations on "
746  << std::string(PlaneID()) << " and " << std::string(new_op->PlaneID())
747  << " at the same time";
748  }
749  if (RawDataDrawerPtr() && (RawDataDrawerPtr() != new_op->RawDataDrawerPtr())) {
751  << "RawDataDrawer::ManyOperations(): "
752  "trying to run operations on different RawDataDrawer"; // possible, but very unlikely
753  }
754  operations.emplace_back(std::move(new_op));
755  }
756 
757  }; // class RawDataDrawer::ManyOperations
758 
759  //......................................................................
761  {
762  geo::PlaneID const& pid = operation->PlaneID();
764 
765  if (digit_cache->empty()) return true;
766 
767  MF_LOG_DEBUG("RawDataDrawer") << "RawDataDrawer::RunOperation() running " << operation->Name();
768 
769  // if we have an initialization failure, return false immediately;
770  // but it's way better if the failure throws an exception
771  if (!operation->Initialize()) return false;
772 
773  lariov::ChannelStatusProvider const& channelStatus =
775 
776  //get pedestal conditions
777  const lariov::DetPedestalProvider& pedestalRetrievalAlg =
778  *(lar::providerFrom<lariov::DetPedestalService>());
779 
780  geo::GeometryCore const& geom = *(lar::providerFrom<geo::Geometry>());
781 
782  // loop over all the channels/raw digits
783  for (evd::details::RawDigitInfo_t const& digit_info : *digit_cache) {
784  raw::RawDigit const& hit = digit_info.Digit();
785  raw::ChannelID_t const channel = hit.Channel();
786 
787  // skip the bad channels
788  if (!channelStatus.IsPresent(channel)) continue;
789  // The following test is meant to be temporary until the "correct" solution is implemented
790  if (!ProcessChannelWithStatus(channelStatus.Status(channel))) continue;
791 
792  // we have a list of all channels, but we are drawing only on one plane;
793  // most of the channels will not contribute to this plane,
794  // and before we start querying databases, unpacking data etc.
795  // we want to know it's for something
796 
797  std::vector<geo::WireID> WireIDs = geom.ChannelToWire(channel);
798 
799  bool bDrawChannel = false;
800  for (geo::WireID const& wireID : WireIDs) {
801  if (wireID.planeID() != pid) continue; // not us!
802  bDrawChannel = true;
803  break;
804  } // for wires
805  if (!bDrawChannel) continue;
806 
807  // collect bad channels
808  bool const bGood = rawopt->fSeeBadChannels || !channelStatus.IsBad(channel);
809 
810  // nothing else to be done if the channel is not good:
811  // cells are marked bad by default and if any good channel falls in any of
812  // them, they become good
813  if (!bGood) continue;
814 
815  // at this point we know we have to process this channel
816  raw::RawDigit::ADCvector_t const& uncompressed = digit_info.Data();
817 
818  // recover the pedestal
819  float pedestal = 0;
820  if (rawopt->fPedestalOption == 0) { pedestal = pedestalRetrievalAlg.PedMean(channel); }
821  else if (rawopt->fPedestalOption == 1) {
822  pedestal = hit.GetPedestal();
823  }
824  else if (rawopt->fPedestalOption == 2) {
825  pedestal = 0;
826  }
827  else {
828  mf::LogWarning("RawDataDrawer")
829  << " PedestalOption is not understood: " << rawopt->fPedestalOption
830  << ". Pedestals not subtracted.";
831  }
832 
833  // loop over all the wires that are covered by this channel;
834  // without knowing better, we have to draw into all of them
835  for (geo::WireID const& wireID : WireIDs) {
836  // check that the plane and tpc are the correct ones to draw
837  if (wireID.planeID() != pid) continue; // not us!
838 
839  // do we have anything to do with this wire?
840  if (!operation->ProcessWire(wireID)) continue;
841 
842  // get an iterator over the adc values
843  // accumulate all the data of this wire in our "cells"
844  size_t const max_tick = std::min({uncompressed.size(), size_t(fStartTick + fTicks)});
845 
846  for (size_t iTick = fStartTick; iTick < max_tick; ++iTick) {
847 
848  // do we have anything to do with this wire?
849  if (!operation->ProcessTick(iTick)) continue;
850 
851  float const adc = uncompressed[iTick] - pedestal;
852  //std::cout << "adc, pedestal: " << adc << " " << pedestal << std::endl;
853 
854  if (!operation->Operate(wireID, iTick, adc)) return false;
855 
856  } // if good
857  } // for wires
858  } // for channels
859 
860  return operation->Finish();
861  } // ChannelLooper()
862 
863  //......................................................................
865  public:
867  geo::PlaneID const& pid,
868  RawDataDrawer* dataDrawer,
869  evdb::View2D* new_view)
870  : OperationBaseClass(pid, dataDrawer)
871  , view(new_view)
872  , rawCharge(0.)
873  , convertedCharge(0.)
874  , drawingRange(*(dataDrawer->fDrawingRange))
875  , ADCCorrector(detProp, PlaneID())
876  {}
877 
878  bool Initialize() override
879  {
881 
882  // set up the size of the grid to be visualized;
883  // the information on the size has to be already there:
884  // caller should have user ExtractRange(), or similar, first.
885  // set the minimum cell in ticks to at least match fTicksPerPoint
886  drawingRange.SetMinTDCCellSize((float)rawopt->fTicksPerPoint);
887  // also set the minimum wire cell size to 1,
888  // otherwise there will be cells represented by no wire.
889  drawingRange.SetMinWireCellSize(1.F);
890  boxInfo.clear();
891  boxInfo.resize(drawingRange.NCells());
892  return true;
893  }
894 
895  bool ProcessWire(geo::WireID const& wire) override
896  {
897  return drawingRange.hasWire((int)wire.Wire);
898  }
899 
900  bool ProcessTick(size_t tick) override { return drawingRange.hasTick((float)tick); }
901 
902  bool Operate(geo::WireID const& wireID, size_t tick, float adc) override
903  {
904  geo::WireID::WireID_t const wire = wireID.Wire;
905  std::ptrdiff_t cell = drawingRange.GetCell(wire, tick);
906  if (cell < 0) return true;
907 
908  BoxInfo_t& info = boxInfo[cell];
909  info.good = true; // if in range, we mark this cell as good
910 
911  rawCharge += adc;
912  convertedCharge += ADCCorrector(adc);
913 
914  // draw maximum digit in the cell
915  if (std::abs(info.adc) <= std::abs(adc)) info.adc = adc;
916 
917  return true;
918  }
919 
920  bool Finish() override
921  {
922  // write the information back
923  geo::PlaneID::PlaneID_t const plane = PlaneID().Plane;
924  RawDataDrawerPtr()->fRawCharge[plane] = rawCharge;
925  RawDataDrawerPtr()->fConvertedCharge[plane] = convertedCharge;
926 
927  // the cell size might have changed because of minimum size settings
928  // from configuration (see Initialize())
929  *(RawDataDrawerPtr()->fDrawingRange) = drawingRange;
930 
931  // complete the drawing
932  RawDataDrawerPtr()->QueueDrawingBoxes(view, PlaneID(), boxInfo);
933 
934  return true;
935  }
936 
937  private:
939 
940  double rawCharge = 0., convertedCharge = 0.;
942  std::vector<BoxInfo_t> boxInfo;
944  }; // class RawDataDrawer::BoxDrawer
945 
947  geo::PlaneID const& pid,
948  std::vector<BoxInfo_t> const& BoxInfo)
949  {
950  //
951  // All the information is now collected in BoxInfo.
952  // Make boxes out of it.
953  //
955 
956  MF_LOG_DEBUG("RawDataDrawer") << "Filling " << BoxInfo.size() << " boxes to be rendered";
957 
958  // drawing options:
959  float const MinSignal = rawopt.fMinSignal;
960  bool const bScaleDigitsByCharge = rawopt.fScaleDigitsByCharge;
961 
963 
965  geo::SigType_t const sigType = geom.SignalType(pid);
966  evdb::ColorScale const& ColorSet = cst->RawQ(sigType);
967  size_t const nBoxes = BoxInfo.size();
968  unsigned int nDrawnBoxes = 0;
969  for (size_t iBox = 0; iBox < nBoxes; ++iBox) {
970  BoxInfo_t const& info = BoxInfo[iBox];
971 
972  // too little signal, don't bother drawing
973  if (info.good && (std::abs(info.adc) < MinSignal)) continue;
974 
975  // skip the bad cells
976  if (!info.good) continue;
977 
978  // box color, proportional to the ADC count
979  int const color = ColorSet.GetColor(info.adc);
980 
981  // scale factor, proportional to ADC count (optional)
982  constexpr float q0 = 1000.;
983  float const sf = bScaleDigitsByCharge ? std::min(std::sqrt((float)info.adc / q0), 1.0F) : 1.;
984 
985  // coordinates of the cell box
986  float min_wire, max_wire, min_tick, max_tick;
987  std::tie(min_wire, min_tick, max_wire, max_tick) = fDrawingRange->GetCellBox(iBox);
988  /*
989  MF_LOG_TRACE("RawDataDrawer")
990  << "Wires ( " << min_wire << " - " << max_wire << " ) ticks ("
991  << min_tick << " - " << max_tick << " ) for cell " << iBox;
992  */
993  if (sf != 1.) { // need to shrink the box
994  float const nsf = 1. - sf; // negation of scale factor
995  float const half_box_wires = (max_wire - min_wire) / 2.,
996  half_box_ticks = (max_tick - min_tick) / 2.;
997 
998  // shrink the box:
999  min_wire += nsf * half_box_wires;
1000  max_wire -= nsf * half_box_wires;
1001  min_tick += nsf * half_box_ticks;
1002  max_tick -= nsf * half_box_ticks;
1003  } // if scaling
1004 
1005  // allocate the box on the view;
1006  // the order of the coordinates depends on the orientation
1007  TBox* pBox;
1008  if (rawopt.fAxisOrientation < 1)
1009  pBox = &(view->AddBox(min_wire, min_tick, max_wire, max_tick));
1010  else
1011  pBox = &(view->AddBox(min_tick, min_wire, max_tick, max_wire));
1012 
1013  pBox->SetFillStyle(1001);
1014  pBox->SetFillColor(color);
1015  pBox->SetBit(kCannotPick);
1016 
1017  ++nDrawnBoxes;
1018  } // for (iBox)
1019 
1020  MF_LOG_DEBUG("RawDataDrawer") << "Sent " << nDrawnBoxes << "/" << BoxInfo.size()
1021  << " boxes to be rendered";
1022  } // RawDataDrawer::QueueDrawingBoxes()
1023 
1025  detinfo::DetectorPropertiesData const& detProp,
1026  evdb::View2D* view,
1027  unsigned int plane)
1028  {
1029 
1030  // Check if we're supposed to draw raw hits at all
1032  if (rawopt->fDrawRawDataOrCalibWires == 1) return;
1033 
1034  geo::PlaneID const pid(rawopt->CurrentTPC(), plane);
1035  BoxDrawer drawer(detProp, pid, this, view);
1036  if (!RunOperation(evt, &drawer)) {
1037  throw art::Exception(art::errors::Unknown) << "RawDataDrawer::RunDrawOperation(): "
1038  "somewhere something went somehow wrong";
1039  }
1040 
1041  } // RawDataDrawer::RunDrawOperation()
1042 
1043  //......................................................................
1045  public:
1046  float const RoIthreshold;
1047 
1049  : OperationBaseClass(pid, data_drawer)
1050  , RoIthreshold(art::ServiceHandle<evd::RawDrawingOptions const>()->RoIthreshold(PlaneID()))
1051  {}
1052 
1053  bool Operate(geo::WireID const& wireID, size_t tick, float adc) override
1054  {
1055  if (std::abs(adc) < RoIthreshold) return true;
1056  WireRange.add(wireID.Wire);
1057  TDCrange.add(tick);
1058  return true;
1059  } // Operate()
1060 
1061  bool Finish() override
1062  {
1063  geo::PlaneID::PlaneID_t const plane = PlaneID().Plane;
1064  int& WireMin = pRawDataDrawer->fWireMin[plane];
1065  int& WireMax = pRawDataDrawer->fWireMax[plane];
1066  int& TimeMin = pRawDataDrawer->fTimeMin[plane];
1067  int& TimeMax = pRawDataDrawer->fTimeMax[plane];
1068 
1069  if ((WireMin == WireMax) && WireRange.has_data()) {
1071  mf::LogInfo("RawDataDrawer")
1072  << "Region of interest for " << std::string(PlaneID()) << " detected to be within wires "
1073  << WireRange.min() << " to " << WireRange.max() << " (plane has "
1074  << geom.Nwires(PlaneID()) << " wires)";
1075  WireMax = WireRange.max() + 1;
1076  WireMin = WireRange.min();
1077  }
1078  if ((TimeMin == TimeMax) && TDCrange.has_data()) {
1079  mf::LogInfo("RawDataDrawer")
1080  << "Region of interest for " << std::string(PlaneID()) << " detected to be within ticks "
1081  << TDCrange.min() << " to " << TDCrange.max();
1082  TimeMax = TDCrange.max() + 1;
1083  TimeMin = TDCrange.min();
1084  }
1085  return true;
1086  } // Finish()
1087 
1088  private:
1090  }; // class RawDataDrawer::RoIextractorClass
1091 
1092  void RawDataDrawer::RunRoIextractor(art::Event const& evt, unsigned int plane)
1093  {
1095  geo::PlaneID const pid(rawopt->CurrentTPC(), plane);
1096 
1097  // if we have no region of interest, prepare to extract it
1098  bool const bExtractRoI = !hasRegionOfInterest(plane);
1099  MF_LOG_TRACE("RawDataDrawer") << "Region of interest for " << pid
1100  << (bExtractRoI ? " extracted" : " not extracted")
1101  << " on this draw";
1102 
1103  if (!bExtractRoI) return;
1104 
1105  RoIextractorClass Extractor(pid, this);
1106  if (!RunOperation(evt, &Extractor)) {
1107  throw std::runtime_error(
1108  "RawDataDrawer::RunRoIextractor(): somewhere something went somehow wrong");
1109  }
1110 
1111  } // RawDataDrawer::RunRoIextractor()
1112 
1113  //......................................................................
1114 
1116  detinfo::DetectorPropertiesData const& detProp,
1117  evdb::View2D* view,
1118  unsigned int plane,
1119  bool bZoomToRoI /* = false */
1120  )
1121  {
1123  geo::PlaneID const pid(rawopt->CurrentTPC(), plane);
1124 
1125  bool const bDraw = (rawopt->fDrawRawDataOrCalibWires != 1);
1126  // if we don't need to draw, don't bother doing anything;
1127  // if the region of interest is required, RunRoIextractor() should be called
1128  // (ok, now it's private, but it could be exposed)
1129  if (!bDraw) return;
1130 
1132 
1133  // Need to loop over the labels, but we don't want to zap existing cached RawDigits that are valid
1134  // So... do the painful search to make sure the RawDigits we recover at those we are searching for.
1135  bool theDroidIAmLookingFor = false;
1136 
1137  // Loop over labels
1138  for (const auto& rawDataLabel : rawopt->fRawDataLabels) {
1139  // make sure we reset what needs to be reset
1140  // before the operations are initialized;
1141  // we call for reading raw digits; they will be cached, so it's not a waste
1142  details::CacheID_t NewCacheID(evt, rawDataLabel, pid);
1143  GetRawDigits(evt, NewCacheID);
1144 
1145  // Painful check to see if these RawDigits contain the droids we are looking for
1146  for (const auto& rawDigit : digit_cache->Digits()) {
1147  std::vector<geo::WireID> WireIDs = geom->ChannelToWire(rawDigit.Channel());
1148 
1149  for (geo::WireID const& wireID : WireIDs) {
1150  if (wireID.planeID() != pid) continue; // not us!
1151  theDroidIAmLookingFor = true;
1152  break;
1153  } // for wires
1154 
1155  if (theDroidIAmLookingFor) break;
1156  }
1157 
1158  if (theDroidIAmLookingFor) break;
1159  }
1160 
1161  if (!theDroidIAmLookingFor) return;
1162 
1163  bool const hasRoI = hasRegionOfInterest(plane);
1164 
1165  // - if we don't have a RoI yet, we want to get it while we draw
1166  // * if we are zooming into it now, we have to extract it first, then draw
1167  // * if we are not zooming, we can do both at the same time
1168  // - if we have a RoI, we don't want to extract it again
1169  if (!bZoomToRoI) { // we are not required to zoom to the RoI
1170 
1171  std::unique_ptr<OperationBaseClass> operation;
1172 
1173  // we will do the drawing in one pass
1174  MF_LOG_DEBUG("RawDataDrawer") << __func__ << "() setting up one-pass drawing";
1175  operation.reset(new BoxDrawer(detProp, pid, this, view));
1176 
1177  if (!hasRoI) { // we don't have any RoI; since it's cheap, let's get it
1178  MF_LOG_DEBUG("RawDataDrawer") << __func__ << "() adding RoI extraction";
1179 
1180  // swap cards: operation becomes a multiple operation:
1181  // - prepare the two operations (one is there already, somehow)
1182  std::unique_ptr<OperationBaseClass> drawer(std::move(operation));
1183  std::unique_ptr<OperationBaseClass> extractor(new RoIextractorClass(pid, this));
1184  // - create a new composite operation and give it the sub-ops
1185  operation.reset(new ManyOperations(pid, this));
1186  ManyOperations* pManyOps = static_cast<ManyOperations*>(operation.get());
1187  pManyOps->AddOperation(std::move(drawer));
1188  pManyOps->AddOperation(std::move(extractor));
1189  }
1190 
1191  if (!RunOperation(evt, operation.get())) {
1192  throw art::Exception(art::errors::Unknown) << "RawDataDrawer::RunDrawOperation(): "
1193  "somewhere something went somehow wrong";
1194  }
1195  }
1196  else { // we are zooming to RoI
1197  // first, we want the RoI extracted; the extractor will update this object
1198  if (!hasRoI) {
1199  MF_LOG_DEBUG("RawDataDrawer") << __func__ << "() setting up RoI extraction for " << pid;
1200  RoIextractorClass extractor(pid, this);
1201  if (!RunOperation(evt, &extractor)) {
1203  << "RawDataDrawer::RunDrawOperation():"
1204  " something went somehow wrong while extracting RoI";
1205  }
1206  }
1207  else {
1208  MF_LOG_DEBUG("RawDataDrawer")
1209  << __func__ << "() using existing RoI for " << pid << ": wires ( " << fWireMin[plane]
1210  << " - " << fWireMax[plane] << " ), ticks ( " << fTimeMin[plane] << " - "
1211  << fTimeMax[plane] << " )";
1212  }
1213 
1214  // adopt the drawing limits information from the wire/time limits
1216 
1217  // then we draw
1218  MF_LOG_DEBUG("RawDataDrawer") << __func__ << "() setting up drawing";
1219  BoxDrawer drawer(detProp, pid, this, view);
1220  if (!RunOperation(evt, &drawer)) {
1221  throw art::Exception(art::errors::Unknown) << "RawDataDrawer::RunDrawOperation():"
1222  " something went somehow wrong while drawing";
1223  }
1224  }
1225  } // RawDataDrawer::RawDigit2D()
1226 
1227  //........................................................................
1228  int RawDataDrawer::GetRegionOfInterest(int plane, int& minw, int& maxw, int& mint, int& maxt)
1229  {
1231 
1232  if ((unsigned int)plane >= fWireMin.size()) {
1233  mf::LogWarning("RawDataDrawer")
1234  << " Requested plane " << plane << " is larger than those available " << std::endl;
1235  return -1;
1236  }
1237 
1238  minw = fWireMin[plane];
1239  maxw = fWireMax[plane];
1240  mint = fTimeMin[plane];
1241  maxt = fTimeMax[plane];
1242 
1243  if ((minw == maxw) || (mint == maxt)) return 1;
1244 
1245  //make values a bit larger, but make sure they don't go out of bounds
1246  minw = (minw - 30 < 0) ? 0 : minw - 30;
1247  mint = (mint - 10 < 0) ? 0 : mint - 10;
1248 
1249  geo::PlaneID const planeid(0, 0, plane);
1250  maxw = (maxw + 10 > (int)geo->Nwires(planeid)) ? geo->Nwires(planeid) : maxw + 10;
1251  maxt = (maxt + 10 > TotalClockTicks()) ? TotalClockTicks() : maxt + 10;
1252 
1253  return 0;
1254  }
1255 
1256  //......................................................................
1257  void RawDataDrawer::GetChargeSum(int plane, double& charge, double& convcharge)
1258  {
1259  charge = fRawCharge[plane];
1260  convcharge = fConvertedCharge[plane];
1261  }
1262 
1263  //......................................................................
1264  void RawDataDrawer::FillQHisto(const art::Event& evt, unsigned int plane, TH1F* histo)
1265  {
1266 
1267  // Check if we're supposed to draw raw hits at all
1269  if (rawopt->fDrawRawDataOrCalibWires == 1) return;
1270 
1272 
1273  geo::PlaneID const pid(rawopt->CurrentTPC(), plane);
1274 
1275  for (const auto& rawDataLabel : rawopt->fRawDataLabels) {
1276  details::CacheID_t NewCacheID(evt, rawDataLabel, pid);
1277  GetRawDigits(evt, NewCacheID);
1278 
1279  lariov::ChannelStatusProvider const& channelStatus =
1281 
1282  //get pedestal conditions
1283  const lariov::DetPedestalProvider& pedestalRetrievalAlg =
1285 
1286  for (evd::details::RawDigitInfo_t const& digit_info : *digit_cache) {
1287  raw::RawDigit const& hit = digit_info.Digit();
1288  raw::ChannelID_t const channel = hit.Channel();
1289 
1290  if (!channelStatus.IsPresent(channel)) continue;
1291 
1292  // The following test is meant to be temporary until the "correct" solution is implemented
1293  if (!ProcessChannelWithStatus(channelStatus.Status(channel))) continue;
1294 
1295  // to be explicit: we don't cound bad channels in
1296  if (!rawopt->fSeeBadChannels && channelStatus.IsBad(channel)) continue;
1297 
1298  std::vector<geo::WireID> wireids = geo->ChannelToWire(channel);
1299  for (auto const& wid : wireids) {
1300  // check that the plane and tpc are the correct ones to draw
1301  if (wid.planeID() != pid) continue;
1302 
1303  raw::RawDigit::ADCvector_t const& uncompressed = digit_info.Data();
1304 
1305  //float const pedestal = pedestalRetrievalAlg.PedMean(channel);
1306  // recover the pedestal
1307  float pedestal = 0;
1308  if (rawopt->fPedestalOption == 0) { pedestal = pedestalRetrievalAlg.PedMean(channel); }
1309  else if (rawopt->fPedestalOption == 1) {
1310  pedestal = hit.GetPedestal();
1311  }
1312  else if (rawopt->fPedestalOption == 2) {
1313  pedestal = 0;
1314  }
1315  else {
1316  mf::LogWarning("RawDataDrawer")
1317  << " PedestalOption is not understood: " << rawopt->fPedestalOption
1318  << ". Pedestals not subtracted.";
1319  }
1320 
1321  for (short d : uncompressed)
1322  histo->Fill(float(d) - pedestal); //pedestals[plane]); //hit.GetPedestal());
1323 
1324  // this channel is on the correct plane, don't double count the raw signal
1325  // if there are more than one wids for the channel
1326  break;
1327  } // end loop over wids
1328  } //end loop over raw hits
1329  } //end loop over labels
1330  }
1331 
1332  //......................................................................
1334  unsigned int plane,
1335  unsigned int wire,
1336  TH1F* histo)
1337  {
1338 
1339  // Check if we're supposed to draw raw hits at all
1341  if (rawopt->fDrawRawDataOrCalibWires == 1) return;
1342 
1343  // make sure we have the raw digits cached
1344  geo::PlaneID const pid(rawopt->CurrentTPC(), plane);
1345 
1346  // loop over labels
1347  for (const auto& rawDataLabel : rawopt->fRawDataLabels) {
1348  details::CacheID_t NewCacheID(evt, rawDataLabel, pid);
1349  GetRawDigits(evt, NewCacheID);
1350 
1351  if (digit_cache->empty()) return;
1352 
1353  geo::WireID const wireid(pid, wire);
1354 
1355  // find the channel
1357  raw::ChannelID_t const channel = geom->PlaneWireToChannel(wireid);
1358  if (!raw::isValidChannelID(channel)) { // no channel, empty histogram
1359  mf::LogError("RawDataDrawer")
1360  << __func__ << ": no channel associated to " << std::string(wireid);
1361  return;
1362  } // if no channel
1363 
1364  // check the channel status; bad channels are still ok.
1365  lariov::ChannelStatusProvider const& channelStatus =
1367 
1368  if (!channelStatus.IsPresent(channel)) return;
1369 
1370  // The following test is meant to be temporary until the "correct" solution is implemented
1371  if (!ProcessChannelWithStatus(channelStatus.Status(channel))) return;
1372 
1373  // we accept to see the content of a bad channel, so this is commented out:
1374  if (!rawopt->fSeeBadChannels && channelStatus.IsBad(channel)) return;
1375 
1376  //get pedestal conditions
1377  const lariov::DetPedestalProvider& pedestalRetrievalAlg =
1379 
1380  // find the raw digit
1381  // (iDigit is an iterator to a evd::details::RawDigitInfo_t)
1382  evd::details::RawDigitInfo_t const* pDigit = digit_cache->FindChannel(channel);
1383 
1384  if (
1385  !pDigit) { // this is weird... actually no, this can happen if the RawDigits are per TPC (or something)
1386  // mf::LogWarning("RawDataDrawer") << __func__
1387  // << ": can't find raw digit for channel #" << channel
1388  // << " (" << std::string(wireid) << ")";
1389  continue;
1390  }
1391 
1392  raw::RawDigit::ADCvector_t const& uncompressed = pDigit->Data();
1393 
1394  // recover the pedestal
1395  float pedestal = 0;
1396  if (rawopt->fPedestalOption == 0) { pedestal = pedestalRetrievalAlg.PedMean(channel); }
1397  else if (rawopt->fPedestalOption == 1) {
1398  pedestal = pDigit->DigitPtr()->GetPedestal();
1399  }
1400  else if (rawopt->fPedestalOption == 2) {
1401  pedestal = 0;
1402  }
1403  else {
1404  mf::LogWarning("RawDataDrawer")
1405  << " PedestalOption is not understood: " << rawopt->fPedestalOption
1406  << ". Pedestals not subtracted.";
1407  }
1408 
1409  for (size_t j = 0; j < uncompressed.size(); ++j)
1410  histo->Fill(float(j),
1411  float(uncompressed[j]) - pedestal); //pedestals[plane]); //hit.GetPedestal());
1412  }
1413 
1414  } // RawDataDrawer::FillTQHisto()
1415 
1416  //......................................................................
1417 
1418  // void RawDataDrawer::RawDigit3D(const art::Event& evt,
1419  // evdb::View3D* view)
1420  // {
1421  // // Check if we're supposed to draw raw hits at all
1422  // art::ServiceHandle<evd::RawDrawingOptions const> rawopt;
1423  // if (rawopt->fDrawRawOrCalibHits!=0) return;
1424 
1425  // art::ServiceHandle<geo::Geometry const> geom;
1426 
1427  // HitTower tower;
1428  // tower.fQscale = 0.01;
1429 
1430  // for (unsigned int imod=0; imod<rawopt->fRawDigitModules.size(); ++imod) {
1431  // const char* which = rawopt->fRawDigitModules[imod].c_str();
1432 
1433  // std::vector<raw::RawDigit> rawhits;
1434  // GetRawDigits(evt, which, rawhits);
1435 
1436  // for (unsigned int i=0; i<rawhits.size(); ++i) {
1437  // double t = 0;
1438  // double q = 0;
1439  // t = rawhits[i]->fTDC[0];
1440  // for (unsigned int j=0; j<rawhits[i]->NADC(); ++j) {
1441  // q += rawhits[i]->ADC(j);
1442  // }
1443  // // Hack for now...
1444  // if (q<=0.0) q = 1+i%10;
1445 
1446  // // Get the cell geometry for the hit
1447  // int iplane = cmap->GetPlane(rawhits[i].get());
1448  // int icell = cmap->GetCell(rawhits[i].get());
1449  // double xyz[3];
1450  // double dpos[3];
1451  // geo::View_t v;
1452  // geom->CellInfo(iplane, icell, &v, xyz, dpos);
1453 
1454  // switch (rawopt->fRawDigit3DStyle) {
1455  // case 1:
1456  // //
1457  // // Render digits as towers
1458  // //
1459  // if (v==geo::kX) {
1460  // tower.AddHit(v, iplane, icell, xyz[0], xyz[2], q, t);
1461  // }
1462  // else if (v==geo::kY) {
1463  // tower.AddHit(v, iplane, icell, xyz[1], xyz[2], q, t);
1464  // }
1465  // else abort();
1466  // break;
1467  // default:
1468  // //
1469  // // Render Digits as boxes
1470  // //
1471  // TPolyLine3D& p = view->AddPolyLine3D(5,kGreen+1,1,2);
1472  // double sf = std::sqrt(0.01*q);
1473  // if (v==geo::kX) {
1474  // double x1 = xyz[0] - sf*dpos[0];
1475  // double x2 = xyz[0] + sf*dpos[0];
1476  // double z1 = xyz[2] - sf*dpos[2];
1477  // double z2 = xyz[2] + sf*dpos[2];
1478  // p.SetPoint(0, x1, geom->DetHalfHeight(), z1);
1479  // p.SetPoint(1, x2, geom->DetHalfHeight(), z1);
1480  // p.SetPoint(2, x2, geom->DetHalfHeight(), z2);
1481  // p.SetPoint(3, x1, geom->DetHalfHeight(), z2);
1482  // p.SetPoint(4, x1, geom->DetHalfHeight(), z1);
1483  // }
1484  // else if (v==geo::kY) {
1485  // double y1 = xyz[1] - sf*dpos[1];
1486  // double y2 = xyz[1] + sf*dpos[1];
1487  // double z1 = xyz[2] - sf*dpos[2];
1488  // double z2 = xyz[2] + sf*dpos[2];
1489  // p.SetPoint(0, geom->DetHalfWidth(), y1, z1);
1490  // p.SetPoint(1, geom->DetHalfWidth(), y2, z1);
1491  // p.SetPoint(2, geom->DetHalfWidth(), y2, z2);
1492  // p.SetPoint(3, geom->DetHalfWidth(), y1, z2);
1493  // p.SetPoint(4, geom->DetHalfWidth(), y1, z1);
1494  // }
1495  // else abort();
1496  // break;
1497  // } // switch fRawDigit3DStyle
1498  // }//end loop over raw digits
1499  // }// end loop over RawDigit modules
1500 
1501  // // Render the towers for that style choice
1502  // if (rawopt->fRawDigit3DStyle==1) tower.Draw(view);
1503  // }
1504 
1505  //......................................................................
1507  {
1508 
1509  return (fWireMax[plane] != -1) && (fTimeMax[plane] != -1);
1510 
1511  } // RawDataDrawer::hasRegionOfInterest()
1512 
1513  //......................................................................
1515  {
1516 
1517  MF_LOG_DEBUG("RawDataDrawer") << "RawDataDrawer[" << ((void*)this)
1518  << "]: resetting the region of interest";
1519 
1520  std::fill(fWireMin.begin(), fWireMin.end(), -1);
1521  std::fill(fWireMax.begin(), fWireMax.end(), -1);
1522  std::fill(fTimeMin.begin(), fTimeMin.end(), -1);
1523  std::fill(fTimeMax.begin(), fTimeMax.end(), -1);
1524 
1525  } // RawDataDrawer::ResetRegionOfInterest()
1526 
1527  //......................................................................
1528 
1530  {
1531  MF_LOG_DEBUG("RawDataDrawer") << "GetRawDigits() for " << new_timestamp
1532  << " (last for: " << *fCacheID << ")";
1533 
1534  // update cache
1535  digit_cache->Update(evt, new_timestamp);
1536 
1537  // if time stamp is changing, we want to reconsider which region is
1538  // interesting
1539  if (!fCacheID->sameTPC(new_timestamp)) ResetRegionOfInterest();
1540 
1541  // all the caches have been properly updated or invalidated;
1542  // we are now on a new cache state
1543  *fCacheID = new_timestamp;
1544 
1545  } // RawDataDrawer::GetRawDigits()
1546 
1547  //......................................................................
1549  lariov::ChannelStatusProvider::Status_t channel_status) const
1550  {
1551  // if we don't have a valid status, we can't reject the channel
1552  if (!lariov::ChannelStatusProvider::IsValidStatus(channel_status)) return true;
1553 
1554  // is the status "too bad"?
1556  if (channel_status > drawopt->fMaxChannelStatus) return false;
1557  if (channel_status < drawopt->fMinChannelStatus) return false;
1558 
1559  // no reason to reject it...
1560  return true;
1561  } // RawDataDrawer::ProcessChannel()
1562 
1563  //----------------------------------------------------------------------------
1564  namespace details {
1565 
1566  //--------------------------------------------------------------------------
1567  //--- RawDigitInfo_t
1568  //---
1569  raw::RawDigit::ADCvector_t const& RawDigitInfo_t::Data() const
1570  {
1571  if (!data.hasData()) UncompressData();
1572  return *data;
1573  } // RawDigitInfo_t::Data()
1574 
1576  {
1577  data.Clear();
1578  digit = src;
1579  } // RawDigitInfo_t::Fill()
1580 
1581  void RawDigitInfo_t::Clear()
1582  {
1583  data.Clear();
1584  sample_info.reset();
1585  }
1586 
1587  void RawDigitInfo_t::UncompressData() const
1588  {
1589  data.Clear();
1590 
1591  if (!digit) return; // no original data, can't do anything
1592 
1594 
1595  if (digit->Compression() == kNone) {
1596  // no compression, we can refer to the original data directly
1597  data.PointToData(digit->ADCs());
1598  }
1599  else {
1600  // data is compressed, need to do the real work
1601  if (drawopt->fUncompressWithPed) { //Use pedestal in uncompression
1602  int pedestal = (int)digit->GetPedestal();
1604  samples.resize(digit->Samples());
1605  Uncompress(digit->ADCs(), samples, pedestal, digit->Compression());
1606  data.StealData(std::move(samples));
1607  }
1608  else {
1610  samples.resize(digit->Samples());
1611  Uncompress(digit->ADCs(), samples, digit->Compression());
1612  data.StealData(std::move(samples));
1613  }
1614  }
1615  } // RawDigitInfo_t::UncompressData()
1616 
1617  void RawDigitInfo_t::CollectSampleInfo() const
1618  {
1619  raw::RawDigit::ADCvector_t const& samples = Data();
1620 
1621  // lar::util::StatCollector<double> stat;
1622  // stat.add(samples.begin(), samples.end());
1623 
1625  samples.end());
1626 
1627  sample_info.reset(new SampleInfo_t);
1628  sample_info->min_charge = stat.min();
1629  sample_info->max_charge = stat.max();
1630  // sample_info->average_charge = stat.Average();
1631 
1632  } // RawDigitInfo_t::CollectSampleInfo()
1633 
1634  RawDigitInfo_t::SampleInfo_t const& RawDigitInfo_t::SampleInfo() const
1635  {
1636  if (!sample_info) CollectSampleInfo();
1637  return *sample_info;
1638  } // SampleInfo()
1639 
1640  template <typename Stream>
1641  void RawDigitInfo_t::Dump(Stream&& out) const
1642  {
1643  out << " digit at " << ((void*)digit.get()) << " on channel #" << digit->Channel()
1644  << " with " << digit->NADC();
1645  if (digit->Compression() == kNone)
1646  out << " uncompressed data";
1647  else
1648  out << " data items compressed with <" << digit->Compression() << ">";
1649  if (data.hasData())
1650  out << " with data (" << data->size() << " samples)";
1651  else
1652  out << " without data";
1653  } // RawDigitInfo_t::Dump()
1654 
1655  //--------------------------------------------------------------------------
1656  //--- RawDigitCacheDataClass
1657  //---
1658 
1659  RawDigitInfo_t const* RawDigitCacheDataClass::FindChannel(raw::ChannelID_t channel) const
1660  {
1661  auto iDigit = std::find_if(
1662  digits.cbegin(), digits.cend(), [channel](evd::details::RawDigitInfo_t const& digit) {
1663  return digit.Channel() == channel;
1664  });
1665  return (iDigit == digits.cend()) ? nullptr : &*iDigit;
1666  } // RawDigitCacheDataClass::FindChannel()
1667 
1668  std::vector<raw::RawDigit> const* RawDigitCacheDataClass::ReadProduct(art::Event const& evt,
1669  art::InputTag label)
1670  {
1672  if (!evt.getByLabel(label, rdcol)) return nullptr;
1673  return &*rdcol;
1674  } // RawDigitCacheDataClass::ReadProduct()
1675 
1676  void RawDigitCacheDataClass::Refill(art::Handle<std::vector<raw::RawDigit>>& rdcol)
1677  {
1678  digits.resize(rdcol->size());
1679  for (size_t iDigit = 0; iDigit < rdcol->size(); ++iDigit) {
1680  art::Ptr<raw::RawDigit> pDigit(rdcol, iDigit);
1681  digits[iDigit].Fill(pDigit);
1682  size_t samples = pDigit->Samples();
1683  if (samples > max_samples) max_samples = samples;
1684  } // for
1685  } // RawDigitCacheDataClass::Refill()
1686 
1687  void RawDigitCacheDataClass::Invalidate()
1688  {
1689  timestamp.clear();
1690  } // RawDigitCacheDataClass::Invalidate()
1691 
1692  void RawDigitCacheDataClass::Clear()
1693  {
1694  Invalidate();
1695  digits.clear();
1696  max_samples = 0;
1697  } // RawDigitCacheDataClass::Clear()
1698 
1699  RawDigitCacheDataClass::BoolWithUpToDateMetadata RawDigitCacheDataClass::CheckUpToDate(
1700  CacheID_t const& ts,
1701  art::Event const* evt /* = nullptr */) const
1702  {
1703  BoolWithUpToDateMetadata res{false, nullptr};
1704 
1705  // normally only if either the event or the product label have changed,
1706  // cache becomes invalid:
1707  if (!ts.sameProduct(timestamp)) return res; // outdated cache
1708 
1709  // But: our cache stores pointers to the original data, and on a new TPC
1710  // the event display may reload the event anew, removing the "old" data
1711  // from memory.
1712  // Since TPC can change with or without the data being invalidated,
1713  // a more accurate verification is needed.
1714 
1715  // if the cache is empty, well, it does not make much difference;
1716  // we invalidate it to be sure
1717  if (empty()) return res; // outdated cache
1718 
1719  if (!evt) return res; // outdated, since we can't know better without the event
1720 
1721  // here we force reading of the product
1722  res.digits = ReadProduct(*evt, ts.inputLabel());
1723  if (!res.digits) return res; // outdated cache; this is actually an error
1724 
1725  if (res.digits->empty())
1726  return res; // outdated; no digits (strange!), invalidate just in case
1727 
1728  // use the first digit as test
1729  raw::ChannelID_t channel = res.digits->front().Channel();
1730  RawDigitInfo_t const* pInfo = FindChannel(channel);
1731  if (!pInfo) return res; // outdated: we don't even have this channel in cache!
1732 
1733  if (&(pInfo->Digit()) != &(res.digits->front()))
1734  return res; // outdated: different memory address for data
1735 
1736  res.bUpToDate = true;
1737  return res; // cache still valid
1738  } // RawDigitCacheDataClass::CheckUpToDate()
1739 
1740  bool RawDigitCacheDataClass::Update(art::Event const& evt, CacheID_t const& new_timestamp)
1741  {
1742  BoolWithUpToDateMetadata update_info = CheckUpToDate(new_timestamp, &evt);
1743 
1744  if (update_info) return false; // already up to date: move on!
1745 
1746  MF_LOG_DEBUG("RawDataDrawer") << "Refilling raw digit cache RawDigitCacheDataClass["
1747  << ((void*)this) << "] for " << new_timestamp;
1748 
1749  Clear();
1750 
1752  if (!evt.getByLabel(new_timestamp.inputLabel(), rdcol)) {
1753  mf::LogWarning("RawDataDrawer")
1754  << "no RawDigit collection '" << new_timestamp.inputLabel() << "' found";
1755  return true;
1756  }
1757 
1758  Refill(rdcol);
1759 
1760  timestamp = new_timestamp;
1761  return true;
1762  } // RawDigitCacheDataClass::Update()
1763 
1764  template <typename Stream>
1765  void RawDigitCacheDataClass::Dump(Stream&& out) const
1766  {
1767  out << "Cache at " << ((void*)this) << " with time stamp " << std::string(timestamp)
1768  << " and " << digits.size() << " entries (maximum sample: " << max_samples << ");"
1769  << " data at " << ((void*)digits.data());
1770  for (RawDigitInfo_t const& digitInfo : digits) {
1771  out << "\n ";
1772  digitInfo.Dump(out);
1773  } // for
1774  out << "\n";
1775  } // RawDigitCacheDataClass::Dump()
1776 
1777  //--------------------------------------------------------------------------
1778  //--- GridAxisClass
1779  //---
1780  std::ptrdiff_t GridAxisClass::GetCell(float coord) const
1781  {
1782  return std::ptrdiff_t((coord - min) / cell_size); // truncate
1783  } // GridAxisClass::GetCell()
1784 
1785  //--------------------------------------------------------------------------
1786  bool GridAxisClass::Init(size_t nDiv, float new_min, float new_max)
1787  {
1788 
1789  n_cells = std::max(nDiv, size_t(1));
1790  return SetLimits(new_min, new_max);
1791 
1792  } // GridAxisClass::Init()
1793 
1794  //--------------------------------------------------------------------------
1795  bool GridAxisClass::SetLimits(float new_min, float new_max)
1796  {
1797  min = new_min;
1798  max = new_max;
1799  cell_size = Length() / float(n_cells);
1800 
1801  return std::isnormal(cell_size);
1802  } // GridAxisClass::SetLimits()
1803 
1804  //--------------------------------------------------------------------------
1805  bool GridAxisClass::SetMinCellSize(float min_size)
1806  {
1807  if (cell_size >= min_size) return false;
1808 
1809  // n_cells gets truncated
1810  n_cells = (size_t)std::max(std::floor(Length() / min_size), 1.0F);
1811 
1812  // reevaluate cell size, that might be different than min_size
1813  // because of n_cells truncation or minimum value
1814  cell_size = Length() / float(n_cells);
1815  return true;
1816  } // GridAxisClass::SetMinCellSize()
1817 
1818  //--------------------------------------------------------------------------
1819  bool GridAxisClass::SetMaxCellSize(float max_size)
1820  {
1821  if (cell_size <= max_size) return false;
1822 
1823  // n_cells gets rounded up
1824  n_cells = (size_t)std::max(std::ceil(Length() / max_size), 1.0F);
1825 
1826  // reevaluate cell size, that might be different than max_size
1827  // because of n_cells rounding or minimum value
1828  cell_size = Length() / float(n_cells);
1829  return true;
1830  } // GridAxisClass::SetMaxCellSize()
1831 
1832  //--------------------------------------------------------------------------
1833  template <typename Stream>
1834  void GridAxisClass::Dump(Stream&& out) const
1835  {
1836  out << NCells() << " cells from " << Min() << " to " << Max() << " (length: " << Length()
1837  << ")";
1838  } // GridAxisClass::Dump()
1839 
1840  //--------------------------------------------------------------------------
1841  //--- CellGridClass
1842  //---
1843  CellGridClass::CellGridClass(unsigned int nWires, unsigned int nTDC)
1844  : wire_axis((size_t)nWires, 0., float(nWires)), tdc_axis((size_t)nTDC, 0., float(nTDC))
1845  {} // CellGridClass::CellGridClass(int, int)
1846 
1847  //--------------------------------------------------------------------------
1849  float max_wire,
1850  unsigned int nWires,
1851  float min_tdc,
1852  float max_tdc,
1853  unsigned int nTDC)
1854  : wire_axis((size_t)nWires, min_wire, max_wire), tdc_axis((size_t)nTDC, min_tdc, max_tdc)
1855  {} // CellGridClass::CellGridClass({ float, float, int } x 2)
1856 
1857  //--------------------------------------------------------------------------
1858  std::ptrdiff_t CellGridClass::GetCell(float wire, float tick) const
1859  {
1860  std::ptrdiff_t iWireCell = wire_axis.GetCell(wire);
1861  if (!wire_axis.hasCell(iWireCell)) return std::ptrdiff_t(-1);
1862  std::ptrdiff_t iTDCCell = tdc_axis.GetCell(tick);
1863  if (!tdc_axis.hasCell(iTDCCell)) return std::ptrdiff_t(-1);
1864  return iWireCell * TDCAxis().NCells() + iTDCCell;
1865  } // CellGridClass::GetCell()
1866 
1867  //--------------------------------------------------------------------------
1868  std::tuple<float, float, float, float> CellGridClass::GetCellBox(std::ptrdiff_t iCell) const
1869  {
1870  // { w1, t1, w2, t2 }
1871  size_t const nTDCCells = TDCAxis().NCells();
1872  std::ptrdiff_t iWireCell = (std::ptrdiff_t)(iCell / nTDCCells),
1873  iTDCCell = (std::ptrdiff_t)(iCell % nTDCCells);
1874 
1875  return std::tuple<float, float, float, float>(WireAxis().LowerEdge(iWireCell),
1876  TDCAxis().LowerEdge(iTDCCell),
1877  WireAxis().UpperEdge(iWireCell),
1878  TDCAxis().UpperEdge(iTDCCell));
1879  } // CellGridClass::GetCellBox()
1880 
1881  //--------------------------------------------------------------------------
1882  template <typename Stream>
1883  void CellGridClass::Dump(Stream&& out) const
1884  {
1885  out << "Wire axis: ";
1886  WireAxis().Dump(out);
1887  out << "; time axis: ";
1888  TDCAxis().Dump(out);
1889  } // CellGridClass::Dump()
1890 
1891  //--------------------------------------------------------------------------
1892 
1893  } // details
1894 
1895 } // namespace evd
1896 
int GetRegionOfInterest(int plane, int &minw, int &maxw, int &mint, int &maxt)
float GetPedestal() const
Definition: RawDigit.h:221
Data_t max() const
Returns the accumulated maximum, or a very small number if no values.
const_pointer operator->() const
bool Operate(geo::WireID const &wireID, size_t tick, float adc) override
details::CellGridClass drawingRange
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3269
short MaxCharge() const
maximum charge
bool has_data() const
Returns whether at least one datum has been added.
~PointerToData_t()
Destructor: gets rid of the owned data.
int fScaleDigitsByCharge
scale the size of the digit by the charge
bool Update(art::Event const &evt, CacheID_t const &new_timestamp)
BoxDrawer(detinfo::DetectorPropertiesData const &detProp, geo::PlaneID const &pid, RawDataDrawer *dataDrawer, evdb::View2D *new_view)
bool sameProduct(PlaneDataChangeTracker_t const &as) const
Returns whether we are in the same event (the rest could differ)
BoolWithUpToDateMetadata(bool uptodate, std::vector< raw::RawDigit > const *newdigits)
bool SetCellSizeBoundary(float min_size, float max_size)
ULong64_t Samples() const
Number of samples in the uncompressed ADC data.
Definition: RawDigit.h:217
bool ProcessTick(size_t tick) override
unsigned int fTPC
TPC number to draw, typically set by TWQProjectionView.
Collection of charge vs time digitized from a single readout channel.
Definition: RawDigit.h:68
void SetWireRange(float min_wire, float max_wire)
Sets the wire range, leaving the number of wire cells unchanged.
void FillTQHisto(const art::Event &evt, unsigned int plane, unsigned int wire, TH1F *histo)
int adc
total ADC count in this box
raw::RawDigit const & Digit() const
Returns an art pointer to the actual digit.
std::vector< WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
void SetTDCRange(float min_tdc, float max_tdc, unsigned int nTDC, float min_size)
Sets the complete TDC range, with minimum cell size.
void SetWireRange(float min_wire, float max_wire, unsigned int nWires, float min_size)
Sets the complete wire range, with minimum cell size.
bool Operate(geo::WireID const &wireID, size_t tick, float adc) override
OperationBaseClass(geo::PlaneID const &pid, RawDataDrawer *data_drawer=nullptr)
void RunDrawOperation(art::Event const &evt, detinfo::DetectorPropertiesData const &detProp, evdb::View2D *view, unsigned int plane)
void SetWireRange(unsigned int nWires)
Sets the wire range, leaving the number of wire cells unchanged.
Display parameters for the raw data.
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
int fDrawRawDataOrCalibWires
0 for raw
const_reference operator*() const
auto coord(Vector &v, unsigned int n) noexcept
Returns an object to manage the coordinate n of a vector.
TNtupleSim Fill(f1, f2, f3, f4)
void Dump(Stream &&out) const
Prints the current axes on the specified stream.
void SetDrawingLimitsFromRoI(geo::PlaneID::PlaneID_t plane)
double fStartTick
low tick
unsigned int PlaneID_t
Type for the ID number.
Definition: geo_types.h:464
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
details::CacheID_t * fCacheID
information about the last processed plane
GridAxisClass const & WireAxis() const
Return the information about the wires.
std::unique_ptr< SampleInfo_t > sample_info
Information collected from the uncompressed data.
CacheID_t timestamp
object expressing validity range of cached data
ChannelID_t Channel() const
DAQ channel this raw data was read from.
Definition: RawDigit.h:213
std::vector< std::unique_ptr< RawDataDrawer::OperationBaseClass > > operations
constexpr auto abs(T v)
Returns the absolute value of the argument.
Classes detecting configuration changes.
float cell_size
size of each cell
std::vector< short > ADCvector_t
Type representing a (compressed) vector of ADC counts.
Definition: RawDigit.h:72
bool SetMinTDCCellSize(float min_size)
Sets the minimum size for TDC cells.
std::ptrdiff_t GetCell(float wire, float tick) const
Returns the index of specified cell, or -1 if out of range.
GridAxisClass()
Default constructor: an invalid range.
void SetTDCRange(float min_tdc, float max_tdc)
Sets the TDC range, leaving the number of ticks unchanged.
std::vector< BoxInfo_t > boxInfo
Definition of basic raw digits.
void RawDigit2D(art::Event const &evt, detinfo::DetectorPropertiesData const &detProp, evdb::View2D *view, unsigned int plane, bool bZoomToRoI=false)
Draws raw digit content in 2D wire plane representation.
bool hasTick(int tick) const
Returns whether the range includes the specified wire.
bool operator!() const
Returns whether we point to nothing.
A collection of drawable 2-D objects.
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:563
intermediate_table::const_iterator const_iterator
int GetColor(double x) const
Definition: ColorScale.cxx:126
ManyOperations(geo::PlaneID const &pid, RawDataDrawer *data_drawer=nullptr)
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
void PointToData(pointer data)
Point to the specified data, not acquiring ownership.
raw::ChannelID_t Channel() const
Returns the channel of this digit (for convenience)
lar::util::MinMaxCollector< float > WireRange
bool ProcessChannelWithStatus(lariov::ChannelStatusProvider::Status_t channel_status) const
Returns whether a channel with the specified status should be processed.
Classes gathering simple statistics.
no compression
Definition: RawTypes.h:9
std::vector< double > fRawCharge
Sum of Raw Charge.
std::vector< int > fWireMin
lowest wire in interesting region for each plane
bool Update(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp)
Definition: PFPUtils.cxx:1055
double electronsToADC
conversion constant
Manages a cell-like division of a coordinate.
std::add_pointer_t< value_type > pointer
void SetDrawingLimits(float low_wire, float high_wire, float low_tdc, float high_tdc)
Fills the viewport borders from the specified extremes.
size_t n_cells
number of cells in the axis
friend class RoIextractorClass
details::ADCCorrectorClass ADCCorrector
IDparameter< geo::PlaneID > PlaneID
Member type of validated geo::PlaneID parameter.
std::vector< int > fTimeMax
highest time in interesting region for each plane
The color scales used by the event display.
Keeps track of the minimum and maximum value we observed.
TBox & AddBox(double x1, double y1, double x2, double y2)
Definition: View2D.cxx:263
Information about a RawDigit; may contain uncompressed duplicate of data.
art::InputTag const & inputLabel() const
Returns whether we are in the same event (the rest could differ)
OperationBaseClass const * Operator(size_t iOp) const
std::add_lvalue_reference_t< value_type > reference
Data_t min() const
Returns the accumulated minimum, or a very large number if no values.
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
Definition: RawTypes.h:31
detinfo::DetectorPropertiesData const & detProp
float Length() const
Returns the length of the axis.
double fTicks
number of ticks of the clock
mutable::details::PointerToData_t< raw::RawDigit::ADCvector_t const > data
Uncompressed data.
bool ProcessWire(geo::WireID const &wire) override
LArSoft includes.
void AcquireData(pointer data)
Acquire ownership of the specified data.
PadResolution_t PadResolution
stored pad resolution
short MinCharge() const
minimum charge
raw::RawDigit::ADCvector_t const & Data() const
average charge
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
bool SetMinWireCellSize(float min_size)
Sets the minimum size for wire cells.
double operator()(float adc) const
Applies Birks correction to the specified pedestal-subtracted charge.
Build an association between a numerical range and a ROOT color index for use in, eg...
Definition: ColorScale.h:44
bool Add(CONT &cont, float wire, float tick, typename CONT::value_type v)
const evdb::ColorScale & RawQ(geo::SigType_t st) const
unsigned int fCryostat
Cryostat number to draw, typically set by TWQProjectionView.
enum geo::_plane_sigtype SigType_t
Enumerate the possible plane projections.
std::string Name() const override
bool hasWire(int wire) const
Returns whether the range includes the specified wire.
std::ptrdiff_t operator()(float coord) const
Returns the index of the specified cell.
ADCCorrectorClass(detinfo::DetectorPropertiesData const &dp, geo::PlaneID const &pid)
unsigned int fMaxChannelStatus
Display channels with this status and below.
Cached set of RawDigitInfo_t.
Collect all the RawData header files together.
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
float UpperEdge(std::ptrdiff_t iCell) const
Returns the upper edge of the cell.
float LowerEdge(std::ptrdiff_t iCell) const
Returns the lower edge of the cell.
void FillQHisto(const art::Event &evt, unsigned int plane, TH1F *histo)
void GetChargeSum(int plane, double &charge, double &convcharge)
double fMinSignal
minimum ADC count to display a time bin
#define MF_LOG_TRACE(id)
void RunRoIextractor(art::Event const &evt, unsigned int plane)
std::vector< int > fWireMax
highest wire in interesting region for each plane
double fTicks
number of TDC ticks to display, ie # fTicks past fStartTick
std::add_lvalue_reference_t< const_value_type > const_reference
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:73
Float_t d
Definition: plot.C:235
constexpr bool isValidChannelID(raw::ChannelID_t channel)
Definition: RawTypes.h:35
void GetRawDigits(art::Event const &evt)
Reads raw::RawDigits; also triggers Reset()
geo::TPCID CurrentTPC() const
Returns the current TPC as a TPCID.
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
bool hasCell(std::ptrdiff_t iCell) const
Returns whether the cell is present or not.
double TotalClockTicks() const
Definition: RawDataDrawer.h:84
The data type to uniquely identify a TPC.
Definition: geo_types.h:381
Description of geometry of one entire detector.
Definition: GeometryCore.h:119
virtual bool Operate(geo::WireID const &wireID, size_t tick, float adc)=0
bool operator()(geo::WireID const &wireID, size_t tick, float adc)
float Max() const
Returns the extremes of the axis.
bool isEmpty() const
Returns whether minimum and maximum match.
bool bOwned
whether we own our data
Class to aid in the rendering of RawData objects.
Detector simulation of raw signals on wires.
void SetTDCRange(float min_tdc, float max_tdc, unsigned int nTDC)
Sets the complete TDC range.
float CellSize() const
Returns the cell size.
Detects the presence of a new event, data product or wire plane.
std::vector< RawDigitInfo_t > const & Digits() const
Returns the list of digit info.
CellGridClass()
Default constructor: invalid ranges.
bool empty() const
Returns whether the cache is empty() (STL-like interface)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
geo::PlaneID const & PlaneID() const
std::size_t color(std::string const &procname)
void NewData(T const &data)
Create a owned copy of the specified object.
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
RawDigitInfo_t const * FindChannel(raw::ChannelID_t channel) const
Returns a pointer to the digit info of given channel, nullptr if none.
int fTicksPerPoint
number of ticks to include in one point
SigType_t SignalType(PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
virtual bool ProcessWire(geo::WireID const &)
bool fSeeBadChannels
Allow "bad" channels to be viewed.
bool hasCoord(float coord) const
Returns whether the coordinate is included in the range or not.
bool hasRegionOfInterest(geo::PlaneID::PlaneID_t plane) const
friend class BoxDrawer
void SetWireRange(float min_wire, float max_wire, unsigned int nWires)
Sets the complete wire range.
void PointToData(reference data)
Point to the specified data, not acquiring ownership.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
#define MF_LOG_DEBUG(id)
pointer pData
pointer to data
size_t NCells() const
Returns the length of the axis.
void QueueDrawingBoxes(evdb::View2D *view, geo::PlaneID const &pid, std::vector< BoxInfo_t > const &BoxInfo)
unsigned int Nwires(PlaneID const &planeid) const
Returns the total number of wires in the specified plane.
int fAxisOrientation
0 = TDC values on y-axis, wire number on x-axis, 1 = swapped
void Clear()
Stop pointing to the data; if owned, delete it.
std::vector< art::InputTag > fRawDataLabels
module label that made the raw digits, default is daq
Aid in the rendering of RawData objects.
Definition: RawDataDrawer.h:47
art::Ptr< raw::RawDigit > digit
a pointer to the actual digit
GridAxisClass(size_t nDiv, float new_min, float new_max)
Constructor: sets the limits and the number of cells.
bool ProcessTick(size_t tick) override
Definition: MVAAlg.h:12
double fStartTick
Starting tick for the display.
bool good
whether the channel is not bad
void Dump(Stream &&out) const
unsigned int WireID_t
Type for the ID number.
Definition: geo_types.h:546
bool owned() const
Returns whether we have data and we own it.
unsigned int Nplanes(TPCID const &tpcid=tpc_zero) const
Returns the total number of planes in the specified TPC.
Definition: GeometryCore.h:977
RawDataDrawer * RawDataDrawerPtr() const
size_t MaxSamples() const
Returns the largest number of samples in the unpacked raw digits.
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
RoIextractorClass(geo::PlaneID const &pid, RawDataDrawer *data_drawer)
void ResetRegionOfInterest()
Forgets about the current region of interest.
details::CellGridClass * fDrawingRange
information about the viewport
std::vector< int > fTimeMin
lowest time in interesting region for each plane
::util::PlaneDataChangeTracker_t CacheID_t
Definition: RawDataDrawer.h:42
std::add_const_t< value_type > const_value_type
Manages a grid-like division of 2D space.
TCEvent evt
Definition: DataStructs.cxx:8
bool ProcessWire(geo::WireID const &wireID) override
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
Applies Birks correction.
OperationBaseClass * Operator(size_t iOp)
virtual std::string Name() const
void Uncompress(const std::vector< short > &adc, std::vector< short > &uncompressed, raw::Compress_t compress)
Uncompresses a raw data buffer.
Definition: raw.cxx:744
evd::details::RawDigitCacheDataClass * digit_cache
Cache of raw digits.
int fPedestalOption
0: use DetPedestalService; 1: Use pedestal in raw::RawDigt; 2: no ped subtraction ...
void SetTDCRange(unsigned int nTDC)
Sets a simple TDC range: all the ticks, one cell per tick.
void StealData(std::remove_const_t< T > &&data)
Move data from the specified object, and own it.
Namespace collecting geometry-related classes utilities.
std::vector< RawDigitInfo_t > digits
vector of raw digit information
GridAxisClass const & TDCAxis() const
Return the information about the TDCs.
bool hasData() const
Returns whether we have data.
art::Ptr< raw::RawDigit > DigitPtr() const
Returns an art pointer to the actual digit.
bool RunOperation(art::Event const &evt, OperationBaseClass *operation)
std::tuple< float, float, float, float > GetCellBox(std::ptrdiff_t iCell) const
Returns the coordinates { w1, t1, w2, t2 } of specified cell.
art framework interface to geometry description
size_t NCells() const
Returns the total number of cells in the grid.
void SetData(pointer data, bool owned)
Sets the data and the ownership.
bool Operate(geo::WireID const &wireID, size_t tick, float adc) override
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:109
bool fUncompressWithPed
Option to uncompress with pedestal. Turned off by default.
std::add_pointer_t< const_value_type > const_pointer
std::ptrdiff_t GetCell(float coord) const
Returns the index of the specified cell.
void AddOperation(std::unique_ptr< OperationBaseClass > new_op)
std::vector< double > fConvertedCharge
Sum of Charge Converted using Birks&#39; formula.
void ExtractRange(TVirtualPad *pPad, std::vector< double > const *zoom=nullptr)
Fills the viewport information from the specified pad.