ATLAS Offline Software
PhiSectionWidget.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include <QMouseEvent>
8 #include <QGraphicsEllipseItem>
9 #include <QCursor>
10 #include <QDrag>
11 #include <QMenu>
12 #include <QDragEnterEvent>
13 #include <QDropEvent>
14 #include <QApplication>
15 #include <QBuffer>
16 #include <QClipboard>
17 #include <QInputDialog>
18 #include <QVector>
19 #include <QMimeData>
20 #include <QDebug>
21 
22 #include <cmath>
23 #include <iostream>
24 
26 // //
27 // Implementation of class PhiSectionWidget //
28 // //
29 // Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> //
30 // //
31 // Initial VP1 version: September 2007 //
32 // Major update: January 2009 //
33 // Riccardo-Maria BIANCHI <rbianchi@cern.ch>: March 2013 //
34 // Riccardo-Maria BIANCHI <rbianchi@cern.ch>: March 2023 //
35 // //
37 
38 //____________________________________________________________________
40 public:
42 
43  //Sectors status and mapping to graphics:
44  QVector<bool> sectorstatus;
45  std::map<QGraphicsEllipseItem*,int> item2sector;
46 
47  void approximateSectorStatusFromRanges( const QList<VP1Interval>& oldEnabledRanges, QVector<bool>& target );
48 
50 
51  //Styles:
52  QPen pen_on;
53  QPen pen_off;
54  QBrush brush_on;
55  QBrush brush_off;
56 
57  //Update colours based on current sectorstatus vector:
58  void updateColors();
59 
60  //Cache:
61  bool cacheValid;
62  QList<VP1Interval> cachedRanges;//this also serves as the cache
63  bool cachedAllOn;//part of the cache
64  bool cachedAllOff;//part of the cache
65 
66  //Convenience:
67  static void wrap(QList<VP1Interval>&);
68 
69  //Allowed sectors:
71  QList<int> allowedNSectors;
72 
73  //Menu:
74  QMenu * popup_menu;
78  QAction* popup_copyAction;
81  QList<QAction*> popuplist_setNPhi;
83  void ensureMenuInit();
85 
86  //Decoding the current phi-ranges and checking for changes:
87  QList<VP1Interval> enabledPhiRangesNoCache(const QVector<bool>& secstatus,
88  bool& allOn, bool& allOff) const;
89  void checkForChanges();
90 
91 };
92 
93 
94 //____________________________________________________________________
96  : QGraphicsView(parent),
97  VP1HelperClassBase(sys,"PhiSectionWidget"),
98  m_d(new Imp)
99 {
100  if(VP1Msg::verbose()){
101  messageVerbose("PhiSectionWidget constr");
102  }
103 
104  m_d->theclass = this;
105  m_d->popup_menu = 0;
108  m_d->popup_invertAction = 0;
109  m_d->popup_copyAction = 0;
110  m_d->popup_pasteAction = 0;
112 
113  setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
114  setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
115  setRenderHint(QPainter::Antialiasing,true);
116 
117  m_d->pen_on.setWidth(0);
118  m_d->pen_on.setBrush(Qt::red);
119  m_d->pen_off.setWidth(0);
120  m_d->pen_off.setBrush(Qt::gray);
121  m_d->brush_on.setColor(Qt::red);
122  m_d->brush_on.setStyle(Qt::SolidPattern);
123  m_d->brush_off.setColor(Qt::gray);
124  m_d->brush_off.setStyle(Qt::SolidPattern);
125 
126  m_d->cacheValid = false;
127 
128  setFocusPolicy(Qt::NoFocus);
129  setAcceptDrops(true);
130 
131  //The following is the way to init N sectors:
132  m_d->allowCustomNSectors = true;
133  QList<int> defaultAllowedNSectors;
134  defaultAllowedNSectors << 4 << 5 << 6 << 8 << 9 << 10
135  << 12 << 16 << 24 << 32 << 36 << 48 << 64;
136  m_d->allowedNSectors << 12; // default number of sectors, at start
137  setNumberOfSectors(12,true);
138  setAllowedNumberOfSectors(defaultAllowedNSectors,true);
139 }
140 
141 //____________________________________________________________________
143 {
144  QGraphicsScene * oldscene = scene();
145  if (oldscene) {
146  setScene(0);
147  delete oldscene;
148  }
149  delete m_d;
150 }
151 
152 //____________________________________________________________________
153 void PhiSectionWidget::setNumberOfSectors(int nsectors,bool forceAllEnabled)
154 {
155  if(VP1Msg::debug()){
156  messageDebug("setNumberOfSectors()");
157  }
158 
159 
160  if (nsectors<4||nsectors>99) {
161  if(VP1Msg::debug()){
162  messageDebug("nsectors<4||nsectors>99. Returning.");
163  }
164  return;
165  }
166 
167  if (!m_d->allowedNSectors.contains(nsectors) && !m_d->allowCustomNSectors) {
168  //Oups! Let us try first to pick something among the allowed
169  //values which would allow us to preserve the ranges exactly;
170  int n(-1);
171  for(int i = 2; i < 100; ++i) {
172  if (m_d->allowedNSectors.contains(i*nsectors)) {
173  n = i*nsectors;
174  break;
175  }
176  }
177  nsectors = n>0 ? n : m_d->allowedNSectors.back();
178  } else if (!m_d->sectorstatus.isEmpty() && nsectors==static_cast<int>(m_d->sectorstatus.count())) {
179  if(VP1Msg::debug()){
180  messageDebug("!sectorstatus.isEmpty() && nsectors==sectorstatus.count(). Returning...");
181  }
182  return;
183  }
184 
185  if ( m_d->sectorstatus.isEmpty() ) {
186  if(VP1Msg::debug()){
187  messageDebug("m_d->sectorstatus is Empty.");
188  }
189  }
190 
191  // check if sectors have already been defined
192  QList<VP1Interval> oldEnabledRanges;
193  if ( !m_d->sectorstatus.isEmpty() ) {
194  oldEnabledRanges = enabledPhiRanges();
195  }
196 
197  //Update new graphics objects with the new settings
198 
199  // first clear everything...
200  m_d->item2sector.clear();
201  m_d->sectorstatus.clear();
202  QGraphicsScene * oldscene = scene();
203  setScene(new QGraphicsScene);
204  delete oldscene;
205 
206  // ...then build new variables with the new settings of 'nsectors'
207  const double R = 10.0;
208  const double r = (2*M_PI)*R / nsectors / 1.2;
209 
210  for (int isector = 0; isector < nsectors; ++isector) {
211  double phi = (isector+0.5)*(2*M_PI)/nsectors;
212  double x(R*cos(phi)), y(-R*sin(phi));
213  QGraphicsEllipseItem * ellipse = scene()->addEllipse(x,y,r,r);
214  m_d->item2sector[ellipse]=isector;
215  }
216 
217  m_d->sectorstatus.fill(forceAllEnabled,m_d->item2sector.size());
218 
219  if (!forceAllEnabled)
221  m_d->updateColors();
222  fitInView(scene()->sceneRect());
223  m_d->checkForChanges();
224 
225 
226  // resize the widget based on the number of sectors
227  // we need to make it larger as the number of sectors increases
228  // otherwise the 'red dots' are difficult to see and pick with the mouse
229  // Note: numbers of sectors are not continuos: after 12, 16 comes, then 24, ...
230  if (nsectors <= 12) {
231  setFixedSize(60,60);
232  } else if(nsectors >= 16 && nsectors < 24) {
233  setFixedSize(120,120);
234  } else if(nsectors >= 24 && nsectors < 32) {
235  setFixedSize(200,200);
236  } else if (nsectors >= 32 && nsectors <= 36) {
237  setFixedSize(300,300);
238  } else if (nsectors > 36) {
239  setFixedSize(400,400);
240  }
241 
242 
243  if ( m_d->sectorstatus.isEmpty() ) {
244  if(VP1Msg::debug()){
245  messageDebug("WARNING. m_d->sectorstatus is still Empty...");
246  }
247  }
248 }
249 
250 
251 //____________________________________________________________________
253 {
254  return m_d->sectorstatus.count();
255 }
256 
257 //____________________________________________________________________
259 {
261  for (it = item2sector.begin();it!=itE;++it) {
262  if (sectorstatus[it->second]) {
263  it->first->setPen(pen_on);
264  it->first->setBrush(brush_on);
265  } else {
266  it->first->setPen(pen_off);
267  it->first->setBrush(brush_off);
268  }
269  }
270 }
271 
272 //____________________________________________________________________
274 {
275  if (isector<0||isector>=static_cast<int>(m_d->sectorstatus.count()))
276  return;
277  if (m_d->sectorstatus.at(isector)==status)
278  return;
279  m_d->sectorstatus[isector]=status;
280  m_d->cacheValid=false;
281  m_d->checkForChanges();
282 }
283 
284 //____________________________________________________________________
286 {
287  if (popup_menu)
288  return;
289  popup_menu = new QMenu(theclass);
290  popup_copyAction = popup_menu->addAction("&Copy");
291  popup_pasteAction = popup_menu->addAction("&Paste");
292  popup_menu->addSeparator();
293  popup_enableAllAction = popup_menu->addAction("&Enable all sectors");
294  popup_disableAllAction = popup_menu->addAction("&Disable all sectors");
295  popup_invertAction = popup_menu->addAction("&Invert");
296  popup_menu->addSeparator();
297  popup_setNPhiSubMenu = popup_menu->addMenu("&Set number of phi sectors");
298  addMenuEntriesForSetNPhi();
299 }
300 
301 //____________________________________________________________________
303 {
304  if (!popup_menu)
305  return;
306  if (!popuplist_setNPhi.isEmpty()) {
307  for(QAction * setNPhiAct : popuplist_setNPhi)
308  delete setNPhiAct;
309  }
310  popuplist_setNPhi.clear();
311 
312  for(int nSectors : allowedNSectors) {
313  QAction * a = popup_setNPhiSubMenu->addAction(QString::number(nSectors));
314  a->setData(nSectors);
315  popuplist_setNPhi << a;
316  }
317  if (allowCustomNSectors) {
318  popup_setNPhiSubMenu->addSeparator();
319  popup_setCustomNPhi = popup_setNPhiSubMenu->addAction("&Custom...");
320  }
321 }
322 
323 //____________________________________________________________________
325 {
326  //Prepare:
327  m_d->ensureMenuInit();
328  m_d->popup_enableAllAction->setEnabled(!allSectorsOn());
329  m_d->popup_disableAllAction->setEnabled(!allSectorsOff());
330 
331  QClipboard * clipboard = QApplication::clipboard();
332  m_d->popup_pasteAction->setEnabled(clipboard
333  &&clipboard->mimeData()->hasFormat("vp1/enabledphisectors"));
334 
335  for(QAction * setNPhiAct : m_d->popuplist_setNPhi) {
336  bool ok;
337  int nSectors = setNPhiAct->data().toInt(&ok);
338  setNPhiAct->setEnabled(ok&&nSectors!=m_d->sectorstatus.count());
339  }
340 
341  //Launch
342  QAction * selAct = m_d->popup_menu->exec(p);
343 
344  //React
345  if (selAct==m_d->popup_copyAction) {
346  QMimeData *mimeData = new QMimeData;
347  mimeData->setData("vp1/enabledphisectors", state());
348  mimeData->setText(enabledRangesToString());
349  clipboard->setMimeData(mimeData);
350  return;
351  }
352  if (selAct==m_d->popup_pasteAction) {
353  QByteArray data = clipboard->mimeData()->data("vp1/enabledphisectors");
354  setState(data);
355  return;
356  }
357  if (selAct==m_d->popup_enableAllAction) {
358  for (int i = 0; i < m_d->sectorstatus.count(); ++i)
359  m_d->sectorstatus[i] = true;
360  m_d->cacheValid = false;
361  m_d->checkForChanges();
362  return;
363  }
364  if (selAct==m_d->popup_disableAllAction) {
365  for (int i = 0; i < m_d->sectorstatus.count(); ++i)
366  m_d->sectorstatus[i] = false;
367  m_d->cacheValid = false;
368  m_d->checkForChanges();
369  return;
370  }
371  if (selAct==m_d->popup_invertAction) {
372  for (int i = 0; i < m_d->sectorstatus.count(); ++i)
374  m_d->cacheValid = false;
375  m_d->checkForChanges();
376  return;
377  }
378  if (selAct==m_d->popup_setCustomNPhi) {
379  bool ok;
380  // int nCustomSectors = QInputDialog::getInteger(this, "Set number of phi sectors",
381  int nCustomSectors = QInputDialog::getInt(this, "Set number of phi sectors",
382  "Set number of phi sectors", m_d->sectorstatus.count(),4,99,1,&ok);
383  if (ok && nCustomSectors >= 4 && nCustomSectors <= 99 )
384  setNumberOfSectors(nCustomSectors);
385  return;
386  }
387  if (m_d->popuplist_setNPhi.contains(selAct)) {
388  bool ok;
389  int nSectors = selAct->data().toInt(&ok);
390  if (ok)
391  setNumberOfSectors(nSectors);
392  return;
393  }
394 }
395 
396 //____________________________________________________________________
398 {
399  if (event->buttons()==Qt::RightButton) {
401  return;
402  }
403 
404  if (event->button() == Qt::LeftButton)
405  m_d->dragStartPosition = event->pos();
406 
407  if (event->buttons()!=Qt::LeftButton) {
408  QGraphicsView::mousePressEvent(event);
409  return;
410  }
411  QGraphicsItem *item_ = itemAt(event->pos());
412  QGraphicsEllipseItem * item = static_cast<QGraphicsEllipseItem*>(item_);
413  if (!item||m_d->item2sector.find(item)==m_d->item2sector.end()) {
414  QGraphicsView::mousePressEvent(event);
415  return;
416  }
417  int isector = m_d->item2sector[item];
418  if (isector<0||isector>=static_cast<int>(m_d->sectorstatus.count())) {
419  QGraphicsView::mousePressEvent(event);
420  return;
421  }
422  m_d->sectorstatus[isector]=!(m_d->sectorstatus.at(isector));
423  if(VP1Msg::verbose()){
424  messageVerbose("Turning on sector"+QString::number(isector));
425  }
426  m_d->cacheValid=false;
427  m_d->checkForChanges();
428 }
429 
430 //____________________________________________________________________
432 {
433  if (!(event->buttons() & Qt::LeftButton))
434  return;
435  if ((event->pos() - m_d->dragStartPosition).manhattanLength()
436  < QApplication::startDragDistance())
437  return;
438 
439  QDrag *drag = new QDrag(this);
440  QMimeData *mimeData = new QMimeData;
441 
443  // For dragging state onto other phi section widgets: //
445 
446  mimeData->setData("vp1/enabledphisectors", state());
447 
449  // For dragging a readable version of the enabled phi-ranges //
450  // into e.g. an editor or email program: //
452 
453  mimeData->setText(enabledRangesToString());
454 
455  //Execute drag:
456  drag->setMimeData(mimeData);//drag assumes ownership of mimeData
457  drag->exec(Qt::CopyAction | Qt::MoveAction);
458 }
459 
460 //____________________________________________________________________
462 {
463  if (event->source()!=this && event->mimeData()->hasFormat("vp1/enabledphisectors"))
464  event->acceptProposedAction();
465 }
466 
467 //____________________________________________________________________
469 {
470  QByteArray data = event->mimeData()->data("vp1/enabledphisectors");
471  event->acceptProposedAction();
472  setState(data);
473 }
474 
475 //____________________________________________________________________
476 void PhiSectionWidget::resizeEvent(QResizeEvent *)
477 {
478  if (scene())
479  fitInView(scene()->sceneRect());
480 }
481 
482 //____________________________________________________________________
484 {
485  if (!m_d->cacheValid)
486  m_d->checkForChanges();
487  return m_d->cachedAllOn;
488 }
489 
490 
491 //____________________________________________________________________
493 {
494  if (!m_d->cacheValid)
495  m_d->checkForChanges();
496  return m_d->cachedAllOff;
497 }
498 
499 //____________________________________________________________________
500 void PhiSectionWidget::Imp::wrap(QList<VP1Interval>& l)
501 {
502  if (l.count()<2||l.front().lower()!=0.0||l.back().upper()!=(2*M_PI))
503  return;
504  l.front().setLower(l.back().lower()-(2*M_PI));
505  l.removeLast();
506 }
507 
508 
509 //____________________________________________________________________
510 QList<VP1Interval> PhiSectionWidget::Imp::enabledPhiRangesNoCache(const QVector<bool>& secstatus, bool& allOn, bool& allOff) const
511 {
512  if(VP1Msg::verbose()){
513  theclass->messageVerbose("enabledPhiRangesNoCache()");
514  }
515  QList<VP1Interval> l;
516  allOn = true;
517  allOff = true;
518 
519  const unsigned int n = secstatus.count();
520 
521  const double dphi = (2*M_PI)/n;
522  if(VP1Msg::debug()){
523  qDebug() << "n: " << n << " - dphi:" << dphi;
524  }
525 
526  bool open(false);
527  double tmp(-999);
528 
529  for (unsigned i = 0; i < n; ++i) {
530  const bool status = secstatus[i];
531  if (status) {
532  allOff = false;
533  }
534  else {
535  allOn = false;
536  }
537  if (status!=open) {
538  if (!open) {
539  tmp = i*dphi;
540  open = true;
541  } else {
542  l << VP1Interval(tmp,i*dphi);
543  open = false;
544  }
545  }
546  }
547  if (open)
548  l << VP1Interval(tmp,(2*M_PI));
549  wrap(l);
550 
551  if(VP1Msg::debug()){
552  theclass->messageDebug("exiting enabledPhiRangesNoCache()...");
553  }
554 
555  return l;
556 }
557 
558 
559 //____________________________________________________________________
560 QList<VP1Interval> PhiSectionWidget::enabledPhiRanges() const
561 {
562  if(VP1Msg::debug()){
563  messageDebug("enabledPhiRanges()");
564  }
565 
566  if (!m_d->cacheValid) {
567  if(VP1Msg::debug()){
568  messageDebug("Cache not valid. Checking for changes...");
569  }
570  m_d->checkForChanges();
571  }
572  return m_d->cachedRanges;
573 }
574 
575 //____________________________________________________________________
576 QList<VP1Interval> PhiSectionWidget::enabledPhiRanges(double phi_min,double phi_max) const
577 {
578  if(VP1Msg::debug()){
579  messageDebug("enabledPhiRanges(double phi_min,double phi_max)");
580  }
581 
582  if (phi_min>=phi_max)
583  return QList<VP1Interval>();
584  if (phi_max-phi_min>=(2*M_PI))
585  return enabledPhiRanges();
586  while (phi_min<0) {
587  phi_min += (2*M_PI);
588  phi_max += (2*M_PI);
589  }
590 
591  //For ranges such as -310deg->10deg, phi_max might now be larger
592  //than 2pi. We handle this as a special case, merging the result of
593  //two calls to this method:
594  if (phi_max>(2*M_PI)) {
595  QList<VP1Interval> l1 = enabledPhiRanges(phi_min,(2*M_PI));
596  QList<VP1Interval> l2 = enabledPhiRanges(0,phi_max-(2*M_PI));
597  // if (!l1.empty()&&!l2.empty()&&l1.front()
598  l2 << l1;
599  Imp::wrap(l2);
600  return l2;
601  }
602 
603  QList<VP1Interval> l = enabledPhiRanges();
604  if (l.empty())
605  return l;
606 
607  //In case one of the ranges wraps around at phi=0, we first unwrap
608  //the list:
609  if (l.front().lower()<0.0) {
610  l.append(VP1Interval(l.front().lower()+(2*M_PI),(2*M_PI)));
611  l.front().setLower(0.0);
612  }
613 
614 
615  //Now, phi_min<phi_max and both are in [0,2pi]. Now, loop over all
616  //ranges and constrain them to [phi_min,phi_max], removing those
617  //that fall outside:
618  double a,b;
619  for ( int i = 0; i < l.count(); ) {
620  a = l[i].lower();
621  b = l[i].upper();
622  if (b <= phi_min||a >= phi_max) {
623  l.removeAt(i);
624  } else {
625  if (a<phi_min)
626  l[i].setLower(phi_min);
627  if (b>phi_max)
628  l[i].setUpper(phi_max);
629  ++i;
630  }
631  }
632 
633  Imp::wrap(l);
634 
635  return l;
636 }
637 
638 //____________________________________________________________________
640 {
641  if (!m_d->cacheValid)
642  m_d->checkForChanges();
643  QString s;
644  for(int i=0;i<m_d->cachedRanges.count();++i)
645  s+= m_d->cachedRanges.at(i).toString()+(i==m_d->cachedRanges.count()-1?"":", ");
646  return s;
647 }
648 
649 //____________________________________________________________________
651 {
652  if(VP1Msg::debug()){
653  theclass->messageDebug("checkForChanges()");
654  }
655 
656  //Ensure caches are updated, and emit signal in case of any change:
657  cacheValid = true;
658 
659  QList<VP1Interval> r = enabledPhiRangesNoCache(sectorstatus,cachedAllOn, cachedAllOff);
660  if (cachedRanges == r) {
661  return;
662  }
663  updateColors();
664  cachedRanges = r;
665 
666  if(VP1Msg::verbose()){
667  QString s;
668  for(int i=0;i<r.count();++i)
669  s+= r.at(i).toString()+(i==r.count()-1?"":", ");
670  theclass->messageVerbose("Emitting enabledPhiRangesChanged("
671  +theclass->enabledRangesToString()+")");
672  }
673  emit theclass->enabledPhiRangesChanged(r);
674 }
675 
676 //____________________________________________________________________
677 bool PhiSectionWidget::virtualSectorEnabled(int iSector,int nSectors) const
678 {
679 // this->messageDebug("virtualSectorEnabled()");
680 
681  if (iSector<0||iSector>=nSectors||nSectors<1)
682  return false;
683  if (!m_d->cacheValid)
684  m_d->checkForChanges();
685  if (m_d->cachedAllOn)
686  return true;
687  if (m_d->cachedAllOff)
688  return false;
689 
690  //Phi-range of virtual sector:
691  const double dphi = (2*M_PI)/nSectors;
692  const double epsilon(dphi*1.0e-9);
693  VP1Interval phirange(dphi*iSector+epsilon,dphi*(iSector+1)-epsilon);
694 
695  //Compare with enabled ranges:
696  for(const VP1Interval& enabledrange : m_d->cachedRanges) {
697  if (phirange.hasOverlap(enabledrange,2*M_PI))
698  return true;
699  }
700  return false;
701 }
702 
703 //____________________________________________________________________
704 QVector<bool> PhiSectionWidget::virtualSectorsEnabled(int nSectors) const
705 {
706  if (nSectors<1)
707  return QVector<bool>();
708  QVector<bool> v(nSectors,false);
709  for (int i = 0; i < nSectors; ++i)
710  if (virtualSectorEnabled(i,nSectors))
711  v[i] = true;
712  return v;
713 }
714 
715 //____________________________________________________________________
717 {
718  //Constrain phi to [0,2*pi[
719  while (phi<0) phi+=(2*M_PI);
720  while (phi>=(2*M_PI)) phi-=(2*M_PI);
721  if (phi<0.0) phi=0.0;
722 
723  int iphi = static_cast<int>(nSectors*phi/((2*M_PI)));
724  return iphi;
725 }
726 
727 //____________________________________________________________________
728 QByteArray PhiSectionWidget::state() const
729 {
730  // ===> Setup stream writing to a byteArray:
731  QByteArray byteArray;
732  QBuffer buffer(&byteArray);
733  buffer.open(QIODevice::WriteOnly);
734  QDataStream out(&buffer);
735  out << qint32(0);//version
736  out << m_d->sectorstatus;//This is all the data we output,
737  //allowing for applicability of the data
738  //between different widgets, even if they are
739  //being used differently.
740  buffer.close();
741  return byteArray;
742 
743 
744 }
745 
746 //____________________________________________________________________
747 void PhiSectionWidget::setState(QByteArray ba)
748 {
749  if(VP1Msg::verbose()){
750  this->messageVerbose("setState()");
751  }
752  // ===> Setup stream for getting the contents of the byteArray:
753  QBuffer buffer(&ba);
754  buffer.open(QIODevice::ReadOnly);
755  QDataStream state(&buffer);
756 
757  qint32 version;
758  state >> version;
759  if (version!=0)
760  return;
761 
762  QVector<bool> restored_sectorstatus;
763  state >> restored_sectorstatus;
764  buffer.close();
765 
766  bool save = blockSignals(true);
767  if (restored_sectorstatus.count()!=m_d->sectorstatus.count())
768  setNumberOfSectors(restored_sectorstatus.count(),true);
769  if (restored_sectorstatus.count()==m_d->sectorstatus.count()) {
770  m_d->sectorstatus = restored_sectorstatus;
771  } else {
772  bool allon, alloff;
773  QList<VP1Interval> r = m_d->enabledPhiRangesNoCache(restored_sectorstatus,allon, alloff);
774  if (allon) {
775  m_d->sectorstatus.fill(true);
776  }
777  else if (alloff) {
778  m_d->sectorstatus.fill(true);
779  }
780  else {
782  }
783  }
784  if (!save)
785  blockSignals(false);
786  m_d->cacheValid=false;
787  m_d->checkForChanges();
788 }
789 
790 //____________________________________________________________________
791 void PhiSectionWidget::Imp::approximateSectorStatusFromRanges( const QList<VP1Interval>& oldEnabledRanges,
792  QVector<bool>& target )
793 {
794  if (oldEnabledRanges.isEmpty()) {
795  target.fill(false);
796  return;
797  }
798  if (oldEnabledRanges.count()==1&&oldEnabledRanges.first().length()>=2*M_PI*(1.0-1.0e-10)) {
799  target.fill(true);
800  return;
801  }
802  const unsigned n = target.size();
803  target.fill(false);
804  const double dphi = (2*M_PI)/n;
805  const double epsilon(dphi*1.0e-9);
806  for (unsigned i = 0; i < n; ++i) {
807  VP1Interval phirange(dphi*i+epsilon,dphi*(i+1)-epsilon);
808  for(const VP1Interval& oldrange : oldEnabledRanges) {
809  if (phirange.hasOverlap(oldrange,2*M_PI)) {
810  target[i]=true;
811  break;
812  }
813  }
814  }
815 }
816 
817 //____________________________________________________________________
818 void PhiSectionWidget::dragMoveEvent ( QDragMoveEvent * event )
819 {
820  //Reimplement to avoid interference by the QGraphicsView implementation.
821  event->acceptProposedAction();
822 }
823 
824 //____________________________________________________________________
825 void PhiSectionWidget::dragLeaveEvent ( QDragLeaveEvent * )
826 {
827  //Reimplement to avoid interference by the QGraphicsView implementation.
828 }
829 
830 //____________________________________________________________________
831 void PhiSectionWidget::setAllowedNumberOfSectors(QList<int> allowedNSectors, bool allowCustom)
832 {
833  if(VP1Msg::verbose()){
834  messageVerbose("setAllowedNumberOfSectors()");
835  }
836 
837  //Check validity:
838  if (allowedNSectors.isEmpty()) {
839  if(VP1Msg::verbose()){
840  messageVerbose("allowedNSectors empty. Returning.");
841  }
842  return;
843  }
844  for(int s : allowedNSectors) {
845  if (s<4) {
846  if(VP1Msg::verbose()){
847  messageVerbose("allowedNSectors s < 4. Returning.");
848  }
849  return;
850  }
851  }
852 
853  if (allowCustom&&!allowedNSectors.contains(m_d->sectorstatus.count())) {
854  allowedNSectors << m_d->sectorstatus.count();
855  }
856 
857  m_d->allowCustomNSectors = allowCustom;
858 
859  std::sort(allowedNSectors.begin(), allowedNSectors.end());
860  if (m_d->allowedNSectors==allowedNSectors) {
861  return;
862  }
863  m_d->allowedNSectors=allowedNSectors;
864  if (m_d->popup_menu) {
866  }
867 
868  if (!m_d->allowedNSectors.contains(m_d->sectorstatus.count())) {
870  }
871 
872  int checkA = m_d->sectorstatus.isEmpty();
873  int checkB = m_d->sectorstatus.count();
874  if(VP1Msg::debug()){
875  messageDebug("check - sectorstatus.isEmpty? " + str(checkA + checkB) );
876  }
877 
878 }
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
PhiSectionWidget::Imp::wrap
static void wrap(QList< VP1Interval > &)
Definition: PhiSectionWidget.cxx:500
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
beamspotman.r
def r
Definition: beamspotman.py:676
PhiSectionWidget::phiToVirtualSectorIndex
static int phiToVirtualSectorIndex(double phi, int nSectors)
Definition: PhiSectionWidget.cxx:716
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
PhiSectionWidget::Imp::popuplist_setNPhi
QList< QAction * > popuplist_setNPhi
Definition: PhiSectionWidget.cxx:81
PhiSectionWidget::Imp::popup_invertAction
QAction * popup_invertAction
Definition: PhiSectionWidget.cxx:77
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
PhiSectionWidget::allSectorsOn
bool allSectorsOn() const
Definition: PhiSectionWidget.cxx:483
PhiSectionWidget::Imp::popup_setNPhiSubMenu
QMenu * popup_setNPhiSubMenu
Definition: PhiSectionWidget.cxx:80
GlobalVariables.phirange
phirange
Definition: GlobalVariables.py:64
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:67
PhiSectionWidget::numberOfSectors
int numberOfSectors() const
Definition: PhiSectionWidget.cxx:252
PhiSectionWidget::~PhiSectionWidget
virtual ~PhiSectionWidget()
Definition: PhiSectionWidget.cxx:142
PhiSectionWidget::Imp
Definition: PhiSectionWidget.cxx:39
VP1HelperClassBase::messageVerbose
void messageVerbose(const QString &) const
Definition: VP1HelperClassBase.cxx:78
PhiSectionWidget::Imp::popup_copyAction
QAction * popup_copyAction
Definition: PhiSectionWidget.cxx:78
PhiSectionWidget::allSectorsOff
bool allSectorsOff() const
Definition: PhiSectionWidget.cxx:492
PhiSectionWidget::Imp::sectorstatus
QVector< bool > sectorstatus
Definition: PhiSectionWidget.cxx:44
CSV_InDetExporter.new
new
Definition: CSV_InDetExporter.py:145
PhiSectionWidget::enabledRangesToString
QString enabledRangesToString() const
Definition: PhiSectionWidget.cxx:639
skel.it
it
Definition: skel.GENtoEVGEN.py:396
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
PhiSectionWidget::Imp::allowCustomNSectors
bool allowCustomNSectors
Definition: PhiSectionWidget.cxx:70
M_PI
#define M_PI
Definition: ActiveFraction.h:11
PhiSectionWidget::mousePressEvent
void mousePressEvent(QMouseEvent *)
Definition: PhiSectionWidget.cxx:397
PhiSectionWidget::Imp::updateColors
void updateColors()
Definition: PhiSectionWidget.cxx:258
VP1Msg::debug
static bool debug()
Definition: VP1Msg.h:32
PhiSectionWidget::Imp::cachedAllOn
bool cachedAllOn
Definition: PhiSectionWidget.cxx:63
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:158
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
x
#define x
VP1String::str
static QString str(const QString &s)
Definition: VP1String.h:49
VP1HelperClassBase::messageDebug
void messageDebug(const QString &) const
Definition: VP1HelperClassBase.cxx:65
mapkey::sys
@ sys
Definition: TElectronEfficiencyCorrectionTool.cxx:42
TruthTest.itE
itE
Definition: TruthTest.py:25
PhiSectionWidget::launchContextMenu
void launchContextMenu(QPoint)
Definition: PhiSectionWidget.cxx:324
PhiSectionWidget::Imp::pen_on
QPen pen_on
Definition: PhiSectionWidget.cxx:52
PhiSectionWidget::PhiSectionWidget
PhiSectionWidget(QWidget *parent, IVP1System *sys=0)
Definition: PhiSectionWidget.cxx:95
PyPoolBrowser.item
item
Definition: PyPoolBrowser.py:129
PhiSectionWidget::resizeEvent
void resizeEvent(QResizeEvent *)
Definition: PhiSectionWidget.cxx:476
PhiSectionWidget::setSectorStatus
void setSectorStatus(int, bool)
Definition: PhiSectionWidget.cxx:273
checkTP.save
def save(self, fileName="./columbo.out")
Definition: checkTP.py:178
IVP1System
Definition: IVP1System.h:36
PhiSectionWidget::Imp::dragStartPosition
QPoint dragStartPosition
Definition: PhiSectionWidget.cxx:49
skel.l2
l2
Definition: skel.GENtoEVGEN.py:399
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
createCoolChannelIdFile.buffer
buffer
Definition: createCoolChannelIdFile.py:12
PhiSectionWidget::Imp::theclass
PhiSectionWidget * theclass
Definition: PhiSectionWidget.cxx:41
PhiSectionWidget::Imp::popup_setCustomNPhi
QAction * popup_setCustomNPhi
Definition: PhiSectionWidget.cxx:82
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
python.SystemOfUnits.gray
int gray
Definition: SystemOfUnits.py:257
lumiFormat.i
int i
Definition: lumiFormat.py:85
PhiSectionWidget::setAllowedNumberOfSectors
void setAllowedNumberOfSectors(QList< int > allowedNSectors, bool allowCustom=false)
Definition: PhiSectionWidget.cxx:831
PhiSectionWidget::setNumberOfSectors
void setNumberOfSectors(int, bool forceAllEnabled=false)
Definition: PhiSectionWidget.cxx:153
beamspotman.n
n
Definition: beamspotman.py:731
PhiSectionWidget::Imp::pen_off
QPen pen_off
Definition: PhiSectionWidget.cxx:53
PhiSectionWidget::state
QByteArray state() const
Definition: PhiSectionWidget.cxx:728
test_pyathena.parent
parent
Definition: test_pyathena.py:15
PhiSectionWidget.h
AnalysisUtils::Delta::R
double R(const INavigable4Momentum *p1, const double v_eta, const double v_phi)
Definition: AnalysisMisc.h:49
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
PhiSectionWidget::Imp::brush_on
QBrush brush_on
Definition: PhiSectionWidget.cxx:54
PhiSectionWidget
Definition: PhiSectionWidget.h:26
VP1HelperClassBase
Definition: VP1HelperClassBase.h:28
PhiSectionWidget::Imp::cacheValid
bool cacheValid
Definition: PhiSectionWidget.cxx:61
PhiSectionWidget::Imp::cachedRanges
QList< VP1Interval > cachedRanges
Definition: PhiSectionWidget.cxx:62
PhiSectionWidget::Imp::popup_menu
QMenu * popup_menu
Definition: PhiSectionWidget.cxx:74
PhiSectionWidget::dragMoveEvent
void dragMoveEvent(QDragMoveEvent *event)
Definition: PhiSectionWidget.cxx:818
PhiSectionWidget::Imp::popup_pasteAction
QAction * popup_pasteAction
Definition: PhiSectionWidget.cxx:79
python.selection.number
number
Definition: selection.py:20
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
PhiSectionWidget::setState
void setState(QByteArray)
Definition: PhiSectionWidget.cxx:747
item
Definition: ItemListSvc.h:43
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
Trk::open
@ open
Definition: BinningType.h:40
python.PyAthena.v
v
Definition: PyAthena.py:154
get_generator_info.version
version
Definition: get_generator_info.py:33
PhiSectionWidget::Imp::ensureMenuInit
void ensureMenuInit()
Definition: PhiSectionWidget.cxx:285
VP1Interval
Definition: VP1Interval.h:23
a
TList * a
Definition: liststreamerinfos.cxx:10
y
#define y
PhiSectionWidget::Imp::popup_enableAllAction
QAction * popup_enableAllAction
Definition: PhiSectionWidget.cxx:75
PhiSectionWidget::Imp::allowedNSectors
QList< int > allowedNSectors
Definition: PhiSectionWidget.cxx:71
copySelective.target
string target
Definition: copySelective.py:37
PhiSectionWidget::Imp::brush_off
QBrush brush_off
Definition: PhiSectionWidget.cxx:55
PhiSectionWidget::Imp::approximateSectorStatusFromRanges
void approximateSectorStatusFromRanges(const QList< VP1Interval > &oldEnabledRanges, QVector< bool > &target)
Definition: PhiSectionWidget.cxx:791
PhiSectionWidget::Imp::addMenuEntriesForSetNPhi
void addMenuEntriesForSetNPhi()
Definition: PhiSectionWidget.cxx:302
PhiSectionWidget::Imp::cachedAllOff
bool cachedAllOff
Definition: PhiSectionWidget.cxx:64
VP1Msg::verbose
static bool verbose()
Definition: VP1Msg.h:31
merge.status
status
Definition: merge.py:17
skel.l1
l1
Definition: skel.GENtoEVGEN.py:398
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
PhiSectionWidget::virtualSectorsEnabled
QVector< bool > virtualSectorsEnabled(int nSectors) const
Definition: PhiSectionWidget.cxx:704
PhiSectionWidget::Imp::item2sector
std::map< QGraphicsEllipseItem *, int > item2sector
Definition: PhiSectionWidget.cxx:45
PhiSectionWidget::virtualSectorEnabled
bool virtualSectorEnabled(int iSector, int nSectors) const
Definition: PhiSectionWidget.cxx:677
PhiSectionWidget::dropEvent
void dropEvent(QDropEvent *event)
Definition: PhiSectionWidget.cxx:468
PhiSectionWidget::dragEnterEvent
void dragEnterEvent(QDragEnterEvent *event)
Definition: PhiSectionWidget.cxx:461
red
@ red
Definition: BinsDiffFromStripMedian.h:18
PhiSectionWidget::Imp::enabledPhiRangesNoCache
QList< VP1Interval > enabledPhiRangesNoCache(const QVector< bool > &secstatus, bool &allOn, bool &allOff) const
Definition: PhiSectionWidget.cxx:510
PhiSectionWidget::enabledPhiRanges
QList< VP1Interval > enabledPhiRanges() const
Definition: PhiSectionWidget.cxx:560
PhiSectionWidget::Imp::checkForChanges
void checkForChanges()
Definition: PhiSectionWidget.cxx:650
PhiSectionWidget::m_d
Imp * m_d
Definition: PhiSectionWidget.h:82
PhiSectionWidget::Imp::popup_disableAllAction
QAction * popup_disableAllAction
Definition: PhiSectionWidget.cxx:76
PhiSectionWidget::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *event)
Definition: PhiSectionWidget.cxx:431
PhiSectionWidget::dragLeaveEvent
void dragLeaveEvent(QDragLeaveEvent *event)
Definition: PhiSectionWidget.cxx:825