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