LArSoft  v09_90_00
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 
26 #include "lareventdisplay/EventDisplay/ChangeTrackers.h" // util::DataProductChangeTracker_t
43 
47 
48 namespace evd {
49 
50  static unsigned int kPlane;
51  static unsigned int kWire;
52  static double kDistance;
53  static int curr_zooming_plane;
54  static const char* zoom_opt = 0;
55 
56  static int shift_lock;
57 
58  //......................................................................
60  : evdb::Canvas(mf)
61  , fRedraw(nullptr)
62  , fCryoInput(nullptr)
63  , fTPCInput(nullptr)
64  , fTotalTPCLabel(nullptr)
65  , isZoomAutomatic(art::ServiceHandle<evd::EvdLayoutOptions const>()->fAutoZoomInterest)
66  , fLastEvent(new util::DataProductChangeTracker_t)
67  {
68 
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  geo->Nplanes() - 1);
124 
125  kPlane = 0;
126  constexpr geo::TPCID tpcid{0, 0};
127  kWire = TMath::Nint(0.5 * geo->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 : geo->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  geo->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 = geo->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("mousedispatch",Form("evd::TWQProjectionView::MouseDispatch(%d, (void*)%d)", i, this));
274  fPlanes[i]->Pad()->AddExec(
275  "mousedispatch",
276  Form("evd::TWQProjectionView::MouseDispatch(%d, (void*)%lu)", i, (unsigned long)this));
277 
278  padname = "fQPadPlane";
279  padname += i;
280 
281  padtitle = "QPlane";
282  padtitle += i;
283 
284  evdb::Canvas::fCanvas->cd();
285  fPlaneQ.push_back(new TQPad(padname, padtitle, twx2, twy1, twx3, twy2, "Q", i, 0));
286  fPlaneQ[i]->Draw();
287  }
288 
289  // propagate the zoom setting
291 
292  evdb::Canvas::fCanvas->Update();
293  }
294 
295  //......................................................................
297  {
298  if (fHeaderPad) {
299  delete fHeaderPad;
300  fHeaderPad = 0;
301  }
302  if (fMC) {
303  delete fMC;
304  fMC = 0;
305  }
306  if (fWireQ) {
307  delete fWireQ;
308  fWireQ = 0;
309  }
310  if (fPlaneEntry) {
311  delete fPlaneEntry;
312  fPlaneEntry = 0;
313  }
314  if (fWireEntry) {
315  delete fWireEntry;
316  fWireEntry = 0;
317  }
318  if (fPlaneLabel) {
319  delete fPlaneLabel;
320  fPlaneLabel = 0;
321  }
322  if (fWireLabel) {
323  delete fWireLabel;
324  fWireLabel = 0;
325  }
326  for (unsigned int i = 0; i < fPlanes.size(); ++i) {
327  if (fPlanes[i]) {
328  delete fPlanes[i];
329  fPlanes[i] = 0;
330  }
331  if (fPlaneQ[i]) {
332  delete fPlaneQ[i];
333  fPlaneQ[i] = 0;
334  }
335  }
336  fPlanes.clear();
337  fPlaneQ.clear();
338 
339  delete fLastEvent;
340  }
341 
342  //......................................................................
344  {
345  for (TWireProjPad* planePad : fPlanes)
346  planePad->RawDataDraw()->ResetRegionOfInterest();
347  } // TWQProjectionView::ResetRegionsOfInterest()
348 
349  //......................................................................
350  void TWQProjectionView::DrawPads(const char* /*opt*/)
351  {
352 
353  OnNewEvent(); // if the current event is a new one, we need some resetting
354 
355  for (unsigned int i = 0; i < fPlanes.size(); ++i) {
356  fPlanes[i]->Draw();
357  fPlanes[i]->Pad()->Update();
358  fPlanes[i]->Pad()->GetFrame()->SetBit(TPad::kCannotMove, true);
359  }
360  for (unsigned int j = 0; j < fPlaneQ.size(); ++j) {
361  fPlaneQ[j]->Draw();
362  fPlaneQ[j]->Pad()->Update();
363  fPlaneQ[j]->Pad()->GetFrame()->SetBit(TPad::kCannotMove, true);
364  }
365  }
366 
367  //......................................................................
368  void TWQProjectionView::SetAutomaticZoomMode(bool bSet /* = true */)
369  {
370  isZoomAutomatic = bSet;
371  for (TWireProjPad* pPlane : fPlanes)
372  pPlane->SetZoomToRoI(isZoomAutomatic);
373  } // TWQProjectionView::SetAutomaticZoomMode()
374 
375  //......................................................................
376  void TWQProjectionView::Draw(const char* opt)
377  {
378  mf::LogDebug("TWQProjectionView") << "Starting to draw";
379 
380  OnNewEvent(); // if the current event is a new one, we need some resetting
381 
383 
384  fPrevZoomOpt.clear();
385 
386  evdb::Canvas::fCanvas->cd();
387  zoom_opt = 0;
388  fHeaderPad->Draw();
389  fMC->Draw();
390  fWireQ->Draw();
391 
393  if (evdlayoutopt->fPrintTotalCharge) PrintCharge();
394 
395  //clear queue of selected points
396  ppoints.clear();
397  pline.clear();
398  // Reset current zooming plane - since it's not currently zooming.
399  curr_zooming_plane = -1;
400 
401  unsigned int const nPlanes = fPlanes.size();
402  MF_LOG_DEBUG("TWQProjectionView") << "Start drawing " << nPlanes << " planes";
403  // double Charge=0, ConvCharge=0;
404  for (unsigned int i = 0; i < nPlanes; ++i) {
405  TWireProjPad* planePad = fPlanes[i];
406  planePad->Draw(opt);
407  planePad->Pad()->Update();
408  planePad->Pad()->GetFrame()->SetBit(TPad::kCannotMove, true);
409  fPlaneQ[i]->Draw();
410  std::vector<double> ZoomParams = planePad->GetCurrentZoom();
411  fZoomOpt.wmin[i] = ZoomParams[0];
412  fZoomOpt.wmax[i] = ZoomParams[1];
413  fZoomOpt.tmin[i] = ZoomParams[2];
414  fZoomOpt.tmax[i] = ZoomParams[3];
415  // Charge deposit feature - not working yet
416  //
417  // if(geo->Plane(i).SignalType()==geo::kCollection)
418  // {
419  // planePad->RecoBaseDraw()->GetChargeSum(i,Charge,ConvCharge);
420  // }
421  }
422  mf::LogDebug("TWQProjectionView") << "Done drawing " << nPlanes << " planes";
423 
424  // Charge deposit feature - not working yet
425  // std::stringstream ss;
426  // if(ConvCharge!=0)
427  // {
428  // ss << ConvCharge << "MeV"<<std::endl;
429  // }
430  // else
431  // {
432  // ss<<" no reco info";
433  // }
434  //
435  // TGText * tt = new TGText(ss.str().c_str());
436  // tt->InsLine(1, "Approx EDep:");
437  // fAngleInfo->SetText(tt);
438  //
439  // ss.flush();
440  //
441 
442  // Reset any text boxes which are enabled
443 
444  if (fXYZPosition) fXYZPosition->SetForegroundColor(kBlack);
445 
446  if (fAngleInfo) fAngleInfo->SetForegroundColor(kBlack);
447 
448  evdb::Canvas::fCanvas->Update();
449  mf::LogDebug("TWQProjectionView") << "Done drawing";
450  }
451 
452  // comment out this method as for now we don't want to change every
453  // plane to have the same range in wire number because wire numbers
454  // don't necessarily overlap from plane to plane, ie the same range
455  // isn't appropriate for every plane
456  //......................................................................
457  // void TWQProjectionView::RangeChanged()
458  // {
459  // static int ilolast = -1;
460  // static int ihilast = -1;
461  //
462  // int ilo;
463  // int ihi;
464  // std::vector<int> lo;
465  // std::vector<int> hi;
466  // std::vector<bool> axischanged;
467  // for(unsigned int i = 0; i < fPlanes.size(); ++i){
468  // fPlanes[i]->GetWireRange(&ilo, &ihi);
469  // lo.push_back(ilo);
470  // hi.push_back(ihi);
471  // axischanged.push_back((ilo != ilolast) || (ihi != ihilast));
472  // }
473  //
474  // TVirtualPad* ori = gPad;
475  //
476  // // loop over the bools to see which axes need to change
477  // for(unsigned int i = 0; i < axischanged.size(); ++i){
478  // if (axischanged[i]) {
479  // fPlanes[i]->SetWireRange(ilo, ihi);
480  // fPlanes[i]->Pad()->cd();
481  // fPlanes[i]->Pad()->Modified();
482  // fPlanes[i]->Pad()->Update();
483  //
484  // ilolast = ilo;
485  // ihilast = ihi;
486  // }
487  // }
488  //
489  // evdb::Canvas::fCanvas->cd();
490  // evdb::Canvas::fCanvas->Modified();
491  // evdb::Canvas::fCanvas->Update();
492  // ori->cd();
493  // }
494  //......................................................................
495 
496  //......................................................................
498  {
500  infot->SetTestFlag(number);
501  }
502 
503  //......................................................................
505  {
506 
509 
510  for (size_t iplane = 0; iplane < fPlanes.size(); ++iplane) {
511  geo::PlaneID planeid(rawopt->CurrentTPC(), iplane);
512  if (geo->SignalType(planeid) != geo::kCollection) continue;
513 
514  double ch = 0, convch = 0;
515  if (rawopt->fDrawRawDataOrCalibWires == 0) {
516  fPlanes[iplane]->RawDataDraw()->GetChargeSum(iplane, ch, convch);
517  mf::LogVerbatim("TWQProjectionView") << "Warning! Calculating for RawData! ";
518  }
519  else {
520  fPlanes[iplane]->RecoBaseDraw()->GetChargeSum(iplane, ch, convch);
521  }
522 
523  mf::LogVerbatim("TWQProjectionView")
524  << "\ncharge collected at collection plane: " << iplane << " " << ch << " " << convch;
525  } // for
526  }
527 
528  //-------------------------------------------------------------------
529  //......................................................................
530  void TWQProjectionView::MouseDispatch(int plane, void* wqpv)
531  {
532  //initial check for a mouse click on a TBox object
533  int event = gPad->GetEvent();
536 
537  switch (event) {
538 
539  case kButton1Shift:
540  shift_lock = 1;
541  if (evdlayoutopt->fMakeClusters == 1) { wqpp->SelectHit(plane); }
542  else {
543  wqpp->SelectPoint(plane);
544  }
545  break;
546  case kButton1Up:
547  if (shift_lock == 1) break;
548  if (evdlayoutopt->fChangeWire == 1) wqpp->ChangeWire(plane);
549  case kButton1Down: shift_lock = 0;
550  case kButton1Motion:
551  if (evdlayoutopt->fMakeClusters == 1) { wqpp->SetClusters(plane); }
552  else {
553  wqpp->SetMouseZoomRegion(plane);
554  }
555  break;
556  // default:
557  }
558  }
559 
560  //......................................................................
562  {
563  //initial check for a mouse click on a TBox object
564  int event = gPad->GetEvent();
565  int px = gPad->GetEventX();
566  if (event != 11) return;
567  TObject* select = gPad->GetSelected();
568  if (!select) return;
569  if (!select->InheritsFrom("TBox")) return;
570 
571  //now find wire that was clicked on
572  float xx = gPad->AbsPixeltoX(px);
573  float x = gPad->PadtoX(xx);
574 
575  kPlane = plane;
576  kWire = (unsigned int)TMath::Nint(x);
577 
578  this->SetPlaneWire();
579 
580  return;
581  }
582 
583  //......................................................................
585  {
586  //initial check for a mouse click on a TBox object
587  int event = gPad->GetEvent();
588 
589  if (event != 7) return;
590 
592  if (evdlayoutopt->fShowEndPointSection != 1) return;
593  //struct planepoint;
594  int px = gPad->GetEventX();
595  double w0 = gPad->AbsPixeltoX(px);
596  double x = gPad->PadtoX(w0);
597 
598  int py = gPad->GetEventY();
599  double t0 = gPad->AbsPixeltoY(py);
600  double y = gPad->PadtoY(t0);
601 
602  util::PxPoint ppx(plane, x, y);
603  curr_zooming_plane = -1;
604 
605  // check if not clicking on a plane that is already in the ppoints list:
606  int repeat_plane = -1;
607  for (size_t ii = 0; ii < this->ppoints.size(); ++ii)
608  if (ppx.plane == this->ppoints[ii].plane) {
609  this->ppoints[ii] = ppx;
610  //clear View and draw new Marker
611  this->fPlanes[this->ppoints[ii].plane]->View()->Clear();
612  if (evdlayoutopt->fShowEndPointMarkers)
613  this->fPlanes[this->ppoints[ii].plane]->View()->AddMarker(ppx.w, ppx.t, kRed, 29, 2.0);
614  else
615  this->fPlanes[plane]->View()->AddMarker(0.0, 0.0, 2, 1, 0.1);
616  this->fPlanes[this->ppoints[ii].plane]->View()->Draw();
617  repeat_plane = this->ppoints[ii].plane;
618  break;
619  }
620 
621  //if plane does not repeat and size of list is larger than 2 pop_front
622  // and delete its marker. Otherwise just push_back.
623  if (repeat_plane == -1) {
624  if (this->ppoints.size() >= 2) {
625  this->fPlanes[this->ppoints[0].plane]->Pad()->cd();
626  this->fPlanes[this->ppoints[0].plane]->View()->Clear();
627  this->fPlanes[this->ppoints[0].plane]->View()->Draw();
628  this->ppoints.pop_front();
629  }
630  this->ppoints.push_back(ppx);
631  this->fPlanes[plane]->Pad()->cd();
632  this->fPlanes[plane]->View()->Clear();
633  if (evdlayoutopt->fShowEndPointMarkers)
634  this->fPlanes[plane]->View()->AddMarker(ppx.w, ppx.t, kRed, 29, 2.0);
635  else
636  this->fPlanes[plane]->View()->AddMarker(0.0, 0.0, 2, 1, 0.1);
637  this->fPlanes[plane]->View()->Draw();
638  }
639 
640  return;
641  }
642 
643  //......................................................................
645  {
646  for (size_t x = 0; x < fPlanes.size(); ++x) {
647  fPlanes[x]->Pad()->cd();
648  fPlanes[x]->View()->Clear();
649  fPlanes[x]->View()->AddMarker(0.0, 0.0, 2, 1, 0.1);
650  fPlanes[x]->Pad()->Update();
651  fPlanes[x]->View()->Draw();
652  }
653  ppoints.clear();
654  gPad->Modified();
655  gPad->Update();
656  gPad->cd();
657  }
658 
659  //......................................................................
661  detinfo::DetectorPropertiesData const& detProp)
662  {
663  // if list is larger than or equal to two, can project to XYZ and extrapolate to third plane (if exists)
664 
665  if (pline.size() >= 2) {
666 
667  double xyz_vertex_fit[3];
668  double second_time;
669  double xx0 = 0., yy0 = 0., zz0 = 0.;
670  double xx1 = 0., yy1 = 0., zz1 = 0.;
671  double length;
672 
673  double y, z;
674 
677  double ftimetick = sampling_rate(clockData) / 1000.;
678  double larv = detProp.DriftVelocity(detProp.Efield(), detProp.Temperature());
679 
680  //find wireIDs corresponding to found wires.
681  geo::WireID wire1(rawOpt->fCryostat, rawOpt->fTPC, pline[0].plane, pline[0].w0);
682  geo::WireID wire2(rawOpt->fCryostat, rawOpt->fTPC, pline[1].plane, pline[1].w0);
683 
684  bool wires_cross = false;
685  bool time_good = false;
686 
687  if (std::abs(pline[0].t0 - pline[1].t0) < 200) {
688  geo::WireIDIntersection widIntersect;
689  wires_cross = geom->WireIDsIntersect(wire1, wire2, widIntersect);
690  y = widIntersect.y;
691  z = widIntersect.z;
692  time_good = true;
693  }
694  else {
695  TGText* tt = new TGText("too big");
696  tt->InsLine(1, "time distance");
697  fXYZPosition->SetText(tt);
698  fXYZPosition->Update();
699  }
700 
701  constexpr geo::TPCID tpcid{0, 0};
702  if (wires_cross) {
703  TGText* tt = new TGText("wires cross");
704  fXYZPosition->SetText(tt);
705  fXYZPosition->Update();
706  xyz_vertex_fit[1] = y;
707  xyz_vertex_fit[2] = z;
708  auto pos = geom->Plane(geo::PlaneID(tpcid, pline[0].plane)).GetBoxCenter();
709  xyz_vertex_fit[0] = (pline[0].t0 - trigger_offset(clockData)) * larv * ftimetick + pos.X();
710  pos = geom->Plane(geo::PlaneID(tpcid, pline[1].plane)).GetBoxCenter();
711  second_time = (pline[1].t0 - trigger_offset(clockData)) * larv * ftimetick + pos.X();
712 
713  xx0 = (xyz_vertex_fit[0] + second_time) / 2;
714  yy0 = y;
715  zz0 = z;
716 
718  }
719  else {
720  if (time_good) { //otherwise the wires_cross are false by default
721  TGText* tt = new TGText("cross");
722  tt->InsLine(1, "wires do not");
723  fXYZPosition->SetText(tt);
724  fXYZPosition->Update();
725  }
726  }
727  //find wireIDs corresponding to found wires AT END OF LINE.
728  wire1.Wire = pline[0].w1;
729  wire2.Wire = pline[1].w1;
730 
731  wires_cross = false;
732  time_good = false;
733 
734  if (std::abs(pline[0].t1 - pline[1].t1) < 200) {
735  geo::WireIDIntersection widIntersect;
736  wires_cross = geom->WireIDsIntersect(wire1, wire2, widIntersect);
737  y = widIntersect.y;
738  z = widIntersect.z;
739  time_good = true;
740  }
741  else {
742  TGText* tt = new TGText("too big");
743  tt->InsLine(1, "time distance");
744  fXYZPosition->SetText(tt);
745  fXYZPosition->Update();
746  // return; //not returning, because may need to delete marker from wplane
747  }
748 
749  if (wires_cross) {
750  TGText* tt = new TGText("wires do cross");
751  fXYZPosition->SetText(tt);
752  fXYZPosition->Update();
753  xyz_vertex_fit[1] = y;
754  xyz_vertex_fit[2] = z;
755  auto pos = geom->Plane(geo::PlaneID(tpcid, pline[0].plane)).GetBoxCenter();
756  xyz_vertex_fit[0] = (pline[0].t1 - trigger_offset(clockData)) * larv * ftimetick + pos.X();
757  pos = geom->Plane(geo::PlaneID(tpcid, pline[1].plane)).GetBoxCenter();
758  second_time = (pline[1].t1 - trigger_offset(clockData)) * larv * ftimetick + pos.X();
759 
760  xx1 = (xyz_vertex_fit[0] + second_time) / 2;
761  yy1 = y;
762  zz1 = z;
763  }
764  else {
765  if (time_good) { //otherwise the wires_cross are false by default
766  TGText* tt = new TGText("cross");
767  tt->InsLine(1, "wires do not");
768  fXYZPosition->SetText(tt);
769  fXYZPosition->Update();
770  }
771  // return; //not returning, because may need to delete marker from wplanereturn;
772  }
773  //update pad?
774  gPad->Modified();
775  gPad->Update();
776  gPad->cd();
777 
778  length = pow(xx0 - xx1, 2) + pow(yy0 - yy1, 2) + pow(zz0 - zz1, 2);
779  length = pow(length, 0.5);
780  return length;
781  } // end if( this->ppoints.size()>=2)
782 
783  else {
784  TGText* tt = new TGText("selected points");
785  tt->InsLine(1, "not enough");
786  fXYZPosition->SetText(tt);
787  fXYZPosition->Update();
788  }
789 
790  return -99;
791  }
792 
793  //......................................................................
795  {
796  art::Event const* pEvent = evdb::EventHolder::Instance()->GetEvent();
797  if (not pEvent) {
798  std::cerr << "No event available\n";
799  return;
800  }
801 
802  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService>()->DataFor(*pEvent);
803 
804  // if list is larger than or equal to two, can project to XYZ and extrapolate to third plane (if exists)
805 
806  if (ppoints.size() >= 2) {
807 
808  double xyz_vertex_fit[3] = {0.};
809  double second_time = 0.;
810  geo::PlaneGeo::LocalPoint_t const origin{0., 0., 0.};
811  double y = 0.;
812  double z = 0.;
813 
816 
817  //find channels corresponding to found wires.
818  geo::WireID wire1(rawOpt->fCryostat, rawOpt->fTPC, ppoints[0].plane, ppoints[0].w);
819  geo::WireID wire2(rawOpt->fCryostat, rawOpt->fTPC, ppoints[1].plane, ppoints[1].w);
820 
821  bool wires_cross = false;
822  bool time_good = false;
823 
824  if (std::abs(ppoints[0].t - ppoints[1].t) < 200) {
825  geo::WireIDIntersection widIntersect;
826  geom->WireIDsIntersect(wire1, wire2, widIntersect);
827  y = widIntersect.y;
828  z = widIntersect.z;
829  wires_cross = true;
830  time_good = true;
831  }
832  else {
833  TGText* tt = new TGText("too big");
834  tt->InsLine(1, "time distance");
835  fXYZPosition->SetText(tt);
836  fXYZPosition->Update();
837  }
838 
839  if (wires_cross) {
840  xyz_vertex_fit[1] = y;
841  xyz_vertex_fit[2] = z;
842 
843  xyz_vertex_fit[0] =
844  detProp.ConvertTicksToX(ppoints[0].t, ppoints[0].plane, rawOpt->fTPC, rawOpt->fCryostat);
845  second_time =
846  detProp.ConvertTicksToX(ppoints[1].t, ppoints[1].plane, rawOpt->fTPC, rawOpt->fCryostat);
847 
848  TGText* tt = new TGText(Form("z:%4.1f", z));
849  tt->InsLine(1, Form("x:%4.1f,", (xyz_vertex_fit[0] + second_time) / 2));
850  tt->InsLine(1, Form("y:%4.1f,", y));
851  fXYZPosition->SetText(tt);
852  fXYZPosition->Update();
854  }
855  else {
856  if (time_good) { //otherwise the wires_cross are false by default
857  TGText* tt = new TGText("cross");
858  tt->InsLine(1, "wires do not");
859  fXYZPosition->SetText(tt);
860  fXYZPosition->Update();
861  }
862  // return; //not returning, because may need to delete marker from wplanereturn;
863  }
864  // extrapolate third point only if there are enough planes
865  if (fPlanes.size() > 2) {
866 
867  unsigned int wplane = 0;
868  unsigned int wirevertex = 0;
870 
871  for (size_t xx = 0; xx < fPlanes.size(); ++xx) {
872  wplane = 0;
873  for (int yy = 0; yy < 2; ++yy)
874  if (ppoints[yy].plane == xx) ++wplane;
875 
876  if (!wplane) {
877  wplane = xx;
878  break;
879  }
880  }
881 
882  geo::PlaneID const planeID{rawOpt->fCryostat, rawOpt->fTPC, wplane};
883  auto pos = geom->Plane(planeID).toWorldCoords(origin);
884  pos.SetY(xyz_vertex_fit[1]);
885  pos.SetZ(xyz_vertex_fit[2]);
886 
887  wirevertex = geom->NearestWireID(pos, planeID).Wire;
888 
889  double timestart = detProp.ConvertXToTicks(xyz_vertex_fit[0], planeID);
890 
891  fPlanes[wplane]->Pad()->cd();
892  fPlanes[wplane]->View()->Clear();
893  if (wires_cross && evdlayoutopt->fShowEndPointMarkers) //only Draw if it makes sense
894  fPlanes[wplane]->View()->AddMarker(wirevertex, timestart, kMagenta, 29, 2.0);
895  else //draw dummy marker to delete old one
896  fPlanes[wplane]->View()->AddMarker(0.0, 0.0, 2, 1, 0.1);
897  fPlanes[wplane]->Pad()->Update();
898  fPlanes[wplane]->View()->Draw();
899  } // end if(fPlanes.size()>2)
900  //update pad?
901  gPad->Modified();
902  gPad->Update();
903  gPad->cd();
904  } // end if( this->ppoints.size()>=2)
905  else {
906  TGText* tt = new TGText("selected points");
907  tt->InsLine(1, "not enough");
908  fXYZPosition->SetText(tt);
909  fXYZPosition->Update();
910  }
911  }
912 
913  //......................................................................
914  // SaveSelection
916  {
917  art::Event const* pEvent = evdb::EventHolder::Instance()->GetEvent();
918  if (not pEvent) {
919  std::cerr << "No event available\n";
920  return;
921  }
922 
924  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService>()->DataFor(*pEvent);
925  auto const detProp =
926  art::ServiceHandle<detinfo::DetectorPropertiesService>()->DataFor(*pEvent, clockData);
927  util::GeometryUtilities const gser{*geom, clockData, detProp};
928 
930  if (evdlayoutoptions->fMakeClusters) {
931  //only calculating in 3 planes now, needs to be generalized eventually
932  double omx[3];
933  double xphi;
934  double xtheta;
935  unsigned int ii;
936  if (pline.size() < 2) {
937  TGText* tt = new TGText("not enough lines selected");
938  fAngleInfo->SetText(tt);
939  fAngleInfo->Update();
940  return;
941  }
942  double deltawire;
943  double deltatime;
944  for (ii = 0; ii < pline.size(); ++ii) {
945  deltawire = pline[ii].w1 - pline[ii].w0;
946  deltatime = pline[ii].t1 - pline[ii].t0;
947  omx[ii] = gser.Get2Dangle(deltawire, deltatime);
948  }
949 
950  for (size_t ii = 0; ii < pline.size(); ++ii) {
951  fPlanes[pline[ii].plane]->SaveHitList(
952  pline[ii].w0, pline[ii].t0, pline[ii].w1, pline[ii].t1, kDistance, zoom_opt);
953  }
954  if (fPlanes.size() > pline.size() && pline.size() >= 2) { // need to project to third plane
955 
956  util::PxPoint p00(pline[0].plane, pline[0].w0, pline[0].t0);
957  util::PxPoint p01(pline[1].plane, pline[1].w0, pline[1].t0);
958  util::PxPoint p0N(0, 0, 0);
959  int error1 = gser.GetProjectedPoint(&p00, &p01, p0N);
960 
961  util::PxPoint p10(pline[0].plane, pline[0].w1, pline[0].t1);
962  util::PxPoint p11(pline[1].plane, pline[1].w1, pline[1].t1);
963  util::PxPoint p1N(0, 0, 0);
964  int error2 = gser.GetProjectedPoint(&p10, &p11, p1N);
965  if (error1 != -1 && error2 != -1)
966  fPlanes[p0N.plane]->SaveHitList(p0N.w, p0N.t, p1N.w, p1N.t, kDistance, zoom_opt, false);
967  }
968 
969  for (size_t jj = 0; jj < fPlanes.size(); ++jj) {
970  fPlanes[jj]->UpdatePad();
971  }
972 
973  gser.Get3DaxisN(pline[0].plane, pline[1].plane, omx[0], omx[1], xphi, xtheta);
974 
975  double length = FindLineLength(clockData, detProp);
976  TGText* tt = new TGText(Form("Length:%4.1f", length));
977  tt->InsLine(1, Form("Omega P%d:%4.1f,", pline[0].plane, omx[0]));
978  tt->InsLine(2, Form("Omega P%d:%4.1f,", pline[1].plane, omx[1]));
979  tt->InsLine(3, Form("Phi: %4.1f,", xphi));
980 
981  tt->InsLine(4, Form("Theta: %4.1f", xtheta));
982  fAngleInfo->SetText(tt);
983  fAngleInfo->Update();
984  } // end else if
985  }
986 
987  //.......................................................................
989  {
991 
992  if (!evdlayoutopt->fMakeClusters)
993  ppoints.clear();
994  else {
995  if (this->pline.size() == 0) return;
996  for (size_t i = 0; i < fPlanes.size(); ++i) {
997  fPlanes[i]->ClearHitList();
998  fPlanes[i]->UpdatePad();
999  }
1000  pline.clear();
1001  }
1002  }
1003 
1004  //.......................................................................
1006  {
1007  //*-*-*-*-*-*-*-*-*-*-*Create a new arrow in this pad*-*-*-*-*-*-*-*-*-*-*-*-*
1008  //*-* ==============================
1009 
1010  TObject* select = gPad->GetSelected();
1011  if (!select) return;
1012  if (!select->InheritsFrom("TBox")) return;
1013 
1014  static Float_t w0 = -1, t0 = -1, w1 = -1, t1 = -1;
1015 
1016  static Int_t pxold, pyold;
1017  static Int_t pw0, pt0;
1018  static Int_t linedrawn;
1019 
1020  static int wstart, wend;
1021  static float tstart, tend;
1022 
1023  int event = gPad->GetEvent();
1024  int px = gPad->GetEventX();
1025  int py = gPad->GetEventY();
1026 
1027  switch (event) {
1028 
1029  case kButton1Down: {
1030  gVirtualX->SetLineColor(-1);
1031  w0 = gPad->AbsPixeltoX(px);
1032  t0 = gPad->AbsPixeltoY(py);
1033  pw0 = px;
1034  pt0 = py;
1035  pxold = px;
1036  pyold = py;
1037  linedrawn = 0;
1038  float x = gPad->PadtoX(w0);
1039  tstart = gPad->PadtoY(t0);
1040 
1041  wstart = (unsigned int)TMath::Nint(x);
1042  curr_zooming_plane = plane;
1043  break;
1044  }
1045  case kButton1Motion: {
1046  int lx, hx, ly, hy;
1047  if (pw0 < pxold) {
1048  lx = pw0;
1049  hx = pxold;
1050  }
1051  else {
1052  lx = pxold;
1053  hx = pw0;
1054  }
1055 
1056  if (pt0 < pyold) {
1057  ly = pt0;
1058  hy = pyold;
1059  }
1060  else {
1061  ly = pyold;
1062  hy = pt0;
1063  }
1064 
1065  if (linedrawn) gVirtualX->DrawBox(lx, ly, hx, hy, TVirtualX::kHollow);
1066  pxold = px;
1067  pyold = py;
1068  linedrawn = 1;
1069 
1070  if (pw0 < pxold) {
1071  lx = pw0;
1072  hx = pxold;
1073  }
1074  else {
1075  lx = pxold;
1076  hx = pw0;
1077  }
1078 
1079  if (pt0 < pyold) {
1080  ly = pt0;
1081  hy = pyold;
1082  }
1083  else {
1084  ly = pyold;
1085  hy = pt0;
1086  }
1087 
1088  gVirtualX->DrawBox(lx, ly, hx, hy, TVirtualX::kHollow);
1089  break;
1090  }
1091  case kButton1Up: {
1092  if (px == pw0 && py == pt0) break;
1093  w1 = gPad->AbsPixeltoX(px);
1094  t1 = gPad->AbsPixeltoY(py);
1095  gPad->Modified(kTRUE);
1096 
1097  float x = gPad->PadtoX(w1);
1098  tend = gPad->PadtoY(t1);
1099  wend = (unsigned int)TMath::Nint(x);
1100 
1101  gROOT->SetEditorMode();
1102 
1103  //make sure the box is significantly big to avoid accidental zooms on nothing.
1104  double xx1, yy1, xx2, yy2;
1105 
1106  gPad->GetRangeAxis(xx1, yy1, xx2, yy2);
1107 
1108  if (wstart != 0 && tstart != 0 && (std::abs(wend - wstart) > 0.01 * (xx2 - xx1)) &&
1109  (std::abs(tend - tstart) > 0.01 * (yy2 - yy1) && curr_zooming_plane == plane)) {
1110 
1111  SetAutomaticZoomMode(false);
1112  this->SetZoom(plane, wstart, wend, tstart, tend);
1113  wstart = -1;
1114  tstart = -1;
1115  }
1116  break;
1117  }
1118  } // end switch
1119  }
1120 
1121  //......................................................................
1123  {
1124  static Float_t w0 = -1, t0 = -1, w1 = -1, t1 = -1;
1125 
1126  static Int_t pxold, pyold;
1127  static Int_t pw0, pt0;
1128 
1129  static Int_t linedrawn;
1130 
1131  int event = gPad->GetEvent();
1132  int px = gPad->GetEventX();
1133  int py = gPad->GetEventY();
1134 
1135  int linefinished = 0;
1136 
1137  switch (event) {
1138 
1139  case kButton1Down: {
1140  //not doing anything right now
1141  w0 = gPad->AbsPixeltoX(px);
1142  t0 = gPad->AbsPixeltoY(py);
1143  pw0 = px;
1144  pt0 = py;
1145  pxold = px;
1146  pyold = py;
1147  linedrawn = 0;
1148  curr_zooming_plane = plane;
1149  break;
1150  }
1151 
1152  case kButton1Motion: {
1153  int lx, hx, ly, hy;
1154 
1155  // If we are in seed mode, and one seed line
1156  // was already placed, constrain head of next line
1157  // to be at same t0
1158 
1159  lx = pxold;
1160  hx = pw0;
1161 
1162  ly = pyold;
1163  hy = pt0;
1164 
1165  if (linedrawn) gVirtualX->DrawLine(lx, ly, hx, hy);
1166 
1167  pxold = px;
1168  pyold = py;
1169  linedrawn = 1;
1170 
1171  lx = pxold;
1172  hx = pw0;
1173 
1174  ly = pyold;
1175  hy = pt0;
1176 
1177  if (linedrawn) gVirtualX->DrawLine(lx, ly, hx, hy);
1178  break;
1179  }
1180 
1181  case kButton1Up: {
1182  if (px == pw0 && py == pt0) break;
1183  w1 = gPad->AbsPixeltoX(px);
1184  t1 = gPad->AbsPixeltoY(py);
1185 
1186  gPad->Modified(kTRUE);
1187 
1188  pline = util::PxLine(plane, w0, t0, w1, t1);
1189  linefinished = 1;
1190  }
1191  } //end switch
1192 
1193  return linefinished;
1194  }
1195 
1196  //.......................................................................
1198  {
1199 
1200  TObject* select = gPad->GetSelected();
1201  if (!select) return;
1202  if (!select->InheritsFrom("TBox")) return;
1203 
1204  util::PxLine ppx;
1205 
1206  if (!DrawLine(plane, ppx)) return;
1207 
1208  curr_zooming_plane = -1;
1209  gROOT->SetEditorMode();
1210 
1211  // check if not clicking on a plane that is already in the ppoints list:
1212  int repeat_plane = -1;
1213 
1214  for (size_t ii = 0; ii < this->pline.size(); ++ii) {
1215  if (ppx.plane == this->pline[ii].plane) {
1216  this->pline[ii] = ppx;
1217 
1218  //clear View and draw new Marker
1219  this->fPlanes[plane]->Pad()->cd();
1220  this->fPlanes[this->pline[ii].plane]->View()->Clear();
1221  this->fPlanes[this->pline[ii].plane]->View()->Draw();
1222  TLine& l = this->fPlanes[this->pline[ii].plane]->View()->AddLine(
1223  pline[ii].w0, pline[ii].t0, pline[ii].w1, pline[ii].t1);
1224  evd::Style::FromPDG(l, 11);
1225  this->fPlanes[this->pline[ii].plane]->View()->Draw();
1226  repeat_plane = this->pline[ii].plane;
1227  break;
1228  }
1229  }
1230 
1231  //if plane does not repeat and size of list is larger than 2 pop_front and delete its marker. Otherwise just push_back.
1232  if (repeat_plane == -1) {
1233  if (this->pline.size() >= 2) {
1234  this->fPlanes[this->pline[0].plane]->Pad()->cd();
1235  this->fPlanes[this->pline[0].plane]->View()->Clear();
1236  this->fPlanes[this->pline[0].plane]->View()->Draw();
1237  this->fPlanes[this->pline[0].plane]->Pad()->Clear();
1238  this->fPlanes[this->pline[0].plane]->Pad()->Draw();
1239  this->fPlanes[this->pline[0].plane]->Draw();
1240  this->fPlanes[this->pline[0].plane]->Pad()->Modified();
1241  this->fPlanes[this->pline[0].plane]->Pad()->Update();
1242  this->fPlanes[this->pline[0].plane]->Pad()->GetFrame()->SetBit(TPad::kCannotMove, true);
1243  this->fPlanes[this->pline[0].plane]->Pad()->SetBit(TPad::kCannotMove, true);
1244  this->pline.pop_front();
1245  }
1246 
1247  this->pline.push_back(ppx);
1248  this->fPlanes[plane]->Pad()->cd();
1249  this->fPlanes[plane]->View()->Clear();
1250  this->fPlanes[plane]->View()->Draw();
1251 
1252  int size = pline.size() - 1;
1253  TLine& l = this->fPlanes[this->pline[size].plane]->View()->AddLine(
1254  pline[size].w0, pline[size].t0, pline[size].w1, pline[size].t1);
1255  this->fPlanes[this->pline[size].plane]->View()->Draw();
1256  evd::Style::FromPDG(l, 11);
1257  }
1258  }
1259 
1260  //......................................................................
1262  {
1264  if (!recoopt->fUseHitSelector) return;
1265 
1266  //initial check for a mouse click on a TBox object
1267  int event = gPad->GetEvent();
1268 
1270  if (event != 7) return;
1271 
1273  if (evdlayoutopt->fMakeClusters != 1) return;
1274  //struct planepoint;
1275  int px = gPad->GetEventX();
1276  double w0 = gPad->AbsPixeltoX(px);
1277  double x = gPad->PadtoX(w0);
1278 
1279  int py = gPad->GetEventY();
1280  double t0 = gPad->AbsPixeltoY(py);
1281  double y = gPad->PadtoY(t0);
1282 
1283  fPlanes[plane]->SelectOneHit(x, y, zoom_opt);
1284  fPlanes[plane]->UpdatePad();
1285  return;
1286  }
1287 
1288  //......................................................................
1289  // if flag is true then zoom. If flag is false then unzoom.
1291  {
1292  mf::LogVerbatim("TWQProjectionView") << "ZoomInterest called";
1293 
1294  if (flag == true)
1295  zoom_opt = "1";
1296  else
1297  zoom_opt = "0";
1298 
1301 
1302  ZoomOptions zo;
1303  fPrevZoomOpt.push_back(fZoomOpt);
1304 
1305  for (size_t iplane = 0; iplane < fPlanes.size(); ++iplane) {
1306  int minw, maxw, mint, maxt;
1307  if (flag) {
1308  int test = 0;
1309  if (rawopt->fDrawRawDataOrCalibWires == 0)
1310  test =
1311  fPlanes[iplane]->RawDataDraw()->GetRegionOfInterest(iplane, minw, maxw, mint, maxt);
1312  else
1313  fPlanes[iplane]->RecoBaseDraw()->GetRegionOfInterest(iplane, minw, maxw, mint, maxt);
1314 
1315  if (test != 0) continue;
1316  }
1317  else {
1318  auto const num_wires = geo->Nwires(geo::PlaneID(0, 0, iplane));
1319  minw = -0.005 * (num_wires - 1);
1320  maxw = 1.005 * (num_wires - 1);
1321  mint = -0.005 * fPlanes[iplane]->RawDataDraw()->TotalClockTicks();
1322  maxt = 1.01 * fPlanes[iplane]->RawDataDraw()->TotalClockTicks();
1323  }
1324 
1325  SetZoom(iplane, minw, maxw, mint, maxt, false);
1326  zo.wmin[iplane] = minw;
1327  zo.tmin[iplane] = mint;
1328  zo.wmax[iplane] = maxw;
1329  zo.tmax[iplane] = maxt;
1330  zo.OnlyPlaneChanged = -1;
1331  }
1332  fZoomOpt = zo;
1333  }
1334 
1335  //......................................................................
1337  {
1338  SetUpZoomButtons();
1343  }
1344 
1345  //......................................................................
1347  {
1349  evdlayoutopt->fAutoZoomInterest = fToggleAutoZoom->GetState();
1350  SetAutomaticZoomMode(evdlayoutopt->fAutoZoomInterest == 1);
1351  }
1352 
1353  //......................................................................
1355  {
1356  for (TWireProjPad* pPlane : fPlanes)
1357  pPlane->SetZoomFromView();
1358  }
1359 
1360  //......................................................................
1362  {
1364  evdlayoutopt->fMakeClusters = fToggleClusters->GetState();
1365  }
1366 
1367  //......................................................................
1369  {
1371  evdlayoutopt->fShowEndPointMarkers = fToggleShowMarkers->GetState();
1372  }
1373 
1374  //......................................................................
1376  {
1377  MF_LOG_DEBUG("TWQProjectionView") << "Explicit request for redrawing";
1378 
1379  // for now, bother only about redrawing the plane pads
1380  SetZoomFromView();
1381  DrawPads();
1382 
1383  } // TWQProjectionView::ForceRedraw()
1384 
1385  //......................................................................
1387  {
1388  // enter zoom buttons
1390 
1391  fZoomInterest = new TGTextButton(fVFrame, "&Zoom Interest", 150);
1392  fZoomInterest->Connect("Clicked()", "evd::TWQProjectionView", this, "ZoomInterest()");
1393 
1394  fUnZoomInterest = new TGTextButton(fVFrame, "&UnZoom Interest", 150);
1395  fUnZoomInterest->Connect("Clicked()", "evd::TWQProjectionView", this, "ZoomInterest(=false)");
1396 
1397  fZoomBack = new TGTextButton(fVFrame, "&Zoom Back", 150);
1398  fZoomBack->Connect("Clicked()", "evd::TWQProjectionView", this, "ZoomBack()");
1399 
1400  fToggleAutoZoom = new TGCheckButton(fVFrame, "AutoZoom", 0);
1401  fToggleAutoZoom->Connect("Clicked()", "evd::TWQProjectionView", this, "SetZoomInterest()");
1402  if (evdlayoutopt->fAutoZoomInterest == 1) fToggleAutoZoom->SetState(kButtonDown);
1403 
1404  fVFrame->AddFrame(fZoomInterest, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1405  fVFrame->AddFrame(fUnZoomInterest, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1406 
1407  fVFrame->AddFrame(fZoomBack, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1408 
1409  fVFrame->AddFrame(fToggleAutoZoom, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1410  }
1411 
1412  //......................................................................
1414  {
1416  if (!evdlayoutopt->fShowClusterSection) return;
1417  // enter zoom buttons
1418 
1419  fToggleZoom = new TGRadioButton(fVFrame, "Use Zoom", 2);
1420  fToggleClusters = new TGRadioButton(fVFrame, "Select Clusters", 3);
1421 
1422  fToggleZoom->Connect("Clicked()", "evd::TWQProjectionView", this, "RadioButtonsDispatch(=0)");
1423  fToggleClusters->Connect(
1424  "Clicked()", "evd::TWQProjectionView", this, "RadioButtonsDispatch(=1)");
1425 
1426  fCalcAngle = new TGTextButton(fVFrame, "&Save Selection", 150);
1427  fCalcAngle->Connect("Clicked()", "evd::TWQProjectionView", this, "SaveSelection()");
1428 
1429  fClear = new TGTextButton(fVFrame, "&Clear Selection", 0);
1430  fClear->Connect("Clicked()", "evd::TWQProjectionView", this, "ClearSelection()");
1431 
1432  if (evdlayoutopt->fMakeClusters == 1)
1433  fToggleClusters->SetState(kButtonDown);
1434  else
1435  fToggleZoom->SetState(kButtonDown);
1436 
1437  fAngleInfo = new TGTextView(
1438  fVFrame, 115, 75, 999, TGView::kNoHSB | TGView::kNoVSB);
1439  fAngleInfo->SetEditable("false");
1440  TGText* tt = new TGText("...");
1441  fAngleInfo->SetText(tt);
1442 
1443  fDistance = new TGNumberEntry(fVFrame,
1444  0,
1445  6,
1446  -1,
1447  TGNumberFormat::kNESReal,
1448  TGNumberFormat::kNEAPositive,
1449  TGNumberFormat::kNELLimitMinMax,
1450  0,
1451  100);
1452  // Initial value
1453  fDistance->SetNumber(1.5);
1454 
1455  // There are two "signals" to which a TGNumberEntry may respond:
1456  // when the user clicks on the arrows, or when the user types in a
1457  // new number in the text field.
1458  fDistance->Connect("ValueSet(Long_t)", "evd::TWQProjectionView", this, "SetDistance()");
1459  fDistance->GetNumberEntry()->Connect(
1460  "ReturnPressed()", "evd::TWQProjectionView", this, "SetDistance()");
1461 
1462  // Text label for this numeric field.
1463  fDistanceLabel = new TGLabel(fVFrame, "Distance");
1464 
1465  fVFrame->AddFrame(fToggleZoom, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1466  fVFrame->AddFrame(fToggleClusters, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1467 
1468  fVFrame->AddFrame(fCalcAngle, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1469  fVFrame->AddFrame(fClear, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1470 
1471  fVFrame->AddFrame(fDistance, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1472  fVFrame->AddFrame(fDistanceLabel, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1473 
1474  fVFrame->AddFrame(fAngleInfo, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1475 
1476  fVFrame->AddFrame(fDistance, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1477  }
1478 
1479  //......................................................................
1481  {
1482  fRedraw = new TGTextButton(fVFrame, "&Redraw", 120);
1483  fRedraw->Connect("Clicked()", "evd::TWQProjectionView", this, "ForceRedraw()");
1484 
1485  fVFrame->AddFrame(fRedraw, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1486  } // SetUpDrawingButtons()
1487 
1488  //......................................................................
1489  std::string TWQProjectionView::TotalElementsString(unsigned int NElements)
1490  {
1491  return "(" + std::to_string(NElements) + " total)";
1492  }
1493 
1495  {
1498 
1499  TGHorizontalFrame* pRow = nullptr;
1500  //
1501  // Cryostat selection line
1502  //
1503  // this is the subframe with horizontal alignment where we place our widgets:
1504  pRow = new TGHorizontalFrame(fVFrame, 216, 32, kHorizontalFrame);
1505 
1506  geo::CryostatID::CryostatID_t const CurrentCryo = rawOpt->fCryostat;
1507  unsigned int const NCryo = geom.Ncryostats();
1508  if (NCryo > 1) { // allow a selector
1509  unsigned int const NCryoDigits =
1510  std::to_string(NCryo - 1).length(); // a silly way fast to code...
1511 
1512  geo::CryostatID::CryostatID_t const CurrentCryo = rawOpt->fCryostat;
1513 
1514  // label
1515  TGLabel* pLabel = new TGLabel(pRow, "Cryo #");
1516  pLabel->SetTextJustify(kTextRight | kTextCenterY);
1517 
1518  // numerical input
1519  fCryoInput =
1520  new TGNumberEntry(pRow,
1521  (Double_t)CurrentCryo, // parent widget; starting value;
1522  NCryoDigits,
1523  -1, // number of digits for the input field; ID;
1524  TGNumberFormat::kNESInteger,
1525  TGNumberFormat::kNEAAnyNumber, // type of number; number attributes;
1526  TGNumberFormat::kNELLimitMinMax,
1527  -1,
1528  NCryo // limits
1529  );
1530 
1531  TGLabel* pTotalCryoLabel = new TGLabel(pRow, TotalElementsString(NCryo).c_str());
1532  pTotalCryoLabel->SetTextJustify(kTextLeft | kTextCenterY);
1533  // the numbers are padding on the four sides
1534  pRow->AddFrame(pLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1535  pRow->AddFrame(fCryoInput, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2));
1536  pRow->AddFrame(pTotalCryoLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1537 
1538  fCryoInput->Connect("ValueSet(Long_t)", "evd::TWQProjectionView", this, "SelectTPC()");
1539  }
1540  else { // just place a static label
1541  TGLabel* pLabel = new TGLabel(pRow, "Cryo #0 (1 total)");
1542  // the numbers are padding on the four sides
1543  pRow->AddFrame(pLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1544  }
1545 
1546  fVFrame->AddFrame(pRow, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2));
1547 
1548  //
1549  // TPC selection line
1550  //
1551  // this is the subframe with horizontal alignment where we place our widgets:
1552  pRow = new TGHorizontalFrame(fVFrame, 216, 32, kHorizontalFrame);
1553 
1554  unsigned int MaxTPC = geom.MaxTPCs();
1555  if (MaxTPC > 1) { // label, numeric input, then total
1556  unsigned int const NTPCDigits =
1557  std::to_string(MaxTPC - 1).length(); // a silly way fast to code...
1558 
1559  geo::TPCID::TPCID_t const CurrentTPC = rawOpt->fTPC;
1560  unsigned int const NTPCs = geom.NTPC(geo::CryostatID(CurrentCryo));
1561 
1562  // label
1563  TGLabel* pLabel = new TGLabel(pRow, "TPC #");
1564  pLabel->SetTextJustify(kTextRight | kTextCenterY);
1565 
1566  // numerical input
1567  fTPCInput =
1568  new TGNumberEntry(pRow,
1569  (Double_t)CurrentTPC, // parent widget; starting value;
1570  NTPCDigits,
1571  -1, // number of digits for the input field; ID;
1572  TGNumberFormat::kNESInteger,
1573  TGNumberFormat::kNEAAnyNumber, // type of number; number attributes;
1574  TGNumberFormat::kNELLimitMinMax,
1575  -1,
1576  MaxTPC // limits
1577  );
1578 
1579  fTotalTPCLabel = new TGLabel(pRow, TotalElementsString(NTPCs).c_str());
1580  fTotalTPCLabel->SetTextJustify(kTextRight | kTextCenterY);
1581  // the numbers are padding on the four sides
1582  pRow->AddFrame(pLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1583  pRow->AddFrame(fTPCInput, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2));
1584  pRow->AddFrame(fTotalTPCLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1585 
1586  fTPCInput->Connect("ValueSet(Long_t)", "evd::TWQProjectionView", this, "SelectTPC()");
1587  }
1588  else { // just place another static label
1589  TGLabel* pLabel = new TGLabel(pRow, "TPC #0 (1 total)");
1590  // the numbers are padding on the four sides
1591  pRow->AddFrame(pLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 5, 5));
1592  }
1593 
1594  fVFrame->AddFrame(pRow, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2));
1595 
1596  } // TWQProjectionView::SetUpTPCselection()
1597 
1598  //----------------------------------------------------------------------------
1600  {
1601  /*
1602  * This function takes care of the input in the cryostat and TPC fields.
1603  * It is called whenever any of the two values (cryostat and TPC) change;
1604  * it can perform a number of tasks:
1605  * - first checks if the new input is valid
1606  * - if it's not, tries to wrap it to a valid TPC ID
1607  * - if it's not possible, goes back to the current TPC
1608  * - if the resulting TPC ID is different from the original one,
1609  * updates the content of the current TPC and cryostat in the service,
1610  * and asks for redrawing
1611  * - if the cryostat is changed, updates the TPC count
1612  * - if it changed the values of the TPC ID respect to what was in input
1613  * at the beginning, then updates the input fields
1614  *
1615  */
1618 
1619  geo::TPCID CurrentTPC(rawOpt.fCryostat, rawOpt.fTPC);
1620  geo::TPCID RequestedTPC(fCryoInput ? (unsigned int)fCryoInput->GetIntNumber() : 0U,
1621  fTPCInput ? (unsigned int)fTPCInput->GetIntNumber() : 0U);
1622  geo::TPCID NewTPC(RequestedTPC);
1623 
1624  // if the input ends up being invalid, try to fix it somehow;
1625  // we give a special meaning to negative values;
1626  // since they are not supported by the container we store them in
1627  // (that is, TPCID) we have to handle negative values as special case:
1628  if (fCryoInput && (fCryoInput->GetIntNumber() < 0)) {
1629  // wrap back to the last cryostat, last TPC
1630  NewTPC.Cryostat = (geo::CryostatID::CryostatID_t)(geom.Ncryostats() - 1);
1631  NewTPC.TPC = (geo::TPCID::TPCID_t)(geom.NTPC(NewTPC) - 1);
1632  }
1633  else if (fTPCInput && (fTPCInput->GetIntNumber() < 0)) {
1634  // wrap back to the previous cryostat, last TPC
1635  if (NewTPC.Cryostat-- == 0)
1636  NewTPC.Cryostat = (geo::CryostatID::CryostatID_t)(geom.Ncryostats() - 1);
1637  NewTPC.TPC = (geo::TPCID::TPCID_t)(geom.NTPC(NewTPC) - 1);
1638  }
1639  else if (!geom.HasTPC(NewTPC)) {
1640  // both elements are positive: it must be overflow
1641  unsigned int const NCryos = geom.Ncryostats();
1642  // what's wrong?
1643  if (NewTPC.Cryostat >= NCryos) { // cryostat wrap
1644  NewTPC.Cryostat = (geo::CryostatID::CryostatID_t)0;
1645  NewTPC.TPC = (geo::TPCID::TPCID_t)0;
1646  }
1647  else { // TPC wrap
1648  if (++NewTPC.Cryostat >= NCryos) NewTPC.Cryostat = (geo::CryostatID::CryostatID_t)0;
1649  NewTPC.TPC = (geo::TPCID::TPCID_t)0;
1650  }
1651 
1652  MF_LOG_DEBUG("TWQProjectionView") << __func__ << ": invalid TPC " << RequestedTPC
1653  << ", corrected as " << NewTPC << " instead";
1654  }
1655 
1656  if (!geom.HasTPC(NewTPC)) { // weird...
1657  MF_LOG_ERROR("TWQProjectionView") << __func__ << ": internal error: " << RequestedTPC
1658  << " turned into an invalid TPC " << NewTPC;
1659  }
1660  else if (NewTPC != CurrentTPC) { // do we need to change after all?
1661  MF_LOG_DEBUG("TWQProjectionView")
1662  << __func__ << ": switching from " << CurrentTPC << " to " << NewTPC;
1663 
1664  // new cryostat?
1665  if (rawOpt.fCryostat != NewTPC.Cryostat) { // update the TPC count
1666  unsigned int const NTPCs = geom.NTPC(NewTPC);
1667  fTotalTPCLabel->SetText(TotalElementsString(NTPCs).c_str());
1668  // fTotalTPCLabel->Modified();
1669  }
1670  // update the current TPC in the service
1671  // (that is the thing everything else refers to)
1672  rawOpt.fCryostat = NewTPC.Cryostat;
1673  rawOpt.fTPC = NewTPC.TPC;
1674 
1675  // redraw the content
1677  DrawPads();
1678  // evdb::Canvas::fCanvas->cd();
1679  // evdb::Canvas::fCanvas->Modified();
1680  // evdb::Canvas::fCanvas->Update();
1681  }
1682 
1683  // if we have changed the requested TPC, we need to update the input fields
1684  if (NewTPC != RequestedTPC) {
1685  if (fCryoInput) fCryoInput->SetIntNumber(NewTPC.Cryostat);
1686  if (fTPCInput) fTPCInput->SetIntNumber(NewTPC.TPC);
1687  }
1688 
1689  } // TWQProjectionView::SelectTPC()
1690 
1691  //----------------------------------------------------------------------------
1693  {
1695  if (parameter == 0) {
1696  evdlayoutopt->fMakeClusters = 0;
1697  fToggleClusters->SetState(kButtonUp);
1698  }
1699  else if (parameter == 1) {
1700  evdlayoutopt->fMakeClusters = 1;
1701  fToggleZoom->SetState(kButtonUp);
1702  }
1703  }
1704 
1705  //......................................................................
1707  {
1708  // enter zoom buttons
1710  if (!evdlayoutopt->fShowEndPointSection) return;
1711 
1712  // int fShowEndPointMarkers; ///< Draw EndPoint Markers if clicked.
1713 
1714  fFindEndpoint = new TGTextButton(fVFrame, "&Find XYZ", 150);
1715  fFindEndpoint->Connect("Clicked()", "evd::TWQProjectionView", this, "FindEndPoint()");
1716 
1717  fXYZPosition = new TGTextView(
1718  fVFrame, 100, 55, 999, TGView::kNoHSB | TGView::kNoVSB);
1719  fXYZPosition->SetEditable("false");
1720  TGText* tt = new TGText("x,y,z");
1721  fXYZPosition->SetText(tt);
1722 
1723  fClearPPoints = new TGTextButton(fVFrame, "&Clear Points", 150);
1724  fClearPPoints->Connect("Clicked()", "evd::TWQProjectionView", this, "ClearEndPoints()"); // ?
1725 
1727  new TGCheckButton(fVFrame, "ShowMarkers", 0);
1728  fToggleShowMarkers->Connect(
1729  "Clicked()", "evd::TWQProjectionView", this, "ToggleEndPointMarkers()");
1730  if (evdlayoutopt->fShowEndPointMarkers == 1) fToggleShowMarkers->SetState(kButtonDown);
1731 
1732  fVFrame->AddFrame(fFindEndpoint, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1733  fVFrame->AddFrame(fXYZPosition, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1734  fVFrame->AddFrame(fClearPPoints, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1735  fVFrame->AddFrame(fToggleShowMarkers, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 5, 1));
1736  }
1737 
1739  // Go back one step in zoom
1740 
1742  {
1743  if (fPrevZoomOpt.size() > 0) {
1744  ZoomOptions ThePrevZoomOpt = fPrevZoomOpt.at(fPrevZoomOpt.size() - 1);
1745  int plane = fZoomOpt.OnlyPlaneChanged;
1746  if (plane != -1) {
1747  SetZoom(plane,
1748  ThePrevZoomOpt.wmin[plane],
1749  ThePrevZoomOpt.wmax[plane],
1750  ThePrevZoomOpt.tmin[plane],
1751  ThePrevZoomOpt.tmax[plane],
1752  false);
1753  }
1754  else {
1755  for (size_t iplane = 0; iplane != fPlanes.size(); ++iplane) {
1756  SetZoom(iplane,
1757  ThePrevZoomOpt.wmin[iplane],
1758  ThePrevZoomOpt.wmax[iplane],
1759  ThePrevZoomOpt.tmin[iplane],
1760  ThePrevZoomOpt.tmax[iplane],
1761  false);
1762  }
1763  }
1764 
1765  fPrevZoomOpt.pop_back();
1766  }
1767  else
1768  mf::LogVerbatim("TWQProjectionView")
1769  << "unable to unzoom further - no zoom settings left on stack" << std::endl;
1770  }
1771 
1772  //------------------------------------
1774  int wirelow,
1775  int wirehi,
1776  int timelow,
1777  int timehi,
1778  bool StoreZoom)
1779  {
1780 
1781  if (StoreZoom) {
1782  fPrevZoomOpt.push_back(fZoomOpt);
1783  fZoomOpt.OnlyPlaneChanged = plane;
1784  }
1785 
1786  fZoomOpt.wmin[plane] = wirelow;
1787  fZoomOpt.wmax[plane] = wirehi;
1788  fZoomOpt.tmin[plane] = timelow;
1789  fZoomOpt.tmax[plane] = timehi;
1790 
1791  TVirtualPad* ori = gPad;
1792  zoom_opt = "1";
1793 
1794  // error checking - useful for the mouse zoom.
1795  if (wirehi < wirelow) {
1796  int temp = wirelow;
1797  wirelow = wirehi;
1798  wirehi = temp;
1799  }
1800 
1801  if (timehi < timelow) {
1802  int temp = timelow;
1803  timelow = timehi;
1804  timehi = temp;
1805  }
1806 
1807  //if drawing, then currently not zooming
1808  curr_zooming_plane = -1;
1809 
1810  fPlanes[plane]->SetZoomRange(wirelow, wirehi, timelow, timehi);
1811  fPlanes[plane]->Draw("1");
1812  fPlanes[plane]->UpdatePad();
1813 
1814  evdb::Canvas::fCanvas->cd();
1815  evdb::Canvas::fCanvas->Modified();
1816  evdb::Canvas::fCanvas->Update();
1817 
1818  ori->cd();
1819 
1820  return;
1821  }
1822 
1823  //-----------------------------------------------------------------
1825  {
1826  TVirtualPad* ori = gPad;
1827 
1828  fWireQ->SetPlaneWire(kPlane, kWire);
1829 
1830  fWireQ->Draw();
1831  fWireQ->Pad()->cd();
1832  fWireQ->Pad()->Modified();
1833  fWireQ->Pad()->Update();
1834  fWireQ->Pad()->SetBit(TPad::kCannotMove, true);
1835  fWireQ->Pad()->GetFrame()->SetBit(TPad::kCannotMove, true);
1836 
1837  fPlaneEntry->SetNumber(kPlane);
1838  fWireEntry->SetNumber(kWire);
1839 
1840  evdb::Canvas::fCanvas->cd();
1841  evdb::Canvas::fCanvas->Modified();
1842  evdb::Canvas::fCanvas->Update();
1843 
1844  ori->cd();
1845  }
1846 
1847  //-----------------------------------------------------------------
1849  {
1850  kPlane = (unsigned int)fPlaneEntry->GetNumberEntry()->GetNumber();
1851 
1852  this->SetPlaneWire();
1853  }
1854 
1855  //-----------------------------------------------------------------
1857  {
1859  auto const num_wires = geo->Nwires(geo::PlaneID(0, 0, kPlane));
1860  kWire = (num_wires - 1 > (unsigned int)fWireEntry->GetNumberEntry()->GetNumber()) ?
1861  (unsigned int)fWireEntry->GetNumberEntry()->GetNumber() :
1862  num_wires - 1;
1863 
1864  this->SetPlaneWire();
1865  }
1866 
1867  //-----------------------------------------------------------------
1869  {
1870  kDistance = (double)fDistance->GetNumberEntry()->GetNumber();
1871  }
1872 
1873  //-----------------------------------------------------------------
1875  {
1876  double threshold = fThresEntry->GetNumberEntry()->GetNumber();
1877 
1878  if (threshold != fLastThreshold) {
1880  rawopt->fMinSignal = threshold;
1881 
1882  TVirtualPad* ori = gPad;
1883  this->DrawPads(zoom_opt);
1884  evdb::Canvas::fCanvas->cd();
1885  evdb::Canvas::fCanvas->Modified();
1886  evdb::Canvas::fCanvas->Update();
1887 
1888  ori->cd();
1889  }
1890 
1891  fLastThreshold = threshold;
1892 
1893  return;
1894  }
1895 
1896  //-----------------------------------------------------------------
1898  {
1900 
1901  TGButton* b = (TGButton*)gTQSender;
1902  if (b->GetState() == kButtonDown) { cst->fColorOrGray = 1; }
1903  else {
1904  cst->fColorOrGray = 0;
1905  }
1906 
1907  TVirtualPad* ori = gPad;
1908  this->DrawPads(zoom_opt);
1909  evdb::Canvas::fCanvas->cd();
1910  evdb::Canvas::fCanvas->Modified();
1911  evdb::Canvas::fCanvas->Update();
1912 
1913  ori->cd();
1914 
1915  return;
1916  }
1917 
1918  //-----------------------------------------------------------------
1920  {
1922 
1923  TGButton* b = (TGButton*)gTQSender;
1924  int id = b->WidgetId();
1925 
1926  // id values are set in lines 125 - 127
1927  if (id == 4) {
1928  rawopt->fDrawRawDataOrCalibWires = 0;
1929  fRawDraw->SetState(kButtonDown);
1930  fCalibDraw->SetState(kButtonUp);
1931  fRawCalibDraw->SetState(kButtonUp);
1932  }
1933  else if (id == 3) {
1934  rawopt->fDrawRawDataOrCalibWires = 1;
1935  fRawDraw->SetState(kButtonUp);
1936  fCalibDraw->SetState(kButtonDown);
1937  fRawCalibDraw->SetState(kButtonUp);
1938  }
1939  else if (id == 2) {
1940  rawopt->fDrawRawDataOrCalibWires = 2;
1941  fRawDraw->SetState(kButtonUp);
1942  fCalibDraw->SetState(kButtonUp);
1943  fRawCalibDraw->SetState(kButtonDown);
1944  }
1945 
1946  TVirtualPad* ori = gPad;
1947 
1948  fWireQ->Draw();
1949  fWireQ->Pad()->cd();
1950  fWireQ->Pad()->Modified();
1951  fWireQ->Pad()->Update();
1952 
1953  this->DrawPads(zoom_opt);
1954  evdb::Canvas::fCanvas->cd();
1955  evdb::Canvas::fCanvas->Modified();
1956  evdb::Canvas::fCanvas->Update();
1957 
1958  ori->cd();
1959 
1960  return;
1961  }
1962 
1963  //-----------------------------------------------------------------
1965  {
1967 
1968  TGButton* b = (TGButton*)gTQSender;
1969  if (b->GetState() == kButtonDown) {
1970  sdo->fShowMCTruthText = 1;
1971  sdo->fShowMCTruthVectors = 1;
1972  }
1973  else {
1974  sdo->fShowMCTruthText = 0;
1975  sdo->fShowMCTruthVectors = 0;
1976  }
1977 
1978  TVirtualPad* ori = gPad;
1979 
1980  fMC->Draw();
1981  evdb::Canvas::fCanvas->cd();
1982  evdb::Canvas::fCanvas->Modified();
1983  evdb::Canvas::fCanvas->Update();
1984 
1985  ori->cd();
1986  }
1987 
1988  //-----------------------------------------------------------------
1990  {
1991 
1992  // first check if it's new...
1993  art::Event const* pEvent = evdb::EventHolder::Instance()->GetEvent();
1994  if (!pEvent) {
1995  if (!fLastEvent->isValid()) return false; // no event before, nor now
1996  fLastEvent->clear();
1997  return true;
1998  }
1999 
2000  // do we have a new event?
2001  if (!fLastEvent->update(
2002  {*pEvent, art::ServiceHandle<evd::RawDrawingOptions const>()->fRawDataLabels[0]}))
2003  return false;
2004 
2005  MF_LOG_DEBUG("TWQProjectionView") << "New event or product: " << *fLastEvent;
2006 
2008  SetAutomaticZoomMode(drawopt->fAutoZoomInterest == 1);
2009 
2010  return true; // yes, a new event is here
2011  } // TWQProjectionView::OnNewEvent()
2012 
2013  //-----------------------------------------------------------------
2014 
2015 } // 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.
details::range_type< T > Iterate() const
Initializes the specified ID with the ID of the first cryostat.
Definition: GeometryCore.h:541
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...
unsigned int NTPC(CryostatID const &cryoid=cryostat_zero) const
Returns the total number of TPCs in the specified cryostat.
Definition: GeometryCore.h:686
const art::Event * GetEvent() const
Definition: EventHolder.cxx:45
double z
z position of intersection
Definition: geo_types.h:792
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
double fLastThreshold
Kludge to prevent double drawing when changing threshold.
Float_t y
Definition: compare.C:6
Double_t z
Definition: plot.C:276
TGTextButton * fZoomInterest
Zoom on iteresting region.
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
void Draw(const char *opt=0)
Drawing pad for time or charge histograms.
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, Point_t &intersection) const
Computes the intersection between two wires.
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.
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:563
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:112
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:430
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 detector geometry.
Definition: type_traits.h:61
PlaneGeo const & Plane(PlaneID const &planeid) const
Returns the specified wire.
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.
Point_t GetBoxCenter() const
Returns the centre of the box representing the plane.
Definition: PlaneGeo.h:449
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
geo::Point_t toWorldCoords(LocalPoint_t const &local) const
Transform point from local plane frame to world frame.
Definition: PlaneGeo.h:1225
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:78
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:31
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:381
Description of geometry of one entire detector.
Definition: GeometryCore.h:119
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:193
SigType_t SignalType(PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
WireID NearestWireID(Point_t const &point, PlaneID const &planeid) const
Returns the ID of wire closest to position in the specified TPC.
unsigned int TPCID_t
Type for the ID number.
Definition: geo_types.h:382
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.
double y
y position of intersection
Definition: geo_types.h:791
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
unsigned int Nwires(PlaneID const &planeid) const
Returns the total number of wires in the specified plane.
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
unsigned int Nplanes(TPCID const &tpcid=tpc_zero) const
Returns the total number of planes in the specified TPC.
Definition: GeometryCore.h:977
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.
Namespace collecting geometry-related classes utilities.
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
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:699
TGNumberEntry * fWireEntry
Wire number displayed.
bool isValid() const
Returns whether there is a current event and data product.
art framework interface to geometry description
geo::Point3DBase_t< PlaneGeoCoordinatesTag > LocalPoint_t
Type of points in the local GDML wire plane frame.
Definition: PlaneGeo.h:106
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:192
Signal from collection planes.
Definition: geo_types.h:152
std::map< int, double > tmax
void SetPlaneWire(unsigned int plane=0, unsigned int wire=0)
Definition: TQPad.h:40