LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
TWQProjectionView.cxx
Go to the documentation of this file.
1 //
6 #include "Buttons.h"
7 #include "TCanvas.h"
8 #include "TFrame.h"
9 #include "TGFrame.h" // For TGMainFrame, TGHorizontalFrame
10 #include "TGLabel.h"
11 #include "TGLayout.h" // For TGLayoutHints
12 #include "TGNumberEntry.h"
13 #include "TGTextView.h"
14 #include "TMath.h"
15 #include "TROOT.h"
16 #include "TRootEmbeddedCanvas.h"
17 #include "TString.h"
18 #include "TVirtualX.h"
19 
27 #include "lareventdisplay/EventDisplay/ChangeTrackers.h" // util::DataProductChangeTracker_t
44 
48 
49 namespace evd {
50 
51  static unsigned int kPlane;
52  static unsigned int kWire;
53  static double kDistance;
54  static int curr_zooming_plane;
55  static const char* zoom_opt = 0;
56 
57  static int shift_lock;
58 
59  //......................................................................
61  : evdb::Canvas(mf)
62  , fRedraw(nullptr)
63  , fCryoInput(nullptr)
64  , fTPCInput(nullptr)
65  , fTotalTPCLabel(nullptr)
66  , isZoomAutomatic(art::ServiceHandle<evd::EvdLayoutOptions const>()->fAutoZoomInterest)
67  , fLastEvent(new util::DataProductChangeTracker_t)
68  {
69  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout>()->Get();
70 
71  // first make pads for things that don't depend on the number of
72  // planes in the detector
73  // bottom left corner is (0.,0.), top right is (1., 1.)
74  fAngleInfo = NULL;
75  fXYZPosition = NULL;
76 
77  fLastThreshold = -1.;
78 
80  fHeaderPad = new HeaderPad("fHeaderPad", "Header", 0.0, 0.0, 0.15, 0.13, "");
81  fHeaderPad->Draw();
82 
84  fMC = new MCBriefPad("fMCPad", "MC Info.", 0.15, 0.13, 1.0, 0.17, "");
85  fMC->Draw();
86 
88  // fWireQ = new TQPad("fWireQPad", "ADCvsTime",0.15,0.0,1.0,0.13,"TQ", 0, 0);
89  fWireQ = new TQPad("fWireQPad", "ADCvsTime", 0.15, 0.0, 1.0, 0.14, "TQ", 0, 0);
90  fWireQ->Pad()->SetBit(TPad::kCannotMove, true);
91  fWireQ->Draw();
92 
93  // add new "meta frame" to hold the GUI Canvas and a side frame (vframe)
94  fMetaFrame = new TGCompositeFrame(mf, 60, 60, kHorizontalFrame);
95  fMetaFrame->SetBit(TPad::kCannotMove, true);
96 
97  //new frame organizing the buttons on the left of the canvas.
98  fVFrame = new TGCompositeFrame(fMetaFrame, 60, 60, kVerticalFrame);
99  // Define a layout for placing the canvas within the frame.
100  fLayout =
101  new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX | kLHintsExpandY, 5, 5, 5, 5);
102 
103  mf->RemoveFrame((TGFrame*)fEmbCanvas);
104  mf->RemoveFrame(fFrame);
105 
106  fEmbCanvas->ReparentWindow(fMetaFrame, fXsize, fYsize);
107 
108  fMetaFrame->AddFrame(fVFrame, new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandY));
109  fMetaFrame->AddFrame(fEmbCanvas, fLayout);
110 
111  mf->AddFrame(fMetaFrame, fLayout);
112  mf->AddFrame(fFrame);
113 
114  // plane number entry
115  fPlaneEntry = new TGNumberEntry(fFrame,
116  0,
117  2,
118  -1,
119  TGNumberFormat::kNESInteger,
120  TGNumberFormat::kNEAAnyNumber,
121  TGNumberFormat::kNELLimitMinMax,
122  0,
123  wireReadoutGeom.Nplanes() - 1);
124 
125  kPlane = 0;
126  constexpr geo::TPCID tpcid{0, 0};
127  kWire = TMath::Nint(0.5 * wireReadoutGeom.Nwires(geo::PlaneID{tpcid, 0}));
128  kDistance = 1.5;
129  fWireQ->SetPlaneWire(kPlane, kWire);
130 
131  // Initial value
132  fPlaneEntry->SetNumber(kPlane);
133 
134  // There are two "signals" to which a TGNumberEntry may respond:
135  // when the user clicks on the arrows, or when the user types in a
136  // new number in the text field.
137  fPlaneEntry->Connect("ValueSet(Long_t)", "evd::TWQProjectionView", this, "SetPlane()");
138  fPlaneEntry->GetNumberEntry()->Connect(
139  "ReturnPressed()", "evd::TWQProjectionView", this, "SetPlane()");
140  // Text label for this numeric field.
141  fPlaneLabel = new TGLabel(fFrame, "Plane");
142 
143  // wire number entry
144  unsigned int maxwire = 0;
145  for (auto const& plane : wireReadoutGeom.Iterate<geo::PlaneGeo>(tpcid)) {
146  maxwire = (plane.Nwires() - 1 > maxwire) ? plane.Nwires() - 1 : maxwire;
147  }
148 
149  fWireEntry = new TGNumberEntry(fFrame,
150  0,
151  6,
152  -1,
153  TGNumberFormat::kNESInteger,
154  TGNumberFormat::kNEAAnyNumber,
155  TGNumberFormat::kNELLimitMinMax,
156  0,
157  maxwire);
158  // Initial value
159  fWireEntry->SetNumber(kWire);
160 
161  // There are two "signals" to which a TGNumberEntry may respond:
162  // when the user clicks on the arrows, or when the user types in a
163  // new number in the text field.
164  fWireEntry->Connect("ValueSet(Long_t)", "evd::TWQProjectionView", this, "SetWire()");
165  fWireEntry->GetNumberEntry()->Connect(
166  "ReturnPressed()", "evd::TWQProjectionView", this, "SetWire()");
167 
168  // Text label for this numeric field.
169  fWireLabel = new TGLabel(fFrame, "Wire");
170 
171  // adc threshold number entry
172  fThresEntry = new TGNumberEntry(fFrame,
173  0,
174  6,
175  -1,
176  TGNumberFormat::kNESInteger,
177  TGNumberFormat::kNEAAnyNumber,
178  TGNumberFormat::kNELLimitMinMax,
179  0,
180  wireReadoutGeom.Nwires(geo::PlaneID{tpcid, 0}) - 1);
181  // Initial value
186 
187  fThresEntry->SetNumber(rawopt->fMinSignal);
188 
189  // There are two "signals" to which a TGNumberEntry may respond:
190  // when the user clicks on the arrows, or when the user types in a
191  // new number in the text field.
192  fThresEntry->Connect("ValueSet(Long_t)", "evd::TWQProjectionView", this, "SetThreshold()");
193  fThresEntry->GetNumberEntry()->Connect(
194  "ReturnPressed()", "evd::TWQProjectionView", this, "SetThreshold()");
195 
196  // Text label for this numeric field.
197  fThresLabel = new TGLabel(fFrame, "ADC Threshold");
198 
199  // check button to toggle color vs grey
200  fGreyScale = new TGCheckButton(fFrame, "Grayscale", 1);
201  fGreyScale->Connect("Clicked()", "evd::TWQProjectionView", this, "SetGreyscale()");
202  if (cst->fColorOrGray == 1) fGreyScale->SetState(kButtonDown);
203 
204  // check button to toggle MC information
205  if (evdlayoutopt->fEnableMCTruthCheckBox) {
206  fMCOn = new TGCheckButton(fFrame, "MC Truth", 5);
207  fMCOn->Connect("Clicked()", "evd::TWQProjectionView", this, "SetMCInfo()");
208  if (sdo->fShowMCTruthText == 1) fMCOn->SetState(kButtonDown);
209  }
210 
211  // radio buttons to toggle drawing raw vs calibrated information
212  fRawCalibDraw = new TGRadioButton(fFrame, "Both", 2);
213  fCalibDraw = new TGRadioButton(fFrame, "Reconstructed", 3);
214  fRawDraw = new TGRadioButton(fFrame, "Raw", 4);
215  fRawDraw->Connect("Clicked()", "evd::TWQProjectionView", this, "SetRawCalib()");
216  fCalibDraw->Connect("Clicked()", "evd::TWQProjectionView", this, "SetRawCalib()");
217  fRawCalibDraw->Connect("Clicked()", "evd::TWQProjectionView", this, "SetRawCalib()");
218  if (rawopt->fDrawRawDataOrCalibWires == 0)
219  fRawDraw->SetState(kButtonDown);
220  else if (rawopt->fDrawRawDataOrCalibWires == 1)
221  fCalibDraw->SetState(kButtonDown);
222  else if (rawopt->fDrawRawDataOrCalibWires == 2)
223  fRawCalibDraw->SetState(kButtonDown);
224 
225  // Put all these widgets into the frame. The last
226  // four numbers in each TGLayoutHint are padleft, padright,
227  // padtop, padbottom.
228  if (evdlayoutopt->fEnableMCTruthCheckBox) {
229  fFrame->AddFrame(fMCOn, new TGLayoutHints(kLHintsBottom | kLHintsRight, 0, 0, 5, 1));
230  }
231  fFrame->AddFrame(fGreyScale, new TGLayoutHints(kLHintsBottom | kLHintsRight, 0, 0, 5, 1));
232  fFrame->AddFrame(fRawCalibDraw, new TGLayoutHints(kLHintsBottom | kLHintsRight, 0, 0, 5, 1));
233  fFrame->AddFrame(fCalibDraw, new TGLayoutHints(kLHintsBottom | kLHintsRight, 0, 0, 5, 1));
234  fFrame->AddFrame(fRawDraw, new TGLayoutHints(kLHintsBottom | kLHintsRight, 0, 0, 5, 1));
235  fFrame->AddFrame(fPlaneEntry, new TGLayoutHints(kLHintsBottom | kLHintsRight, 0, 0, 2, 1));
236  fFrame->AddFrame(fPlaneLabel, new TGLayoutHints(kLHintsBottom | kLHintsRight, 0, 0, 5, 1));
237  fFrame->AddFrame(fWireEntry, new TGLayoutHints(kLHintsBottom | kLHintsRight, 0, 0, 2, 1));
238  fFrame->AddFrame(fWireLabel, new TGLayoutHints(kLHintsBottom | kLHintsRight, 0, 0, 5, 1));
239  fFrame->AddFrame(fThresEntry, new TGLayoutHints(kLHintsBottom | kLHintsRight, 0, 0, 2, 1));
240  fFrame->AddFrame(fThresLabel, new TGLayoutHints(kLHintsBottom | kLHintsRight, 0, 0, 5, 1));
241 
242  // geometry to figure out the number of planes
243  unsigned int nplanes = wireReadoutGeom.Nplanes();
244 
245  if (evdlayoutopt->fShowSideBar)
246  SetUpSideBar();
247  else
248  evdlayoutopt->fShowEndPointSection =
249  0; // zero it to avoid a misconfiguration in the fcl file.
250 
251  //zero the ppoints queue.
252  ppoints.clear();
253  pline.clear();
254 
255  // now determine the positions of all the time vs wire number
256  // and charge histograms for the planes
257  for (unsigned int i = 0; i < nplanes; ++i) {
258  double twx1 = 0.;
259  double twx2 = 0.97;
260  double twx3 = 1.0;
261  double twy1 = 0.17 + (i) * (1.0 - 0.171) / (1. * nplanes);
262  double twy2 = 0.17 + (i + 1) * (1.0 - 0.171) / (1. * nplanes);
263 
264  TString padname = "fWireProjP";
265  padname += i;
266 
267  TString padtitle = "Plane";
268  padtitle += i;
269 
270  evdb::Canvas::fCanvas->cd();
271  fPlanes.push_back(new TWireProjPad(padname, padtitle, twx1, twy1, twx2, twy2, i));
272  fPlanes[i]->Draw();
273  fPlanes[i]->Pad()->AddExec(
274  "mousedispatch",
275  Form("evd::TWQProjectionView::MouseDispatch(%d, (void*)%lu)", i, (unsigned long)this));
276 
277  padname = "fQPadPlane";
278  padname += i;
279 
280  padtitle = "QPlane";
281  padtitle += i;
282 
283  evdb::Canvas::fCanvas->cd();
284  fPlaneQ.push_back(new TQPad(padname, padtitle, twx2, twy1, twx3, twy2, "Q", i, 0));
285  fPlaneQ[i]->Draw();
286  }
287 
288  // propagate the zoom setting
290 
291  evdb::Canvas::fCanvas->Update();
292  }
293 
294  //......................................................................
296  {
297  if (fHeaderPad) {
298  delete fHeaderPad;
299  fHeaderPad = 0;
300  }
301  if (fMC) {
302  delete fMC;
303  fMC = 0;
304  }
305  if (fWireQ) {
306  delete fWireQ;
307  fWireQ = 0;
308  }
309  if (fPlaneEntry) {
310  delete fPlaneEntry;
311  fPlaneEntry = 0;
312  }
313  if (fWireEntry) {
314  delete fWireEntry;
315  fWireEntry = 0;
316  }
317  if (fPlaneLabel) {
318  delete fPlaneLabel;
319  fPlaneLabel = 0;
320  }
321  if (fWireLabel) {
322  delete fWireLabel;
323  fWireLabel = 0;
324  }
325  for (unsigned int i = 0; i < fPlanes.size(); ++i) {
326  if (fPlanes[i]) {
327  delete fPlanes[i];
328  fPlanes[i] = 0;
329  }
330  if (fPlaneQ[i]) {
331  delete fPlaneQ[i];
332  fPlaneQ[i] = 0;
333  }
334  }
335  fPlanes.clear();
336  fPlaneQ.clear();
337 
338  delete fLastEvent;
339  }
340 
341  //......................................................................
343  {
344  for (TWireProjPad* planePad : fPlanes)
345  planePad->RawDataDraw()->ResetRegionOfInterest();
346  } // TWQProjectionView::ResetRegionsOfInterest()
347 
348  //......................................................................
349  void TWQProjectionView::DrawPads(const char* /*opt*/)
350  {
351 
352  OnNewEvent(); // if the current event is a new one, we need some resetting
353 
354  for (unsigned int i = 0; i < fPlanes.size(); ++i) {
355  fPlanes[i]->Draw();
356  fPlanes[i]->Pad()->Update();
357  fPlanes[i]->Pad()->GetFrame()->SetBit(TPad::kCannotMove, true);
358  }
359  for (unsigned int j = 0; j < fPlaneQ.size(); ++j) {
360  fPlaneQ[j]->Draw();
361  fPlaneQ[j]->Pad()->Update();
362  fPlaneQ[j]->Pad()->GetFrame()->SetBit(TPad::kCannotMove, true);
363  }
364  }
365 
366  //......................................................................
367  void TWQProjectionView::SetAutomaticZoomMode(bool bSet /* = true */)
368  {
369  isZoomAutomatic = bSet;
370  for (TWireProjPad* pPlane : fPlanes)
371  pPlane->SetZoomToRoI(isZoomAutomatic);
372  } // TWQProjectionView::SetAutomaticZoomMode()
373 
374  //......................................................................
375  void TWQProjectionView::Draw(const char* opt)
376  {
377  mf::LogDebug("TWQProjectionView") << "Starting to draw";
378 
379  OnNewEvent(); // if the current event is a new one, we need some resetting
380 
381  fPrevZoomOpt.clear();
382 
383  evdb::Canvas::fCanvas->cd();
384  zoom_opt = 0;
385  fHeaderPad->Draw();
386  fMC->Draw();
387  fWireQ->Draw();
388 
390  if (evdlayoutopt->fPrintTotalCharge) PrintCharge();
391 
392  //clear queue of selected points
393  ppoints.clear();
394  pline.clear();
395  // Reset current zooming plane - since it's not currently zooming.
396  curr_zooming_plane = -1;
397 
398  unsigned int const nPlanes = fPlanes.size();
399  MF_LOG_DEBUG("TWQProjectionView") << "Start drawing " << nPlanes << " planes";
400  // double Charge=0, ConvCharge=0;
401  for (unsigned int i = 0; i < nPlanes; ++i) {
402  TWireProjPad* planePad = fPlanes[i];
403  planePad->Draw(opt);
404  planePad->Pad()->Update();
405  planePad->Pad()->GetFrame()->SetBit(TPad::kCannotMove, true);
406  fPlaneQ[i]->Draw();
407  std::vector<double> ZoomParams = planePad->GetCurrentZoom();
408  fZoomOpt.wmin[i] = ZoomParams[0];
409  fZoomOpt.wmax[i] = ZoomParams[1];
410  fZoomOpt.tmin[i] = ZoomParams[2];
411  fZoomOpt.tmax[i] = ZoomParams[3];
412  }
413  mf::LogDebug("TWQProjectionView") << "Done drawing " << nPlanes << " planes";
414 
415  // Reset any text boxes which are enabled
416 
417  if (fXYZPosition) fXYZPosition->SetForegroundColor(kBlack);
418 
419  if (fAngleInfo) fAngleInfo->SetForegroundColor(kBlack);
420 
421  evdb::Canvas::fCanvas->Update();
422  mf::LogDebug("TWQProjectionView") << "Done drawing";
423  }
424 
425  //......................................................................
427  {
429  infot->SetTestFlag(number);
430  }
431 
432  //......................................................................
434  {
436  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout const>()->Get();
437 
438  for (size_t iplane = 0; iplane < fPlanes.size(); ++iplane) {
439  geo::PlaneID planeid(rawopt->CurrentTPC(), iplane);
440  if (wireReadoutGeom.SignalType(planeid) != geo::kCollection) continue;
441 
442  double ch = 0, convch = 0;
443  if (rawopt->fDrawRawDataOrCalibWires == 0) {
444  fPlanes[iplane]->RawDataDraw()->GetChargeSum(iplane, ch, convch);
445  mf::LogVerbatim("TWQProjectionView") << "Warning! Calculating for RawData! ";
446  }
447  else {
448  fPlanes[iplane]->RecoBaseDraw()->GetChargeSum(iplane, ch, convch);
449  }
450 
451  mf::LogVerbatim("TWQProjectionView")
452  << "\ncharge collected at collection plane: " << iplane << " " << ch << " " << convch;
453  } // for
454  }
455 
456  //-------------------------------------------------------------------
457  //......................................................................
458  void TWQProjectionView::MouseDispatch(int plane, void* wqpv)
459  {
460  //initial check for a mouse click on a TBox object
461  int event = gPad->GetEvent();
464 
465  switch (event) {
466 
467  case kButton1Shift:
468  shift_lock = 1;
469  if (evdlayoutopt->fMakeClusters == 1) { wqpp->SelectHit(plane); }
470  else {
471  wqpp->SelectPoint(plane);
472  }
473  break;
474  case kButton1Up:
475  if (shift_lock == 1) break;
476  if (evdlayoutopt->fChangeWire == 1) wqpp->ChangeWire(plane);
477  case kButton1Down: shift_lock = 0;
478  case kButton1Motion:
479  if (evdlayoutopt->fMakeClusters == 1) { wqpp->SetClusters(plane); }
480  else {
481  wqpp->SetMouseZoomRegion(plane);
482  }
483  break;
484  // default:
485  }
486  }
487 
488  //......................................................................
490  {
491  //initial check for a mouse click on a TBox object
492  int event = gPad->GetEvent();
493  int px = gPad->GetEventX();
494  if (event != 11) return;
495  TObject* select = gPad->GetSelected();
496  if (!select) return;
497  if (!select->InheritsFrom("TBox")) return;
498 
499  //now find wire that was clicked on
500  float xx = gPad->AbsPixeltoX(px);
501  float x = gPad->PadtoX(xx);
502 
503  kPlane = plane;
504  kWire = (unsigned int)TMath::Nint(x);
505 
506  this->SetPlaneWire();
507 
508  return;
509  }
510 
511  //......................................................................
513  {
514  //initial check for a mouse click on a TBox object
515  int event = gPad->GetEvent();
516 
517  if (event != 7) return;
518 
520  if (evdlayoutopt->fShowEndPointSection != 1) return;
521  //struct planepoint;
522  int px = gPad->GetEventX();
523  double w0 = gPad->AbsPixeltoX(px);
524  double x = gPad->PadtoX(w0);
525 
526  int py = gPad->GetEventY();
527  double t0 = gPad->AbsPixeltoY(py);
528  double y = gPad->PadtoY(t0);
529 
530  util::PxPoint ppx(plane, x, y);
531  curr_zooming_plane = -1;
532 
533  // check if not clicking on a plane that is already in the ppoints list:
534  int repeat_plane = -1;
535  for (size_t ii = 0; ii < this->ppoints.size(); ++ii)
536  if (ppx.plane == this->ppoints[ii].plane) {
537  this->ppoints[ii] = ppx;
538  //clear View and draw new Marker
539  this->fPlanes[this->ppoints[ii].plane]->View()->Clear();
540  if (evdlayoutopt->fShowEndPointMarkers)
541  this->fPlanes[this->ppoints[ii].plane]->View()->AddMarker(ppx.w, ppx.t, kRed, 29, 2.0);
542  else
543  this->fPlanes[plane]->View()->AddMarker(0.0, 0.0, 2, 1, 0.1);
544  this->fPlanes[this->ppoints[ii].plane]->View()->Draw();
545  repeat_plane = this->ppoints[ii].plane;
546  break;
547  }
548 
549  //if plane does not repeat and size of list is larger than 2 pop_front
550  // and delete its marker. Otherwise just push_back.
551  if (repeat_plane == -1) {
552  if (this->ppoints.size() >= 2) {
553  this->fPlanes[this->ppoints[0].plane]->Pad()->cd();
554  this->fPlanes[this->ppoints[0].plane]->View()->Clear();
555  this->fPlanes[this->ppoints[0].plane]->View()->Draw();
556  this->ppoints.pop_front();
557  }
558  this->ppoints.push_back(ppx);
559  this->fPlanes[plane]->Pad()->cd();
560  this->fPlanes[plane]->View()->Clear();
561  if (evdlayoutopt->fShowEndPointMarkers)
562  this->fPlanes[plane]->View()->AddMarker(ppx.w, ppx.t, kRed, 29, 2.0);
563  else
564  this->fPlanes[plane]->View()->AddMarker(0.0, 0.0, 2, 1, 0.1);
565  this->fPlanes[plane]->View()->Draw();
566  }
567 
568  return;
569  }
570 
571  //......................................................................
573  {
574  for (size_t x = 0; x < fPlanes.size(); ++x) {
575  fPlanes[x]->Pad()->cd();
576  fPlanes[x]->View()->Clear();
577  fPlanes[x]->View()->AddMarker(0.0, 0.0, 2, 1, 0.1);
578  fPlanes[x]->Pad()->Update();
579  fPlanes[x]->View()->Draw();
580  }
581  ppoints.clear();
582  gPad->Modified();
583  gPad->Update();
584  gPad->cd();
585  }
586 
587  //......................................................................
589  detinfo::DetectorPropertiesData const& detProp)
590  {
591  // if list is larger than or equal to two, can project to XYZ and extrapolate to third plane (if exists)
592 
593  if (pline.size() >= 2) {
594 
595  double xyz_vertex_fit[3];
596  double second_time;
597  double xx0 = 0., yy0 = 0., zz0 = 0.;
598  double xx1 = 0., yy1 = 0., zz1 = 0.;
599  double length;
600 
602  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout const>()->Get();
604  double ftimetick = sampling_rate(clockData) / 1000.;
605  double larv = detProp.DriftVelocity(detProp.Efield(), detProp.Temperature());
606 
607  //find wireIDs corresponding to found wires.
608  geo::WireID wire1(rawOpt->fCryostat, rawOpt->fTPC, pline[0].plane, pline[0].w0);
609  geo::WireID wire2(rawOpt->fCryostat, rawOpt->fTPC, pline[1].plane, pline[1].w0);
610 
611  std::optional<geo::WireIDIntersection> wires_cross{};
612  bool time_good = false;
613 
614  if (std::abs(pline[0].t0 - pline[1].t0) < 200) {
615  wires_cross = wireReadoutGeom.WireIDsIntersect(wire1, wire2);
616  time_good = true;
617  }
618  else {
619  TGText* tt = new TGText("too big");
620  tt->InsLine(1, "time distance");
621  fXYZPosition->SetText(tt);
622  fXYZPosition->Update();
623  }
624 
625  constexpr geo::TPCID tpcid{0, 0};
626  if (wires_cross) {
627  TGText* tt = new TGText("wires cross");
628  fXYZPosition->SetText(tt);
629  fXYZPosition->Update();
630  xyz_vertex_fit[1] = wires_cross->y;
631  xyz_vertex_fit[2] = wires_cross->z;
632  auto pos = wireReadoutGeom.Plane(geo::PlaneID(tpcid, pline[0].plane)).GetBoxCenter();
633  xyz_vertex_fit[0] = (pline[0].t0 - trigger_offset(clockData)) * larv * ftimetick + pos.X();
634  pos = wireReadoutGeom.Plane(geo::PlaneID(tpcid, pline[1].plane)).GetBoxCenter();
635  second_time = (pline[1].t0 - trigger_offset(clockData)) * larv * ftimetick + pos.X();
636 
637  xx0 = (xyz_vertex_fit[0] + second_time) / 2;
638  yy0 = wires_cross->y;
639  zz0 = wires_cross->z;
640 
642  }
643  else {
644  if (time_good) { //otherwise the wires_cross are false by default
645  TGText* tt = new TGText("cross");
646  tt->InsLine(1, "wires do not");
647  fXYZPosition->SetText(tt);
648  fXYZPosition->Update();
649  }
650  }
651  //find wireIDs corresponding to found wires AT END OF LINE.
652  wire1.Wire = pline[0].w1;
653  wire2.Wire = pline[1].w1;
654 
655  wires_cross = std::nullopt;
656  time_good = false;
657 
658  if (std::abs(pline[0].t1 - pline[1].t1) < 200) {
659  wires_cross = wireReadoutGeom.WireIDsIntersect(wire1, wire2);
660  time_good = true;
661  }
662  else {
663  TGText* tt = new TGText("too big");
664  tt->InsLine(1, "time distance");
665  fXYZPosition->SetText(tt);
666  fXYZPosition->Update();
667  // return; //not returning, because may need to delete marker from wplane
668  }
669 
670  if (wires_cross) {
671  TGText* tt = new TGText("wires do cross");
672  fXYZPosition->SetText(tt);
673  fXYZPosition->Update();
674  xyz_vertex_fit[1] = wires_cross->y;
675  xyz_vertex_fit[2] = wires_cross->z;
676  auto pos = wireReadoutGeom.Plane(geo::PlaneID(tpcid, pline[0].plane)).GetBoxCenter();
677  xyz_vertex_fit[0] = (pline[0].t1 - trigger_offset(clockData)) * larv * ftimetick + pos.X();
678  pos = wireReadoutGeom.Plane(geo::PlaneID(tpcid, pline[1].plane)).GetBoxCenter();
679  second_time = (pline[1].t1 - trigger_offset(clockData)) * larv * ftimetick + pos.X();
680 
681  xx1 = (xyz_vertex_fit[0] + second_time) / 2;
682  yy1 = wires_cross->y;
683  zz1 = wires_cross->z;
684  }
685  else {
686  if (time_good) { //otherwise the wires_cross are false by default
687  TGText* tt = new TGText("cross");
688  tt->InsLine(1, "wires do not");
689  fXYZPosition->SetText(tt);
690  fXYZPosition->Update();
691  }
692  // return; //not returning, because may need to delete marker from wplanereturn;
693  }
694  //update pad?
695  gPad->Modified();
696  gPad->Update();
697  gPad->cd();
698 
699  length = pow(xx0 - xx1, 2) + pow(yy0 - yy1, 2) + pow(zz0 - zz1, 2);
700  length = pow(length, 0.5);
701  return length;
702  } // end if( this->ppoints.size()>=2)
703 
704  else {
705  TGText* tt = new TGText("selected points");
706  tt->InsLine(1, "not enough");
707  fXYZPosition->SetText(tt);
708  fXYZPosition->Update();
709  }
710 
711  return -99;
712  }
713 
714  //......................................................................
716  {
717  art::Event const* pEvent = evdb::EventHolder::Instance()->GetEvent();
718  if (not pEvent) {
719  std::cerr << "No event available\n";
720  return;
721  }
722 
723  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService>()->DataFor(*pEvent);
724 
725  // if list is larger than or equal to two, can project to XYZ and extrapolate to third plane (if exists)
726 
727  if (ppoints.size() >= 2) {
728 
729  double xyz_vertex_fit[3] = {0.};
730  double second_time = 0.;
731  geo::PlaneGeo::LocalPoint_t const origin{0., 0., 0.};
732 
733  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout const>()->Get();
735 
736  //find channels corresponding to found wires.
737  geo::WireID wire1(rawOpt->fCryostat, rawOpt->fTPC, ppoints[0].plane, ppoints[0].w);
738  geo::WireID wire2(rawOpt->fCryostat, rawOpt->fTPC, ppoints[1].plane, ppoints[1].w);
739 
740  std::optional<geo::WireIDIntersection> wires_cross{};
741  bool time_good = false;
742 
743  if (std::abs(ppoints[0].t - ppoints[1].t) < 200) {
744  wires_cross = wireReadoutGeom.WireIDsIntersect(wire1, wire2);
745  time_good = true;
746  }
747  else {
748  TGText* tt = new TGText("too big");
749  tt->InsLine(1, "time distance");
750  fXYZPosition->SetText(tt);
751  fXYZPosition->Update();
752  }
753 
754  if (wires_cross) {
755  xyz_vertex_fit[1] = wires_cross->y;
756  xyz_vertex_fit[2] = wires_cross->z;
757 
758  xyz_vertex_fit[0] =
759  detProp.ConvertTicksToX(ppoints[0].t, ppoints[0].plane, rawOpt->fTPC, rawOpt->fCryostat);
760  second_time =
761  detProp.ConvertTicksToX(ppoints[1].t, ppoints[1].plane, rawOpt->fTPC, rawOpt->fCryostat);
762 
763  TGText* tt = new TGText(Form("z:%4.1f", wires_cross->z));
764  tt->InsLine(1, Form("x:%4.1f,", (xyz_vertex_fit[0] + second_time) / 2));
765  tt->InsLine(1, Form("y:%4.1f,", wires_cross->y));
766  fXYZPosition->SetText(tt);
767  fXYZPosition->Update();
769  }
770  else {
771  if (time_good) { //otherwise the wires_cross are false by default
772  TGText* tt = new TGText("cross");
773  tt->InsLine(1, "wires do not");
774  fXYZPosition->SetText(tt);
775  fXYZPosition->Update();
776  }
777  // return; //not returning, because may need to delete marker from wplanereturn;
778  }
779  // extrapolate third point only if there are enough planes
780  if (fPlanes.size() > 2) {
781 
782  unsigned int wplane = 0;
783  unsigned int wirevertex = 0;
785 
786  for (size_t xx = 0; xx < fPlanes.size(); ++xx) {
787  wplane = 0;
788  for (int yy = 0; yy < 2; ++yy)
789  if (ppoints[yy].plane == xx) ++wplane;
790 
791  if (!wplane) {
792  wplane = xx;
793  break;
794  }
795  }
796 
797  geo::PlaneID const planeID{rawOpt->fCryostat, rawOpt->fTPC, wplane};
798  auto const& planeg = wireReadoutGeom.Plane(planeID);
799  auto pos = planeg.toWorldCoords(origin);
800  pos.SetY(xyz_vertex_fit[1]);
801  pos.SetZ(xyz_vertex_fit[2]);
802 
803  wirevertex = planeg.NearestWireID(pos).Wire;
804 
805  double timestart = detProp.ConvertXToTicks(xyz_vertex_fit[0], planeID);
806 
807  fPlanes[wplane]->Pad()->cd();
808  fPlanes[wplane]->View()->Clear();
809  if (wires_cross && evdlayoutopt->fShowEndPointMarkers) //only Draw if it makes sense
810  fPlanes[wplane]->View()->AddMarker(wirevertex, timestart, kMagenta, 29, 2.0);
811  else //draw dummy marker to delete old one
812  fPlanes[wplane]->View()->AddMarker(0.0, 0.0, 2, 1, 0.1);
813  fPlanes[wplane]->Pad()->Update();
814  fPlanes[wplane]->View()->Draw();
815  } // end if(fPlanes.size()>2)
816  //update pad?
817  gPad->Modified();
818  gPad->Update();
819  gPad->cd();
820  } // end if( this->ppoints.size()>=2)
821  else {
822  TGText* tt = new TGText("selected points");
823  tt->InsLine(1, "not enough");
824  fXYZPosition->SetText(tt);
825  fXYZPosition->Update();
826  }
827  }
828 
829  //......................................................................
830  // SaveSelection
832  {
833  art::Event const* pEvent = evdb::EventHolder::Instance()->GetEvent();
834  if (not pEvent) {
835  std::cerr << "No event available\n";
836  return;
837  }
838 
840  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout const>()->Get();
841  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService>()->DataFor(*pEvent);
842  auto const detProp =
843  art::ServiceHandle<detinfo::DetectorPropertiesService>()->DataFor(*pEvent, clockData);
844  util::GeometryUtilities const gser{*geom, wireReadoutGeom, clockData, detProp};
845 
847  if (evdlayoutoptions->fMakeClusters) {
848  //only calculating in 3 planes now, needs to be generalized eventually
849  double omx[3];
850  double xphi;
851  double xtheta;
852  unsigned int ii;
853  if (pline.size() < 2) {
854  TGText* tt = new TGText("not enough lines selected");
855  fAngleInfo->SetText(tt);
856  fAngleInfo->Update();
857  return;
858  }
859  double deltawire;
860  double deltatime;
861  for (ii = 0; ii < pline.size(); ++ii) {
862  deltawire = pline[ii].w1 - pline[ii].w0;
863  deltatime = pline[ii].t1 - pline[ii].t0;
864  omx[ii] = gser.Get2Dangle(deltawire, deltatime);
865  }
866 
867  for (size_t ii = 0; ii < pline.size(); ++ii) {
868  fPlanes[pline[ii].plane]->SaveHitList(
869  pline[ii].w0, pline[ii].t0, pline[ii].w1, pline[ii].t1, kDistance, zoom_opt);
870  }
871  if (fPlanes.size() > pline.size() && pline.size() >= 2) { // need to project to third plane
872 
873  util::PxPoint p00(pline[0].plane, pline[0].w0, pline[0].t0);
874  util::PxPoint p01(pline[1].plane, pline[1].w0, pline[1].t0);
875  util::PxPoint p0N(0, 0, 0);
876  int error1 = gser.GetProjectedPoint(&p00, &p01, p0N);
877 
878  util::PxPoint p10(pline[0].plane, pline[0].w1, pline[0].t1);
879  util::PxPoint p11(pline[1].plane, pline[1].w1, pline[1].t1);
880  util::PxPoint p1N(0, 0, 0);
881  int error2 = gser.GetProjectedPoint(&p10, &p11, p1N);
882  if (error1 != -1 && error2 != -1)
883  fPlanes[p0N.plane]->SaveHitList(p0N.w, p0N.t, p1N.w, p1N.t, kDistance, zoom_opt, false);
884  }
885 
886  for (size_t jj = 0; jj < fPlanes.size(); ++jj) {
887  fPlanes[jj]->UpdatePad();
888  }
889 
890  gser.Get3DaxisN(pline[0].plane, pline[1].plane, omx[0], omx[1], xphi, xtheta);
891 
892  double length = FindLineLength(clockData, detProp);
893  TGText* tt = new TGText(Form("Length:%4.1f", length));
894  tt->InsLine(1, Form("Omega P%d:%4.1f,", pline[0].plane, omx[0]));
895  tt->InsLine(2, Form("Omega P%d:%4.1f,", pline[1].plane, omx[1]));
896  tt->InsLine(3, Form("Phi: %4.1f,", xphi));
897 
898  tt->InsLine(4, Form("Theta: %4.1f", xtheta));
899  fAngleInfo->SetText(tt);
900  fAngleInfo->Update();
901  } // end else if
902  }
903 
904  //.......................................................................
906  {
908 
909  if (!evdlayoutopt->fMakeClusters)
910  ppoints.clear();
911  else {
912  if (this->pline.size() == 0) return;
913  for (size_t i = 0; i < fPlanes.size(); ++i) {
914  fPlanes[i]->ClearHitList();
915  fPlanes[i]->UpdatePad();
916  }
917  pline.clear();
918  }
919  }
920 
921  //.......................................................................
923  {
924  //*-*-*-*-*-*-*-*-*-*-*Create a new arrow in this pad*-*-*-*-*-*-*-*-*-*-*-*-*
925  //*-* ==============================
926 
927  TObject* select = gPad->GetSelected();
928  if (!select) return;
929  if (!select->InheritsFrom("TBox")) return;
930 
931  static Float_t w0 = -1, t0 = -1, w1 = -1, t1 = -1;
932 
933  static Int_t pxold, pyold;
934  static Int_t pw0, pt0;
935  static Int_t linedrawn;
936 
937  static int wstart, wend;
938  static float tstart, tend;
939 
940  int event = gPad->GetEvent();
941  int px = gPad->GetEventX();
942  int py = gPad->GetEventY();
943 
944  switch (event) {
945 
946  case kButton1Down: {
947  gVirtualX->SetLineColor(-1);
948  w0 = gPad->AbsPixeltoX(px);
949  t0 = gPad->AbsPixeltoY(py);
950  pw0 = px;
951  pt0 = py;
952  pxold = px;
953  pyold = py;
954  linedrawn = 0;
955  float x = gPad->PadtoX(w0);
956  tstart = gPad->PadtoY(t0);
957 
958  wstart = (unsigned int)TMath::Nint(x);
959  curr_zooming_plane = plane;
960  break;
961  }
962  case kButton1Motion: {
963  int lx, hx, ly, hy;
964  if (pw0 < pxold) {
965  lx = pw0;
966  hx = pxold;
967  }
968  else {
969  lx = pxold;
970  hx = pw0;
971  }
972 
973  if (pt0 < pyold) {
974  ly = pt0;
975  hy = pyold;
976  }
977  else {
978  ly = pyold;
979  hy = pt0;
980  }
981 
982  if (linedrawn) gVirtualX->DrawBox(lx, ly, hx, hy, TVirtualX::kHollow);
983  pxold = px;
984  pyold = py;
985  linedrawn = 1;
986 
987  if (pw0 < pxold) {
988  lx = pw0;
989  hx = pxold;
990  }
991  else {
992  lx = pxold;
993  hx = pw0;
994  }
995 
996  if (pt0 < pyold) {
997  ly = pt0;
998  hy = pyold;
999  }
1000  else {
1001  ly = pyold;
1002  hy = pt0;
1003  }
1004 
1005  gVirtualX->DrawBox(lx, ly, hx, hy, TVirtualX::kHollow);
1006  break;
1007  }
1008  case kButton1Up: {
1009  if (px == pw0 && py == pt0) break;
1010  w1 = gPad->AbsPixeltoX(px);
1011  t1 = gPad->AbsPixeltoY(py);
1012  gPad->Modified(kTRUE);
1013 
1014  float x = gPad->PadtoX(w1);
1015  tend = gPad->PadtoY(t1);
1016  wend = (unsigned int)TMath::Nint(x);
1017 
1018  gROOT->SetEditorMode();
1019 
1020  //make sure the box is significantly big to avoid accidental zooms on nothing.
1021  double xx1, yy1, xx2, yy2;
1022 
1023  gPad->GetRangeAxis(xx1, yy1, xx2, yy2);
1024 
1025  if (wstart != 0 && tstart != 0 && (std::abs(wend - wstart) > 0.01 * (xx2 - xx1)) &&
1026  (std::abs(tend - tstart) > 0.01 * (yy2 - yy1) && curr_zooming_plane == plane)) {
1027 
1028  SetAutomaticZoomMode(false);
1029  this->SetZoom(plane, wstart, wend, tstart, tend);
1030  wstart = -1;
1031  tstart = -1;
1032  }
1033  break;
1034  }
1035  } // end switch
1036  }
1037 
1038  //......................................................................
1040  {
1041  static Float_t w0 = -1, t0 = -1, w1 = -1, t1 = -1;
1042 
1043  static Int_t pxold, pyold;
1044  static Int_t pw0, pt0;
1045 
1046  static Int_t linedrawn;
1047 
1048  int event = gPad->GetEvent();
1049  int px = gPad->GetEventX();
1050  int py = gPad->GetEventY();
1051 
1052  int linefinished = 0;
1053 
1054  switch (event) {
1055 
1056  case kButton1Down: {
1057  //not doing anything right now
1058  w0 = gPad->AbsPixeltoX(px);
1059  t0 = gPad->AbsPixeltoY(py);
1060  pw0 = px;
1061  pt0 = py;
1062  pxold = px;
1063  pyold = py;
1064  linedrawn = 0;
1065  curr_zooming_plane = plane;
1066  break;
1067  }
1068 
1069  case kButton1Motion: {
1070  int lx, hx, ly, hy;
1071 
1072  // If we are in seed mode, and one seed line
1073  // was already placed, constrain head of next line
1074  // to be at same t0
1075 
1076  lx = pxold;
1077  hx = pw0;
1078 
1079  ly = pyold;
1080  hy = pt0;
1081 
1082  if (linedrawn) gVirtualX->DrawLine(lx, ly, hx, hy);
1083 
1084  pxold = px;
1085  pyold = py;
1086  linedrawn = 1;
1087 
1088  lx = pxold;
1089  hx = pw0;
1090 
1091  ly = pyold;
1092  hy = pt0;
1093 
1094  if (linedrawn) gVirtualX->DrawLine(lx, ly, hx, hy);
1095  break;
1096  }
1097 
1098  case kButton1Up: {
1099  if (px == pw0 && py == pt0) break;
1100  w1 = gPad->AbsPixeltoX(px);
1101  t1 = gPad->AbsPixeltoY(py);
1102 
1103  gPad->Modified(kTRUE);
1104 
1105  pline = util::PxLine(plane, w0, t0, w1, t1);
1106  linefinished = 1;
1107  }
1108  } //end switch
1109 
1110  return linefinished;
1111  }
1112 
1113  //.......................................................................
1115  {
1116 
1117  TObject* select = gPad->GetSelected();
1118  if (!select) return;
1119  if (!select->InheritsFrom("TBox")) return;
1120 
1121  util::PxLine ppx;
1122 
1123  if (!DrawLine(plane, ppx)) return;
1124 
1125  curr_zooming_plane = -1;
1126  gROOT->SetEditorMode();
1127 
1128  // check if not clicking on a plane that is already in the ppoints list:
1129  int repeat_plane = -1;
1130 
1131  for (size_t ii = 0; ii < this->pline.size(); ++ii) {
1132  if (ppx.plane == this->pline[ii].plane) {
1133  this->pline[ii] = ppx;
1134 
1135  //clear View and draw new Marker
1136  this->fPlanes[plane]->Pad()->cd();
1137  this->fPlanes[this->pline[ii].plane]->View()->Clear();
1138  this->fPlanes[this->pline[ii].plane]->View()->Draw();
1139  TLine& l = this->fPlanes[this->pline[ii].plane]->View()->AddLine(
1140  pline[ii].w0, pline[ii].t0, pline[ii].w1, pline[ii].t1);
1141  evd::Style::FromPDG(l, 11);
1142  this->fPlanes[this->pline[ii].plane]->View()->Draw();
1143  repeat_plane = this->pline[ii].plane;
1144  break;
1145  }
1146  }
1147 
1148  //if plane does not repeat and size of list is larger than 2 pop_front and delete its marker. Otherwise just push_back.
1149  if (repeat_plane == -1) {
1150  if (this->pline.size() >= 2) {
1151  this->fPlanes[this->pline[0].plane]->Pad()->cd();
1152  this->fPlanes[this->pline[0].plane]->View()->Clear();
1153  this->fPlanes[this->pline[0].plane]->View()->Draw();
1154  this->fPlanes[this->pline[0].plane]->Pad()->Clear();
1155  this->fPlanes[this->pline[0].plane]->Pad()->Draw();
1156  this->fPlanes[this->pline[0].plane]->Draw();
1157  this->fPlanes[this->pline[0].plane]->Pad()->Modified();
1158  this->fPlanes[this->pline[0].plane]->Pad()->Update();
1159  this->fPlanes[this->pline[0].plane]->Pad()->GetFrame()->SetBit(TPad::kCannotMove, true);
1160  this->fPlanes[this->pline[0].plane]->Pad()->SetBit(TPad::kCannotMove, true);
1161  this->pline.pop_front();
1162  }
1163 
1164  this->pline.push_back(ppx);
1165  this->fPlanes[plane]->Pad()->cd();
1166  this->fPlanes[plane]->View()->Clear();
1167  this->fPlanes[plane]->View()->Draw();
1168 
1169  int size = pline.size() - 1;
1170  TLine& l = this->fPlanes[this->pline[size].plane]->View()->AddLine(
1171  pline[size].w0, pline[size].t0, pline[size].w1, pline[size].t1);
1172  this->fPlanes[this->pline[size].plane]->View()->Draw();
1173  evd::Style::FromPDG(l, 11);
1174  }
1175  }
1176 
1177  //......................................................................
1179  {
1181  if (!recoopt->fUseHitSelector) return;
1182 
1183  //initial check for a mouse click on a TBox object
1184  int event = gPad->GetEvent();
1185 
1187  if (event != 7) return;
1188 
1190  if (evdlayoutopt->fMakeClusters != 1) return;
1191  //struct planepoint;
1192  int px = gPad->GetEventX();
1193  double w0 = gPad->AbsPixeltoX(px);
1194  double x = gPad->PadtoX(w0);
1195 
1196  int py = gPad->GetEventY();
1197  double t0 = gPad->AbsPixeltoY(py);
1198  double y = gPad->PadtoY(t0);
1199 
1200  fPlanes[plane]->SelectOneHit(x, y, zoom_opt);
1201  fPlanes[plane]->UpdatePad();
1202  return;
1203  }
1204 
1205  //......................................................................
1206  // if flag is true then zoom. If flag is false then unzoom.
1208  {
1209  mf::LogVerbatim("TWQProjectionView") << "ZoomInterest called";
1210 
1211  if (flag == true)
1212  zoom_opt = "1";
1213  else
1214  zoom_opt = "0";
1215 
1216  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout>()->Get();
1218 
1219  ZoomOptions zo;
1220  fPrevZoomOpt.push_back(fZoomOpt);
1221 
1222  for (size_t iplane = 0; iplane < fPlanes.size(); ++iplane) {
1223  int minw, maxw, mint, maxt;
1224  if (flag) {
1225  int test = 0;
1226  if (rawopt->fDrawRawDataOrCalibWires == 0)
1227  test =
1228  fPlanes[iplane]->RawDataDraw()->GetRegionOfInterest(iplane, minw, maxw, mint, maxt);
1229  else
1230  fPlanes[iplane]->RecoBaseDraw()->GetRegionOfInterest(iplane, minw, maxw, mint, maxt);
1231 
1232  if (test != 0) continue;
1233  }
1234  else {
1235  auto const num_wires = wireReadoutGeom.Nwires(geo::PlaneID(0, 0, iplane));
1236  minw = -0.005 * (num_wires - 1);
1237  maxw = 1.005 * (num_wires - 1);
1238  mint = -0.005 * fPlanes[iplane]->RawDataDraw()->TotalClockTicks();
1239  maxt = 1.01 * fPlanes[iplane]->RawDataDraw()->TotalClockTicks();
1240  }
1241 
1242  SetZoom(iplane, minw, maxw, mint, maxt, false);
1243  zo.wmin[iplane] = minw;
1244  zo.tmin[iplane] = mint;
1245  zo.wmax[iplane] = maxw;
1246  zo.tmax[iplane] = maxt;
1247  zo.OnlyPlaneChanged = -1;
1248  }
1249  fZoomOpt = zo;
1250  }
1251 
1252  //......................................................................
1254  {
1255  SetUpZoomButtons();
1260  }
1261 
1262  //......................................................................
1264  {
1266  evdlayoutopt->fAutoZoomInterest = fToggleAutoZoom->GetState();
1267  SetAutomaticZoomMode(evdlayoutopt->fAutoZoomInterest == 1);
1268  }
1269 
1270  //......................................................................
1272  {
1273  for (TWireProjPad* pPlane : fPlanes)
1274  pPlane->SetZoomFromView();
1275  }
1276 
1277  //......................................................................
1279  {
1281  evdlayoutopt->fMakeClusters = fToggleClusters->GetState();
1282  }
1283 
1284  //......................................................................
1286  {
1288  evdlayoutopt->fShowEndPointMarkers = fToggleShowMarkers->GetState();
1289  }
1290 
1291  //......................................................................
1293  {
1294  MF_LOG_DEBUG("TWQProjectionView") << "Explicit request for redrawing";
1295 
1296  // for now, bother only about redrawing the plane pads
1297  SetZoomFromView();
1298  DrawPads();
1299 
1300  } // TWQProjectionView::ForceRedraw()
1301 
1302  //......................................................................
1304  {
1305  // enter zoom buttons
1307 
1308  fZoomInterest = new TGTextButton(fVFrame, "&Zoom Interest", 150);
1309  fZoomInterest->Connect("Clicked()", "evd::TWQProjectionView", this, "ZoomInterest()");
1310 
1311  fUnZoomInterest = new TGTextButton(fVFrame, "&UnZoom Interest", 150);
1312  fUnZoomInterest->Connect("Clicked()", "evd::TWQProjectionView", this, "ZoomInterest(=false)");
1313 
1314  fZoomBack = new TGTextButton(fVFrame, "&Zoom Back", 150);
1315  fZoomBack->Connect("Clicked()", "evd::TWQProjectionView", this, "ZoomBack()");
1316 
1317  fToggleAutoZoom = new TGCheckButton(fVFrame, "AutoZoom", 0);
1318  fToggleAutoZoom->Connect("Clicked()", "evd::TWQProjectionView", this, "SetZoomInterest()");
1319  if (evdlayoutopt->fAutoZoomInterest == 1) fToggleAutoZoom->SetState(kButtonDown);
1320 
1321  fVFrame->AddFrame(fZoomInterest, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1322  fVFrame->AddFrame(fUnZoomInterest, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1323 
1324  fVFrame->AddFrame(fZoomBack, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1325 
1326  fVFrame->AddFrame(fToggleAutoZoom, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1327  }
1328 
1329  //......................................................................
1331  {
1333  if (!evdlayoutopt->fShowClusterSection) return;
1334  // enter zoom buttons
1335 
1336  fToggleZoom = new TGRadioButton(fVFrame, "Use Zoom", 2);
1337  fToggleClusters = new TGRadioButton(fVFrame, "Select Clusters", 3);
1338 
1339  fToggleZoom->Connect("Clicked()", "evd::TWQProjectionView", this, "RadioButtonsDispatch(=0)");
1340  fToggleClusters->Connect(
1341  "Clicked()", "evd::TWQProjectionView", this, "RadioButtonsDispatch(=1)");
1342 
1343  fCalcAngle = new TGTextButton(fVFrame, "&Save Selection", 150);
1344  fCalcAngle->Connect("Clicked()", "evd::TWQProjectionView", this, "SaveSelection()");
1345 
1346  fClear = new TGTextButton(fVFrame, "&Clear Selection", 0);
1347  fClear->Connect("Clicked()", "evd::TWQProjectionView", this, "ClearSelection()");
1348 
1349  if (evdlayoutopt->fMakeClusters == 1)
1350  fToggleClusters->SetState(kButtonDown);
1351  else
1352  fToggleZoom->SetState(kButtonDown);
1353 
1354  fAngleInfo = new TGTextView(
1355  fVFrame, 115, 75, 999, TGView::kNoHSB | TGView::kNoVSB);
1356  fAngleInfo->SetEditable("false");
1357  TGText* tt = new TGText("...");
1358  fAngleInfo->SetText(tt);
1359 
1360  fDistance = new TGNumberEntry(fVFrame,
1361  0,
1362  6,
1363  -1,
1364  TGNumberFormat::kNESReal,
1365  TGNumberFormat::kNEAPositive,
1366  TGNumberFormat::kNELLimitMinMax,
1367  0,
1368  100);
1369  // Initial value
1370  fDistance->SetNumber(1.5);
1371 
1372  // There are two "signals" to which a TGNumberEntry may respond:
1373  // when the user clicks on the arrows, or when the user types in a
1374  // new number in the text field.
1375  fDistance->Connect("ValueSet(Long_t)", "evd::TWQProjectionView", this, "SetDistance()");
1376  fDistance->GetNumberEntry()->Connect(
1377  "ReturnPressed()", "evd::TWQProjectionView", this, "SetDistance()");
1378 
1379  // Text label for this numeric field.
1380  fDistanceLabel = new TGLabel(fVFrame, "Distance");
1381 
1382  fVFrame->AddFrame(fToggleZoom, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1383  fVFrame->AddFrame(fToggleClusters, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1384 
1385  fVFrame->AddFrame(fCalcAngle, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1386  fVFrame->AddFrame(fClear, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1387 
1388  fVFrame->AddFrame(fDistance, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1389  fVFrame->AddFrame(fDistanceLabel, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1390 
1391  fVFrame->AddFrame(fAngleInfo, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1392 
1393  fVFrame->AddFrame(fDistance, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1394  }
1395 
1396  //......................................................................
1398  {
1399  fRedraw = new TGTextButton(fVFrame, "&Redraw", 120);
1400  fRedraw->Connect("Clicked()", "evd::TWQProjectionView", this, "ForceRedraw()");
1401 
1402  fVFrame->AddFrame(fRedraw, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1403  } // SetUpDrawingButtons()
1404 
1405  //......................................................................
1406  std::string TWQProjectionView::TotalElementsString(unsigned int NElements)
1407  {
1408  return "(" + std::to_string(NElements) + " total)";
1409  }
1410 
1412  {
1415 
1416  TGHorizontalFrame* pRow = nullptr;
1417  //
1418  // Cryostat selection line
1419  //
1420  // this is the subframe with horizontal alignment where we place our widgets:
1421  pRow = new TGHorizontalFrame(fVFrame, 216, 32, kHorizontalFrame);
1422 
1423  geo::CryostatID::CryostatID_t const CurrentCryo = rawOpt->fCryostat;
1424  unsigned int const NCryo = geom.Ncryostats();
1425  if (NCryo > 1) { // allow a selector
1426  unsigned int const NCryoDigits =
1427  std::to_string(NCryo - 1).length(); // a silly way fast to code...
1428 
1429  geo::CryostatID::CryostatID_t const CurrentCryo = rawOpt->fCryostat;
1430 
1431  // label
1432  TGLabel* pLabel = new TGLabel(pRow, "Cryo #");
1433  pLabel->SetTextJustify(kTextRight | kTextCenterY);
1434 
1435  // numerical input
1436  fCryoInput =
1437  new TGNumberEntry(pRow,
1438  (Double_t)CurrentCryo, // parent widget; starting value;
1439  NCryoDigits,
1440  -1, // number of digits for the input field; ID;
1441  TGNumberFormat::kNESInteger,
1442  TGNumberFormat::kNEAAnyNumber, // type of number; number attributes;
1443  TGNumberFormat::kNELLimitMinMax,
1444  -1,
1445  NCryo // limits
1446  );
1447 
1448  TGLabel* pTotalCryoLabel = new TGLabel(pRow, TotalElementsString(NCryo).c_str());
1449  pTotalCryoLabel->SetTextJustify(kTextLeft | kTextCenterY);
1450  // the numbers are padding on the four sides
1451  pRow->AddFrame(pLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1452  pRow->AddFrame(fCryoInput, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2));
1453  pRow->AddFrame(pTotalCryoLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1454 
1455  fCryoInput->Connect("ValueSet(Long_t)", "evd::TWQProjectionView", this, "SelectTPC()");
1456  }
1457  else { // just place a static label
1458  TGLabel* pLabel = new TGLabel(pRow, "Cryo #0 (1 total)");
1459  // the numbers are padding on the four sides
1460  pRow->AddFrame(pLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1461  }
1462 
1463  fVFrame->AddFrame(pRow, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2));
1464 
1465  //
1466  // TPC selection line
1467  //
1468  // this is the subframe with horizontal alignment where we place our widgets:
1469  pRow = new TGHorizontalFrame(fVFrame, 216, 32, kHorizontalFrame);
1470 
1471  unsigned int MaxTPC = geom.MaxTPCs();
1472  if (MaxTPC > 1) { // label, numeric input, then total
1473  unsigned int const NTPCDigits =
1474  std::to_string(MaxTPC - 1).length(); // a silly way fast to code...
1475 
1476  geo::TPCID::TPCID_t const CurrentTPC = rawOpt->fTPC;
1477  unsigned int const NTPCs = geom.NTPC(geo::CryostatID(CurrentCryo));
1478 
1479  // label
1480  TGLabel* pLabel = new TGLabel(pRow, "TPC #");
1481  pLabel->SetTextJustify(kTextRight | kTextCenterY);
1482 
1483  // numerical input
1484  fTPCInput =
1485  new TGNumberEntry(pRow,
1486  (Double_t)CurrentTPC, // parent widget; starting value;
1487  NTPCDigits,
1488  -1, // number of digits for the input field; ID;
1489  TGNumberFormat::kNESInteger,
1490  TGNumberFormat::kNEAAnyNumber, // type of number; number attributes;
1491  TGNumberFormat::kNELLimitMinMax,
1492  -1,
1493  MaxTPC // limits
1494  );
1495 
1496  fTotalTPCLabel = new TGLabel(pRow, TotalElementsString(NTPCs).c_str());
1497  fTotalTPCLabel->SetTextJustify(kTextRight | kTextCenterY);
1498  // the numbers are padding on the four sides
1499  pRow->AddFrame(pLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1500  pRow->AddFrame(fTPCInput, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2));
1501  pRow->AddFrame(fTotalTPCLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1502 
1503  fTPCInput->Connect("ValueSet(Long_t)", "evd::TWQProjectionView", this, "SelectTPC()");
1504  }
1505  else { // just place another static label
1506  TGLabel* pLabel = new TGLabel(pRow, "TPC #0 (1 total)");
1507  // the numbers are padding on the four sides
1508  pRow->AddFrame(pLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1509  }
1510 
1511  fVFrame->AddFrame(pRow, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2));
1512 
1513  } // TWQProjectionView::SetUpTPCselection()
1514 
1515  //----------------------------------------------------------------------------
1517  {
1518  /*
1519  * This function takes care of the input in the cryostat and TPC fields.
1520  * It is called whenever any of the two values (cryostat and TPC) change;
1521  * it can perform a number of tasks:
1522  * - first checks if the new input is valid
1523  * - if it's not, tries to wrap it to a valid TPC ID
1524  * - if it's not possible, goes back to the current TPC
1525  * - if the resulting TPC ID is different from the original one,
1526  * updates the content of the current TPC and cryostat in the service,
1527  * and asks for redrawing
1528  * - if the cryostat is changed, updates the TPC count
1529  * - if it changed the values of the TPC ID respect to what was in input
1530  * at the beginning, then updates the input fields
1531  *
1532  */
1535 
1536  geo::TPCID CurrentTPC(rawOpt.fCryostat, rawOpt.fTPC);
1537  geo::TPCID RequestedTPC(fCryoInput ? (unsigned int)fCryoInput->GetIntNumber() : 0U,
1538  fTPCInput ? (unsigned int)fTPCInput->GetIntNumber() : 0U);
1539  geo::TPCID NewTPC(RequestedTPC);
1540 
1541  // if the input ends up being invalid, try to fix it somehow;
1542  // we give a special meaning to negative values;
1543  // since they are not supported by the container we store them in
1544  // (that is, TPCID) we have to handle negative values as special case:
1545  if (fCryoInput && (fCryoInput->GetIntNumber() < 0)) {
1546  // wrap back to the last cryostat, last TPC
1547  NewTPC.Cryostat = (geo::CryostatID::CryostatID_t)(geom.Ncryostats() - 1);
1548  NewTPC.TPC = (geo::TPCID::TPCID_t)(geom.NTPC(NewTPC) - 1);
1549  }
1550  else if (fTPCInput && (fTPCInput->GetIntNumber() < 0)) {
1551  // wrap back to the previous cryostat, last TPC
1552  if (NewTPC.Cryostat-- == 0)
1553  NewTPC.Cryostat = (geo::CryostatID::CryostatID_t)(geom.Ncryostats() - 1);
1554  NewTPC.TPC = (geo::TPCID::TPCID_t)(geom.NTPC(NewTPC) - 1);
1555  }
1556  else if (!geom.HasTPC(NewTPC)) {
1557  // both elements are positive: it must be overflow
1558  unsigned int const NCryos = geom.Ncryostats();
1559  // what's wrong?
1560  if (NewTPC.Cryostat >= NCryos) { // cryostat wrap
1561  NewTPC.Cryostat = (geo::CryostatID::CryostatID_t)0;
1562  NewTPC.TPC = (geo::TPCID::TPCID_t)0;
1563  }
1564  else { // TPC wrap
1565  if (++NewTPC.Cryostat >= NCryos) NewTPC.Cryostat = (geo::CryostatID::CryostatID_t)0;
1566  NewTPC.TPC = (geo::TPCID::TPCID_t)0;
1567  }
1568 
1569  MF_LOG_DEBUG("TWQProjectionView") << __func__ << ": invalid TPC " << RequestedTPC
1570  << ", corrected as " << NewTPC << " instead";
1571  }
1572 
1573  if (!geom.HasTPC(NewTPC)) { // weird...
1574  MF_LOG_ERROR("TWQProjectionView") << __func__ << ": internal error: " << RequestedTPC
1575  << " turned into an invalid TPC " << NewTPC;
1576  }
1577  else if (NewTPC != CurrentTPC) { // do we need to change after all?
1578  MF_LOG_DEBUG("TWQProjectionView")
1579  << __func__ << ": switching from " << CurrentTPC << " to " << NewTPC;
1580 
1581  // new cryostat?
1582  if (rawOpt.fCryostat != NewTPC.Cryostat) { // update the TPC count
1583  unsigned int const NTPCs = geom.NTPC(NewTPC);
1584  fTotalTPCLabel->SetText(TotalElementsString(NTPCs).c_str());
1585  // fTotalTPCLabel->Modified();
1586  }
1587  // update the current TPC in the service
1588  // (that is the thing everything else refers to)
1589  rawOpt.fCryostat = NewTPC.Cryostat;
1590  rawOpt.fTPC = NewTPC.TPC;
1591 
1592  // redraw the content
1594  DrawPads();
1595  // evdb::Canvas::fCanvas->cd();
1596  // evdb::Canvas::fCanvas->Modified();
1597  // evdb::Canvas::fCanvas->Update();
1598  }
1599 
1600  // if we have changed the requested TPC, we need to update the input fields
1601  if (NewTPC != RequestedTPC) {
1602  if (fCryoInput) fCryoInput->SetIntNumber(NewTPC.Cryostat);
1603  if (fTPCInput) fTPCInput->SetIntNumber(NewTPC.TPC);
1604  }
1605 
1606  } // TWQProjectionView::SelectTPC()
1607 
1608  //----------------------------------------------------------------------------
1610  {
1612  if (parameter == 0) {
1613  evdlayoutopt->fMakeClusters = 0;
1614  fToggleClusters->SetState(kButtonUp);
1615  }
1616  else if (parameter == 1) {
1617  evdlayoutopt->fMakeClusters = 1;
1618  fToggleZoom->SetState(kButtonUp);
1619  }
1620  }
1621 
1622  //......................................................................
1624  {
1625  // enter zoom buttons
1627  if (!evdlayoutopt->fShowEndPointSection) return;
1628 
1629  // int fShowEndPointMarkers; ///< Draw EndPoint Markers if clicked.
1630 
1631  fFindEndpoint = new TGTextButton(fVFrame, "&Find XYZ", 150);
1632  fFindEndpoint->Connect("Clicked()", "evd::TWQProjectionView", this, "FindEndPoint()");
1633 
1634  fXYZPosition = new TGTextView(
1635  fVFrame, 100, 55, 999, TGView::kNoHSB | TGView::kNoVSB);
1636  fXYZPosition->SetEditable("false");
1637  TGText* tt = new TGText("x,y,z");
1638  fXYZPosition->SetText(tt);
1639 
1640  fClearPPoints = new TGTextButton(fVFrame, "&Clear Points", 150);
1641  fClearPPoints->Connect("Clicked()", "evd::TWQProjectionView", this, "ClearEndPoints()"); // ?
1642 
1644  new TGCheckButton(fVFrame, "ShowMarkers", 0);
1645  fToggleShowMarkers->Connect(
1646  "Clicked()", "evd::TWQProjectionView", this, "ToggleEndPointMarkers()");
1647  if (evdlayoutopt->fShowEndPointMarkers == 1) fToggleShowMarkers->SetState(kButtonDown);
1648 
1649  fVFrame->AddFrame(fFindEndpoint, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1650  fVFrame->AddFrame(fXYZPosition, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1651  fVFrame->AddFrame(fClearPPoints, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1652  fVFrame->AddFrame(fToggleShowMarkers, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1653  }
1654 
1656  // Go back one step in zoom
1657 
1659  {
1660  if (fPrevZoomOpt.size() > 0) {
1661  ZoomOptions ThePrevZoomOpt = fPrevZoomOpt.at(fPrevZoomOpt.size() - 1);
1662  int plane = fZoomOpt.OnlyPlaneChanged;
1663  if (plane != -1) {
1664  SetZoom(plane,
1665  ThePrevZoomOpt.wmin[plane],
1666  ThePrevZoomOpt.wmax[plane],
1667  ThePrevZoomOpt.tmin[plane],
1668  ThePrevZoomOpt.tmax[plane],
1669  false);
1670  }
1671  else {
1672  for (size_t iplane = 0; iplane != fPlanes.size(); ++iplane) {
1673  SetZoom(iplane,
1674  ThePrevZoomOpt.wmin[iplane],
1675  ThePrevZoomOpt.wmax[iplane],
1676  ThePrevZoomOpt.tmin[iplane],
1677  ThePrevZoomOpt.tmax[iplane],
1678  false);
1679  }
1680  }
1681 
1682  fPrevZoomOpt.pop_back();
1683  }
1684  else
1685  mf::LogVerbatim("TWQProjectionView")
1686  << "unable to unzoom further - no zoom settings left on stack" << std::endl;
1687  }
1688 
1689  //------------------------------------
1691  int wirelow,
1692  int wirehi,
1693  int timelow,
1694  int timehi,
1695  bool StoreZoom)
1696  {
1697 
1698  if (StoreZoom) {
1699  fPrevZoomOpt.push_back(fZoomOpt);
1700  fZoomOpt.OnlyPlaneChanged = plane;
1701  }
1702 
1703  fZoomOpt.wmin[plane] = wirelow;
1704  fZoomOpt.wmax[plane] = wirehi;
1705  fZoomOpt.tmin[plane] = timelow;
1706  fZoomOpt.tmax[plane] = timehi;
1707 
1708  TVirtualPad* ori = gPad;
1709  zoom_opt = "1";
1710 
1711  // error checking - useful for the mouse zoom.
1712  if (wirehi < wirelow) {
1713  int temp = wirelow;
1714  wirelow = wirehi;
1715  wirehi = temp;
1716  }
1717 
1718  if (timehi < timelow) {
1719  int temp = timelow;
1720  timelow = timehi;
1721  timehi = temp;
1722  }
1723 
1724  //if drawing, then currently not zooming
1725  curr_zooming_plane = -1;
1726 
1727  fPlanes[plane]->SetZoomRange(wirelow, wirehi, timelow, timehi);
1728  fPlanes[plane]->Draw("1");
1729  fPlanes[plane]->UpdatePad();
1730 
1731  evdb::Canvas::fCanvas->cd();
1732  evdb::Canvas::fCanvas->Modified();
1733  evdb::Canvas::fCanvas->Update();
1734 
1735  ori->cd();
1736 
1737  return;
1738  }
1739 
1740  //-----------------------------------------------------------------
1742  {
1743  TVirtualPad* ori = gPad;
1744 
1745  fWireQ->SetPlaneWire(kPlane, kWire);
1746 
1747  fWireQ->Draw();
1748  fWireQ->Pad()->cd();
1749  fWireQ->Pad()->Modified();
1750  fWireQ->Pad()->Update();
1751  fWireQ->Pad()->SetBit(TPad::kCannotMove, true);
1752  fWireQ->Pad()->GetFrame()->SetBit(TPad::kCannotMove, true);
1753 
1754  fPlaneEntry->SetNumber(kPlane);
1755  fWireEntry->SetNumber(kWire);
1756 
1757  evdb::Canvas::fCanvas->cd();
1758  evdb::Canvas::fCanvas->Modified();
1759  evdb::Canvas::fCanvas->Update();
1760 
1761  ori->cd();
1762  }
1763 
1764  //-----------------------------------------------------------------
1766  {
1767  kPlane = (unsigned int)fPlaneEntry->GetNumberEntry()->GetNumber();
1768 
1769  this->SetPlaneWire();
1770  }
1771 
1772  //-----------------------------------------------------------------
1774  {
1775  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout>()->Get();
1776  auto const num_wires = wireReadoutGeom.Nwires(geo::PlaneID(0, 0, kPlane));
1777  kWire = (num_wires - 1 > (unsigned int)fWireEntry->GetNumberEntry()->GetNumber()) ?
1778  (unsigned int)fWireEntry->GetNumberEntry()->GetNumber() :
1779  num_wires - 1;
1780 
1781  this->SetPlaneWire();
1782  }
1783 
1784  //-----------------------------------------------------------------
1786  {
1787  kDistance = (double)fDistance->GetNumberEntry()->GetNumber();
1788  }
1789 
1790  //-----------------------------------------------------------------
1792  {
1793  double threshold = fThresEntry->GetNumberEntry()->GetNumber();
1794 
1795  if (threshold != fLastThreshold) {
1797  rawopt->fMinSignal = threshold;
1798 
1799  TVirtualPad* ori = gPad;
1800  this->DrawPads(zoom_opt);
1801  evdb::Canvas::fCanvas->cd();
1802  evdb::Canvas::fCanvas->Modified();
1803  evdb::Canvas::fCanvas->Update();
1804 
1805  ori->cd();
1806  }
1807 
1808  fLastThreshold = threshold;
1809 
1810  return;
1811  }
1812 
1813  //-----------------------------------------------------------------
1815  {
1817 
1818  TGButton* b = (TGButton*)gTQSender;
1819  if (b->GetState() == kButtonDown) { cst->fColorOrGray = 1; }
1820  else {
1821  cst->fColorOrGray = 0;
1822  }
1823 
1824  TVirtualPad* ori = gPad;
1825  this->DrawPads(zoom_opt);
1826  evdb::Canvas::fCanvas->cd();
1827  evdb::Canvas::fCanvas->Modified();
1828  evdb::Canvas::fCanvas->Update();
1829 
1830  ori->cd();
1831 
1832  return;
1833  }
1834 
1835  //-----------------------------------------------------------------
1837  {
1839 
1840  TGButton* b = (TGButton*)gTQSender;
1841  int id = b->WidgetId();
1842 
1843  // id values are set in lines 125 - 127
1844  if (id == 4) {
1845  rawopt->fDrawRawDataOrCalibWires = 0;
1846  fRawDraw->SetState(kButtonDown);
1847  fCalibDraw->SetState(kButtonUp);
1848  fRawCalibDraw->SetState(kButtonUp);
1849  }
1850  else if (id == 3) {
1851  rawopt->fDrawRawDataOrCalibWires = 1;
1852  fRawDraw->SetState(kButtonUp);
1853  fCalibDraw->SetState(kButtonDown);
1854  fRawCalibDraw->SetState(kButtonUp);
1855  }
1856  else if (id == 2) {
1857  rawopt->fDrawRawDataOrCalibWires = 2;
1858  fRawDraw->SetState(kButtonUp);
1859  fCalibDraw->SetState(kButtonUp);
1860  fRawCalibDraw->SetState(kButtonDown);
1861  }
1862 
1863  TVirtualPad* ori = gPad;
1864 
1865  fWireQ->Draw();
1866  fWireQ->Pad()->cd();
1867  fWireQ->Pad()->Modified();
1868  fWireQ->Pad()->Update();
1869 
1870  this->DrawPads(zoom_opt);
1871  evdb::Canvas::fCanvas->cd();
1872  evdb::Canvas::fCanvas->Modified();
1873  evdb::Canvas::fCanvas->Update();
1874 
1875  ori->cd();
1876 
1877  return;
1878  }
1879 
1880  //-----------------------------------------------------------------
1882  {
1884 
1885  TGButton* b = (TGButton*)gTQSender;
1886  if (b->GetState() == kButtonDown) {
1887  sdo->fShowMCTruthText = 1;
1888  sdo->fShowMCTruthVectors = 1;
1889  }
1890  else {
1891  sdo->fShowMCTruthText = 0;
1892  sdo->fShowMCTruthVectors = 0;
1893  }
1894 
1895  TVirtualPad* ori = gPad;
1896 
1897  fMC->Draw();
1898  evdb::Canvas::fCanvas->cd();
1899  evdb::Canvas::fCanvas->Modified();
1900  evdb::Canvas::fCanvas->Update();
1901 
1902  ori->cd();
1903  }
1904 
1905  //-----------------------------------------------------------------
1907  {
1908 
1909  // first check if it's new...
1910  art::Event const* pEvent = evdb::EventHolder::Instance()->GetEvent();
1911  if (!pEvent) {
1912  if (!fLastEvent->isValid()) return false; // no event before, nor now
1913  fLastEvent->clear();
1914  return true;
1915  }
1916 
1917  // do we have a new event?
1918  if (!fLastEvent->update(
1919  {*pEvent, art::ServiceHandle<evd::RawDrawingOptions const>()->fRawDataLabels[0]}))
1920  return false;
1921 
1922  MF_LOG_DEBUG("TWQProjectionView") << "New event or product: " << *fLastEvent;
1923 
1925  SetAutomaticZoomMode(drawopt->fAutoZoomInterest == 1);
1926 
1927  return true; // yes, a new event is here
1928  } // TWQProjectionView::OnNewEvent()
1929 
1930  //-----------------------------------------------------------------
1931 
1932 } // namespace
Float_t x
Definition: compare.C:6
void SetTestFlag(int value)
Definition: InfoTransfer.h:55
std::vector< ZoomOptions > fPrevZoomOpt
TGNumberEntry * fCryoInput
current cryostat
code to link reconstructed objects back to the MC truth information
TGRadioButton * fToggleClusters
Use make cluster setting.
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
HeaderPad * fHeaderPad
Show header information.
std::deque< util::PxLine > pline
list of lines in each WireProjPad used for calculating 2d and 3d angles, also making seeds (eventuall...
const art::Event * GetEvent() const
Definition: EventHolder.cxx:45
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:26
Double_t xx
Definition: macro.C:12
int fEnableMCTruthCheckBox
1 to have the check box appear, 0 otherwise
unsigned int fTPC
TPC number to draw, typically set by TWQProjectionView.
TTree * t1
Definition: plottest35.C:26
void SetMouseZoomRegion(int plane)
static unsigned int kWire
int DrawLine(int plane, util::PxLine &pline)
void SetTestFlag(int number=1)
Drawing pad for short summary of an MC event.
TGTextButton * fCalcAngle
Calculate the 2D & 3D angles between lines.
Drawing pad showing a single X-Z or Y-Z projection of an event.
Display parameters for the raw data.
TGTextButton * fZoomBack
Unzoom on iteresting region.
int fDrawRawDataOrCalibWires
0 for raw
TGCompositeFrame * fFrame
Graphics frame.
Definition: Canvas.h:39
unsigned int NTPC(CryostatID const &cryoid=details::cryostat_zero) const
Returns the total number of TPCs in the specified cryostat.
Definition: GeometryCore.h:416
double fLastThreshold
Kludge to prevent double drawing when changing threshold.
Float_t y
Definition: compare.C:6
TGTextButton * fZoomInterest
Zoom on iteresting region.
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
void Draw(const char *opt=0)
Drawing pad for time or charge histograms.
bool isZoomAutomatic
true if user did not ask for custom zoom
double Temperature() const
In kelvin.
void ForceRedraw()
Forces a redraw of the window.
TGNumberEntry * fTPCInput
current TPC
constexpr auto abs(T v)
Returns the absolute value of the argument.
TGCheckButton * fToggleShowMarkers
Toggle the ShowEndPointMarkersSetting.
Classes detecting configuration changes.
#define MF_LOG_ERROR(category)
TQPad * fWireQ
Histogram of charge vs time on selected wire.
TGTextView * fXYZPosition
Display the xyz position.
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
Definition: AddMC.C:8
static unsigned int kPlane
TCanvas * fCanvas
The ROOT drawing canvas.
Definition: Canvas.h:42
A collection of drawable 2-D objects.
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:430
static void FromPDG(TLine &line, int pdgcode)
Definition: Style.cxx:131
int fMakeClusters
Draw two lines to make clusters if clicked.
void Draw()
Definition: TQPad.cxx:110
TGLayoutHints * fLayout
Layout hints for frame.
Definition: Canvas.h:40
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
Definition: GeometryCore.h:303
TGNumberEntry * fDistance
Distance from line to find hits in cluster.
Manage all things related to colors for the event display.
std::deque< util::PxPoint > ppoints
list of points in each WireProjPad used for x,y,z finding
TGTextButton * fFindEndpoint
Calculate XYZ position of two points in wire planes.
Singleton to hold the current art::Event for the event display.
TGRadioButton * fRawCalibDraw
Draw raw and calibrated information.
std::vector< TQPad * > fPlaneQ
charge on each plane
void SetAutomaticZoomMode(bool bSet=true)
Records whether we are automatically zooming to the region of interest.
static double kDistance
double Efield(unsigned int planegap=0) const
kV/cm
std::map< int, double > wmin
int fShowEndPointSection
Show section corresponding to EndPoint finding.
std::vector< double > const & GetCurrentZoom() const
Definition: TWireProjPad.h:83
The color scales used by the event display.
TWQProjectionView(TGMainFrame *mf)
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
Drawing pad for time or charge histograms.
int fShowClusterSection
Show section to make clusters.
Access the description of the physical detector geometry.
Definition: type_traits.h:61
TGCheckButton * fToggleAutoZoom
Toggle the autozoom setting.
TGCompositeFrame * fMetaFrame
needed for the side frame
TGTextButton * fClear
Clears the selected points in an event.
TGTextButton * fClearPPoints
Clear current list of End Points.
int fShowSideBar
1 to show, 0 don&#39;t show
TGRadioButton * fToggleZoom
Use zoom setting.
LArSoft includes.
unsigned short fXsize
Size of the canvas;.
Definition: Canvas.h:44
A drawing pad for time vs wire.
Definition: TWireProjPad.h:27
void ResetRegionsOfInterest()
Clear all the regions of interest.
int fAutoZoomInterest
Set the automatic zoom to the interest region.
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
TGLabel * fTotalTPCLabel
total TPCs in the current cryostat
unsigned int fCryostat
Cryostat number to draw, typically set by TWQProjectionView.
static EventHolder * Instance()
Definition: EventHolder.cxx:15
double t
Definition: PxUtils.h:10
static int curr_zooming_plane
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:67
int fShowEndPointMarkers
Draw EndPoint Markers if clicked.
double fMinSignal
minimum ADC count to display a time bin
TGTextButton * fRedraw
Button to force redraw.
TPad * Pad()
Definition: DrawingPad.h:30
geo::TPCID CurrentTPC() const
Returns the current TPC as a TPCID.
TGCompositeFrame * fVFrame
needed for the side frame
static int shift_lock
void Draw(const char *opt="")
TGNumberEntry * fThresEntry
ADC threshold to display.
double FindLineLength(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp)
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
void SelectTPC()
select TPC from GUI
The data type to uniquely identify a TPC.
Definition: geo_types.h:306
Description of the physical geometry of one entire detector.
Definition: GeometryCore.h:91
bool OnNewEvent()
Returns if a new event is detected; if so, it also resets accordingly.
Class to aid in the rendering of RecoBase objects.
void DrawPads(const char *opt="")
TGRadioButton * fCalibDraw
Draw calibrated information only.
std::map< int, double > wmax
Class to aid in the rendering of RawData objects.
void ZoomInterest(bool flag=true)
double w
Definition: PxUtils.h:9
unsigned short fYsize
Size of the canvas;.
Definition: Canvas.h:45
void Draw(const char *opt="")
Definition: HeaderPad.cxx:47
TGRadioButton * fRawDraw
Draw Raw information only.
TGTextButton * fUnZoomInterest
Unzoom on iteresting region.
void RadioButtonsDispatch(int parameter)
TGNumberEntry * fPlaneEntry
Plane number displayed.
unsigned int CryostatID_t
Type for the ID number.
Definition: geo_types.h:188
unsigned int TPCID_t
Type for the ID number.
Definition: geo_types.h:307
Encapsulate the construction of a single detector plane .
int fChangeWire
1 to click mouse and change wire, 0 don&#39;t
Contains all timing reference information for the detector.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
static std::string TotalElementsString(unsigned int NElements)
Returns a string visualizing the total number of elements.
void clear()
Set a new event and data product label as current.
#define MF_LOG_DEBUG(id)
int fColorOrGray
0 = color, 1 = gray
static void MouseDispatch(int plane, void *wqpv)
TGCheckButton * fMCOn
Display MC truth information.
int trigger_offset(DetectorClocksData const &data)
Definition: MVAAlg.h:12
static const char * zoom_opt
int fPrintTotalCharge
Print out the total charge in an event.
void SetZoom(int plane, int wirelow, int wirehi, int timelo, int timehi, bool StoreZoom=true)
MCBriefPad * fMC
Short summary of MC event.
unsigned int plane
Definition: PxUtils.h:68
A view showing the time vs wire, charge and charge vs time information for an event.
std::vector< TWireProjPad * > fPlanes
time vs wire projection for each plane
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
bool update(DataProductChangeTracker_t const &new_prod)
Update to a new data product, return true if it has changed.
TGCheckButton * fGreyScale
Display gray or color scale.
std::map< int, double > tmin
Point3DBase_t< PlaneGeoCoordinatesTag > LocalPoint_t
Type of points in the local GDML wire plane frame.
Definition: PlaneGeo.h:94
util::DataProductChangeTracker_t * fLastEvent
keeps track of latest event
TRootEmbeddedCanvas * fEmbCanvas
Embedded canvas.
Definition: Canvas.h:41
unsigned int MaxTPCs() const
Returns the largest number of TPCs a cryostat in the detector has.
bool HasTPC(TPCID const &tpcid) const
Returns whether we have the specified TPC.
Definition: GeometryCore.h:429
TGNumberEntry * fWireEntry
Wire number displayed.
bool isValid() const
Returns whether there is a current event and data product.
art framework interface to geometry description
unsigned int plane
Definition: PxUtils.h:11
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:229
Event finding and building.
The data type to uniquely identify a cryostat.
Definition: geo_types.h:187
Signal from collection planes.
Definition: geo_types.h:148
std::map< int, double > tmax
void SetPlaneWire(unsigned int plane=0, unsigned int wire=0)
Definition: TQPad.h:40