ATLAS Offline Software
Loading...
Searching...
No Matches
BunchCrossingToolBase.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
5// STL include(s):
6#include <algorithm>
7#include <functional>
8#include <cmath>
9
10// Local include(s):
12#include "SetPrint.h"
14
15namespace Trig {
16
22 : asg::AsgMetadataTool( name ),
25
27 declareProperty( "MaxBunchSpacing", m_maxBunchSpacing = 150 );
28 declareProperty( "FrontLength", m_frontLength = 300 );
29 declareProperty( "TailLength", m_tailLength = 300 );
30 }
31
33
34 // Check if this is a filled bunch crossing:
35 if( m_filledBunches.find( bcid ) != m_filledBunches.end() ) {
36 return true;
37 } else {
38 return false;
39 }
40 }
41
43
44 // Look for this BCID in the list of bunch trains:
45 std::set< BunchTrain >::const_iterator itr = m_bunchTrains.begin();
46 std::set< BunchTrain >::const_iterator end = m_bunchTrains.end();
47 for( ; itr != end; ++itr ) {
48 if( itr->find( bcid ) != itr->end() ) {
49 return true;
50 }
51 }
52
53 return false;
54 }
55
57
58 // Check if this is an unpaired bunch crossing:
59 if( m_unpairedBunches.find( bcid ) != m_unpairedBunches.end() ) {
60 return true;
61 } else {
62 return false;
63 }
64 }
65
67
68 // Check if this is a filled bunch:
69 std::set< BunchCrossing >::const_iterator itr_fill =
70 m_filledBunches.find( bcid );
71 if( itr_fill != m_filledBunches.end() ) {
72 return true;
73 }
74
75 // Check if this is an unpaired bunch with the bunch in beam 1:
76 std::set< BunchCrossing >::const_iterator itr_unp =
77 m_unpairedBunches.find( bcid );
78 if( ( itr_unp != m_unpairedBunches.end() ) &&
79 ( itr_unp->intensityBeam1() > 0.001 ) ) {
80 return true;
81 } else {
82 return false;
83 }
84 }
85
87
88 // Check if this is a filled bunch:
89 std::set< BunchCrossing >::const_iterator itr_fill =
90 m_filledBunches.find( bcid );
91 if( itr_fill != m_filledBunches.end() ) {
92 return true;
93 }
94
95 // Check if this is an unpaired bunch with the bunch in beam 1:
96 std::set< BunchCrossing >::const_iterator itr_unp =
97 m_unpairedBunches.find( bcid );
98 if( ( itr_unp != m_unpairedBunches.end() ) &&
99 ( itr_unp->intensityBeam2() > 0.001 ) ) {
100 return true;
101 } else {
102 return false;
103 }
104 }
105
107 BeamType type ) const {
108
109 // Check if this is a colliding bunch:
110 std::set< BunchCrossing >::const_iterator itr;
111 if( ( itr = m_filledBunches.find( bcid ) ) != m_filledBunches.end() ) {
112 switch( type ) {
113 case Crossing:
114 if( itr->intensityBeam2() > 0.001 ) {
115 ATH_MSG_WARNING( "Crossing intensity not available, ask for "
116 << "separate beam intensities instead" );
117 return 0.0;
118 } else {
119 return itr->intensityBeam1();
120 }
121 case Beam1:
122 if( std::abs( itr->intensityBeam2() ) < 0.001 ) {
123 ATH_MSG_WARNING( "Separate beam intensities not available, ask "
124 << "for the crossing intensity instead" );
125 return 0.0;
126 } else {
127 return itr->intensityBeam1();
128 }
129 break;
130 case Beam2:
131 return itr->intensityBeam2();
132 break;
133 default:
134 ATH_MSG_ERROR( "Unknown intensity type requested (" << type
135 << ")" );
136 return -1.0;
137 }
138 }
139
140 // Check if this is an unpaired bunch:
141 if( ( itr = m_unpairedBunches.find( bcid ) ) !=
142 m_unpairedBunches.end() ) {
143 switch( type ) {
144 case Beam1:
145 return itr->intensityBeam1();
146 break;
147 case Beam2:
148 return itr->intensityBeam2();
149 break;
150 case Crossing:
151 ATH_MSG_WARNING( "Crossing intensity requested for unpaired bunch ("
152 << "bcid=" << bcid << ")" );
153 return 0.0;
154 default:
155 ATH_MSG_ERROR( "Unknown intensity type requested (" << type
156 << ")" );
157 return -1.0;
158 }
159 }
160
161 // If neither, then its intensity is 0.0 by definition:
162 return 0.0;
163 }
164
167
168 // First the obvious check:
169 if( ! isFilled( bcid ) ) {
170 // Check if it's an unpaired bunch:
171 if( isUnpaired( bcid ) ) {
172 return Unpaired;
173 }
174 // If the previous bunch crossing is the tail of a bunch train:
175 if( ! distanceFromTail( bcid - 1, BunchCrossings ) ) {
176 return FirstEmpty;
177 }
178 // Check if it's in the middle of a bunch train:
179 std::set< BunchTrain >::const_iterator itr = m_bunchTrains.begin();
180 std::set< BunchTrain >::const_iterator end = m_bunchTrains.end();
181 for( ; itr != end; ++itr ) {
182 if( itr->isInside( bcid ) ) {
183 return MiddleEmpty;
184 }
185 }
186 // If none of the above are true, it has to be a "simple" empty bunch:
187 return Empty;
188 }
189
190 // Now we know that the bunch has to be a filled one...
191
192 // If it's not in a train, it has to be a single filled bunch:
193 if( ! isInTrain( bcid ) ) return Single;
194
195 // Let's check if it is close to the front of a bunch train:
196 int distance = distanceFromFront( bcid, NanoSec );
197 if( ( distance >= 0 ) && ( distance <= m_frontLength ) ) {
198 return Front;
199 }
200 // Now let's check if it's close to the tail of a bunch train:
202 if( ( distance >= 0 ) && ( distance <= m_tailLength ) ) {
203 return Tail;
204 }
205
206 // If none of the above are true, it has to be in the middle of a train:
207 return Middle;
208 }
209
238 int
240 BunchDistanceType type ) const {
241
242 // Look for this BCID in the list of bunch trains:
243 std::set< BunchTrain >::const_iterator itr = m_bunchTrains.begin();
244 std::set< BunchTrain >::const_iterator end = m_bunchTrains.end();
245 for( ; itr != end; ++itr ) {
246 BunchTrain::const_iterator element;
247 if( ( element = itr->find( bcid ) ) != itr->end() ) {
248 switch( type ) {
249
250 case NanoSec:
252 *( itr->train_front() ) );
253 break;
254 case BunchCrossings:
255 return ( BunchCrossing( bcid ) - *( itr->train_front() ) );
256 break;
257 case FilledBunches:
258 if( *( itr->train_front() ) > *( itr->train_back() ) ) {
259 if( BunchCrossing( bcid ) <= *( itr->train_back() ) ) {
260 return ( std::count_if( itr->begin(), element,
261 std::bind( std::not_equal_to< BunchCrossing >(),
262 *element, std::placeholders::_1 ) ) +
263 std::count_if( itr->train_front(), itr->end(),
264 std::bind( std::not_equal_to< BunchCrossing >(),
265 *element, std::placeholders::_1 ) ) );
266 } else {
267 return std::count_if( itr->train_front(), element,
268 std::bind( std::not_equal_to< BunchCrossing >(),
269 *element, std::placeholders::_1 ) );
270 }
271 } else {
272 return std::count_if( itr->begin(), element,
273 std::bind( std::not_equal_to< BunchCrossing >(),
274 *element, std::placeholders::_1 ) );
275 }
276 break;
277 default:
278 ATH_MSG_ERROR( "BunchDistanceType not understood!" );
279 return -1;
280 }
281 }
282 }
283
284 // If the bunch crossing is not part of a train:
285 return -1;
286 }
287
317 BunchDistanceType type ) const {
318
319 // Look for this BCID in the list of bunch trains:
320 std::set< BunchTrain >::const_iterator itr = m_bunchTrains.begin();
321 std::set< BunchTrain >::const_iterator end = m_bunchTrains.end();
322 for( ; itr != end; ++itr ) {
323 BunchTrain::const_iterator element;
324 if( ( element = itr->find( bcid ) ) != itr->end() ) {
325 switch( type ) {
326
327 case NanoSec:
328 return BunchCrossing::BUNCH_SPACING * ( *( itr->train_back() ) -
329 BunchCrossing( bcid ) );
330 break;
331 case BunchCrossings:
332 return ( *( itr->train_back() ) - BunchCrossing( bcid ) );
333 break;
334 case FilledBunches:
335 if( *( itr->train_front() ) > *( itr->train_back() ) ) {
336 if( BunchCrossing( bcid ) > *( itr->train_back() ) ) {
337 return ( std::count_if( element, itr->end(),
338 std::bind( std::not_equal_to< BunchCrossing >(),
339 *element, std::placeholders::_1 ) ) +
340 std::count_if( itr->begin(), ++( itr->train_back() ),
341 std::bind( std::not_equal_to< BunchCrossing >(),
342 *element, std::placeholders::_1 ) ) );
343 } else {
344 return std::count_if( element, ++( itr->train_back() ),
345 std::bind( std::not_equal_to< BunchCrossing >(),
346 *element, std::placeholders::_1 ) );
347 }
348 } else {
349 return std::count_if( element, itr->end(),
350 std::bind( std::not_equal_to< BunchCrossing >(),
351 *element, std::placeholders::_1 ) );
352 }
353 break;
354 default:
355 ATH_MSG_ERROR( "BunchDistanceType not understood!" );
356 return -1;
357 }
358 }
359 }
360
361 // If the bunch crossing is not part of a train:
362 return -1;
363 }
364
375 BunchDistanceType type ) const {
376
377 // Find this BCID in the list of bunch trains:
378 std::set< BunchTrain >::const_iterator itr = m_bunchTrains.begin();
379 std::set< BunchTrain >::const_iterator end = m_bunchTrains.end();
380 std::set< BunchTrain >::const_iterator train = m_bunchTrains.end();
381 for( ; itr != end; ++itr ) {
382 if( itr->find( bcid ) != itr->end() ) {
383 train = itr;
384 break;
385 }
386 }
387
388 // If we didn't find this BCID in a train, let's return right away:
389 if( train == end ) {
390 return -1;
391 }
392
393 // Search for the first filled bunch before the front of this train:
394 BunchCrossing train_tail = *( train->train_front() );
395 --train_tail;
396 while( ! isFilled( train_tail ) ) {
397 --train_tail;
398 }
399
400 // Now return the results:
401 switch( type ) {
402
403 case NanoSec:
405 train->train_front()->distance( train_tail );
406 break;
407 case BunchCrossings:
408 return train->train_front()->distance( train_tail );
409 break;
410 default:
411 ATH_MSG_ERROR( "You can only use NanoSec or BunchCrossings for type "
412 "for gapBeforeTrain" );
413 return -1;
414 }
415
416 // This should actually never be reached:
417 return -1;
418 }
419
430 BunchDistanceType type ) const {
431
432 // Find this BCID in the list of bunch trains:
433 std::set< BunchTrain >::const_iterator itr = m_bunchTrains.begin();
434 std::set< BunchTrain >::const_iterator end = m_bunchTrains.end();
435 std::set< BunchTrain >::const_iterator train = m_bunchTrains.end();
436 for( ; itr != end; ++itr ) {
437 if( itr->find( bcid ) != itr->end() ) {
438 train = itr;
439 break;
440 }
441 }
442
443 // If we didn't find this BCID in a train, let's return right away:
444 if( train == end ) {
445 return -1;
446 }
447
448 // Search for the first filled bunch before the front of this train:
449 BunchCrossing train_front = *( train->train_back() );
450 ++train_front;
451 while( ! isFilled( train_front ) ) {
452 ++train_front;
453 }
454
455 // Now return the results:
456 switch( type ) {
457
458 case NanoSec:
460 train_front.distance( *( train->train_back() ) );
461 break;
462 case BunchCrossings:
463 return train_front.distance( *( train->train_back() ) );
464 break;
465 default:
466 ATH_MSG_ERROR( "You can only use NanoSec or BunchCrossings for type "
467 "for gapAfterTrain" );
468 return -1;
469 }
470
471 // This should actually never be reached:
472 return -1;
473 }
474
488 BunchDistanceType dtype,
489 BunchFillType ftype ) const {
490
491 // Construct this "smart" BCID:
492 const BunchCrossing bunch( bcid );
493
494 // Search for the first previous bunch that fulfills the requirement:
495 BunchCrossing prev_bunch( bunch );
496 --prev_bunch;
497 int loop_counter = 0;
498 switch( ftype ) {
499
500 case CollidingBunch:
501 // There should always be filled bunches in the configuration, but
502 // let's make sure that we don't get into an endless loop:
503 while( ( ! isFilled( prev_bunch ) ) &&
504 ( loop_counter < BunchCrossing::MAX_BCID ) ) {
505 --prev_bunch;
506 ++loop_counter;
507 }
508 if( loop_counter == BunchCrossing::MAX_BCID ) {
509 ATH_MSG_ERROR( "Failed to calculate gap before BCID "
510 << bcid << " to a filled bunch! This shouldn't have "
511 << "happened!" );
512 return -1;
513 }
514 break;
515 case UnpairedBunch:
516 // There are no unpaired bunches in every configuration, so make sure
517 // we don't get into an endless loop:
518 while( ( ! isUnpaired( prev_bunch ) ) &&
519 ( loop_counter < BunchCrossing::MAX_BCID ) ) {
520 --prev_bunch;
521 ++loop_counter;
522 }
523 // Return "-1" if there are no unpaired bunches in the configuration:
524 if( loop_counter == BunchCrossing::MAX_BCID ) {
525 return -1;
526 }
527 break;
528 case UnpairedBeam1:
529 // There are no unpaired bunches from beam 1 in every configuration, so
530 // make sure we don't get into an endless loop:
531 while( ( ! ( isUnpaired( prev_bunch ) && isBeam1( prev_bunch ) ) ) &&
532 ( loop_counter < BunchCrossing::MAX_BCID ) ) {
533 --prev_bunch;
534 ++loop_counter;
535 }
536 // Return "-1" if there are no unpaired bunches from beam 1 in the
537 // configuration:
538 if( loop_counter == BunchCrossing::MAX_BCID ) {
539 return -1;
540 }
541 break;
542 case UnpairedBeam2:
543 // There are no unpaired bunches from beam 2 in every configuration, so
544 // make sure we don't get into an endless loop:
545 while( ( ! ( isUnpaired( prev_bunch ) && isBeam2( prev_bunch ) ) ) &&
546 ( loop_counter < BunchCrossing::MAX_BCID ) ) {
547 --prev_bunch;
548 ++loop_counter;
549 }
550 // Return "-1" if there are no unpaired bunches from beam 2 in the
551 // configuration:
552 if( loop_counter == BunchCrossing::MAX_BCID ) {
553 return -1;
554 }
555 break;
556 case EmptyBunch:
557 // There should always be empty bunches in the configuration, but let's
558 // make sure that we don't get into an endless loop:
559 while( ( isFilled( prev_bunch ) || isUnpaired( prev_bunch ) ) &&
560 ( loop_counter < BunchCrossing::MAX_BCID ) ) {
561 --prev_bunch;
562 ++loop_counter;
563 }
564 if( loop_counter == BunchCrossing::MAX_BCID ) {
565 ATH_MSG_ERROR( "Failed to calculate gap before BCID "
566 << bcid << " to an empty bunch! This shouldn't have "
567 << "happened!" );
568 return -1;
569 }
570 break;
571 default:
572 ATH_MSG_ERROR( "Unknown bunch fill type specified: "
573 << ftype );
574 return -1;
575 }
576
577 // Now return the results:
578 switch( dtype ) {
579
580 case NanoSec:
581 return BunchCrossing::BUNCH_SPACING * bunch.gapFrom( prev_bunch );
582 break;
583 case BunchCrossings:
584 return bunch.gapFrom( prev_bunch );
585 break;
586 default:
587 ATH_MSG_ERROR( "You can only use NanoSec or BunchCrossings for type "
588 "for gapBeforeBunch" );
589 return -1;
590 }
591
592 // This should actually never be reached:
593 return -1;
594 }
595
609 BunchDistanceType dtype,
610 BunchFillType ftype ) const {
611
612 // Construct this "smart" BCID:
613 const BunchCrossing bunch( bcid );
614
615 // Search for the first next bunch that fulfills the requirement:
616 BunchCrossing next_bunch( bunch );
617 ++next_bunch;
618 int loop_counter = 0;
619 switch( ftype ) {
620
621 case CollidingBunch:
622 // There should always be filled bunches in the configuration, but
623 // let's make sure that we don't get into an endless loop:
624 while( ( ! isFilled( next_bunch ) ) &&
625 ( loop_counter < BunchCrossing::MAX_BCID ) ) {
626 ++next_bunch;
627 ++loop_counter;
628 }
629 if( loop_counter == BunchCrossing::MAX_BCID ) {
630 ATH_MSG_ERROR( "Failed to calculate gap after BCID "
631 << bcid << " to a filled bunch! This shouldn't have "
632 << "happened!" );
633 return -1;
634 }
635 break;
636 case UnpairedBunch:
637 // There are no unpaired bunches in every configuration, so make sure
638 // we don't get into an endless loop:
639 while( ( ! isUnpaired( next_bunch ) ) &&
640 ( loop_counter < BunchCrossing::MAX_BCID ) ) {
641 ++next_bunch;
642 ++loop_counter;
643 }
644 // Return "-1" if there are no unpaired bunches in the configuration:
645 if( loop_counter == BunchCrossing::MAX_BCID ) {
646 return -1;
647 }
648 break;
649 case UnpairedBeam1:
650 // There are no unpaired bunches from beam 1 in every configuration, so
651 // make sure we don't get into an endless loop:
652 while( ( ! ( isUnpaired( next_bunch ) && isBeam1( next_bunch ) ) ) &&
653 ( loop_counter < BunchCrossing::MAX_BCID ) ) {
654 ++next_bunch;
655 ++loop_counter;
656 }
657 // Return "-1" if there are no unpaired bunches from beam 1 in the
658 // configuration:
659 if( loop_counter == BunchCrossing::MAX_BCID ) {
660 return -1;
661 }
662 break;
663 case UnpairedBeam2:
664 // There are no unpaired bunches from beam 2 in every configuration, so
665 // make sure we don't get into an endless loop:
666 while( ( ! ( isUnpaired( next_bunch ) && isBeam2( next_bunch ) ) ) &&
667 ( loop_counter < BunchCrossing::MAX_BCID ) ) {
668 ++next_bunch;
669 ++loop_counter;
670 }
671 // Return "-1" if there are no unpaired bunches from beam 2 in the
672 // configuration:
673 if( loop_counter == BunchCrossing::MAX_BCID ) {
674 return -1;
675 }
676 break;
677 case EmptyBunch:
678 // There should always be empty bunches in the configuration, but let's
679 // make sure that we don't get into an endless loop:
680 while( ( isFilled( next_bunch ) || isUnpaired( next_bunch ) ) &&
681 ( loop_counter < BunchCrossing::MAX_BCID ) ) {
682 ++next_bunch;
683 ++loop_counter;
684 }
685 if( loop_counter == BunchCrossing::MAX_BCID ) {
686 ATH_MSG_ERROR( "Failed to calculate gap after BCID "
687 << bcid << " to an empty bunch! This shouldn't have "
688 << "happened!" );
689 return -1;
690 }
691 break;
692 default:
693 ATH_MSG_ERROR( "Unknown bunch fill type specified: "
694 << ftype );
695 return -1;
696 }
697
698 // Now return the results:
699 switch( dtype ) {
700
701 case NanoSec:
702 return BunchCrossing::BUNCH_SPACING * bunch.gapTo( next_bunch );
703 break;
704 case BunchCrossings:
705 return bunch.gapTo( next_bunch );
706 break;
707 default:
708 ATH_MSG_ERROR( "You can only use NanoSec or BunchCrossings for type "
709 "for gapBeforeBunch" );
710 return -1;
711 }
712
713 // This should actually never be reached:
714 return -1;
715 }
716
717 std::vector< bool >
719 int bunches ) const {
720
721 // The only thing we have to be careful about is the bunches near the
722 // "turnover" region of the BCIDs. That's why I use the BunchCrossing
723 // class here:
724 std::vector< bool > result;
725 for( int i = 0; i < bunches; ++i ) {
726 result.push_back( isFilled( BunchCrossing( bcid ) -
727 BunchCrossing( i ) ) );
728 }
729
730 return result;
731 }
732
733 std::vector< bool >
735 int bunches ) const {
736
737 // The only thing we have to be careful about is the bunches near the
738 // "turnover" region of the BCIDs. That's why I use the BunchCrossing
739 // class here:
740 std::vector< bool > result;
741 for( int i = 0; i < bunches; ++i ) {
742 result.push_back( isFilled( BunchCrossing( bcid ) +
743 BunchCrossing( i ) ) );
744 }
745
746 return result;
747 }
748
749 std::vector< float >
751 int bunches,
752 BeamType type ) const {
753
754 std::vector< float > result;
755 for( int i = 0; i < bunches; ++i ) {
756 std::set< BunchCrossing >::const_iterator itr =
757 m_filledBunches.find( BunchCrossing( bcid ) - BunchCrossing( i ) );
758 if( itr != m_filledBunches.end() ) {
759 switch( type ) {
760 case Beam1:
761 case Crossing:
762 result.push_back( itr->intensityBeam1() );
763 break;
764 case Beam2:
765 result.push_back( itr->intensityBeam2() );
766 break;
767 default:
768 ATH_MSG_ERROR( "Unknown intensity type requested ("
769 << type << ")" );
770 return result;
771 }
772 } else {
773 result.push_back( 0.0 );
774 }
775 }
776
777 return result;
778 }
779
780 std::vector< float >
782 int bunches,
783 BeamType type ) const {
784
785 std::vector< float > result;
786 for( int i = 0; i < bunches; ++i ) {
787 std::set< BunchCrossing >::const_iterator itr =
788 m_filledBunches.find( BunchCrossing( bcid ) + BunchCrossing( i ) );
789 if( itr != m_filledBunches.end() ) {
790 switch( type ) {
791 case Beam1:
792 case Crossing:
793 result.push_back( itr->intensityBeam1() );
794 break;
795 case Beam2:
796 result.push_back( itr->intensityBeam2() );
797 break;
798 default:
799 ATH_MSG_ERROR( "Unknown intensity type requested ("
800 << type << ")" );
801 return result;
802 }
803 } else {
804 result.push_back( 0.0 );
805 }
806 }
807
808 return result;
809 }
810
812
813 return m_filledBunches.size();
814 }
815
817
818 return m_unpairedBunches.size();
819 }
820
822
823 return m_bunchTrains.size();
824 }
825
826 int
828
829 // Check if there are bunch trains in the current configurations:
830 if( m_bunchTrains.size() ) {
831 switch( type ) {
832 case NanoSec:
833 return m_bunchTrains.begin()->spacing();
834 break;
835 case BunchCrossings:
836 return ( m_bunchTrains.begin()->spacing() /
838 break;
839 case FilledBunches:
840 ATH_MSG_ERROR( "Function should not be called with argument: "
841 "FilledBunches" );
842 return -1;
843 break;
844 default:
845 ATH_MSG_ERROR( "Function called with unknown argument: " << type );
846 return -1;
847 }
848 } else {
849 // Return -1 if there are no bunch trains in the configuration:
850 return -1;
851 }
852
853 ATH_MSG_FATAL( "The code should never reach this line. Check the code!" );
854 return -1;
855 }
856
871 loadSingleBunches( const std::vector< int >& bunches,
872 const std::vector< float >& bunch_int1,
873 const std::vector< float >& bunch_int2 ) {
874
875 // Do a small sanity check:
876 if( ( ( bunches.size() != bunch_int1.size() ) && bunch_int1.size() ) ||
877 ( ( bunches.size() != bunch_int2.size() ) && bunch_int2.size() ) ) {
878 ATH_MSG_ERROR( "Received vectors of different sizes for the bunch "
879 "IDs and bunch intensities\n"
880 "Function can not work like this..." );
881 return StatusCode::FAILURE;
882 }
883 if( ! bunch_int1.size() ) {
884 ATH_MSG_DEBUG( "Not using bunch intensity for the calculation" );
885 }
886 if( ( ! bunch_int2.size() ) && bunch_int1.size() ) {
887 ATH_MSG_DEBUG( "Using 'bunch crossing intensity' for the "
888 "calculation" );
889 }
890
891 //
892 // Calculate the allowed maximum BCID separation between single bunches:
893 //
894 const int maxBCSpacing = bunchSpacing( bunches );
895
896 // Reset the cache:
897 m_filledBunches.clear();
898 m_singleBunches.clear();
899
900 //
901 // Loop over the paired bunch crossings:
902 //
903 std::vector< int >::const_iterator b_itr = bunches.begin();
904 std::vector< int >::const_iterator b_end = bunches.end();
905 std::vector< float >::const_iterator i1_itr = bunch_int1.begin();
906 std::vector< float >::const_iterator i2_itr = bunch_int2.begin();
907 for( ; b_itr != b_end; ++b_itr ) {
908
909 // Evaluate the intensity of this paired bunch:
910 const float intensity1 = bunch_int1.size() ? *i1_itr : 1.0;
911 const float intensity2 = bunch_int2.size() ? *i2_itr : 0.0;
912
913 // It's definitely a filled bunch, so let's remember it as such:
914 m_filledBunches.insert( BunchCrossing( *b_itr, intensity1,
915 intensity2 ) );
916
917 ATH_MSG_VERBOSE( "Evaluating bunch crossing: " << *b_itr );
918
919 //
920 // This expression counts how many of the paired bunches fulfill:
921 //
922 // distance( ref_bcid, bcid ) <= maxBCSpacing
923 //
924 // Since the calculation takes the reference bcid into account as well,
925 // the count is always >= 1. I have to use the specialised
926 // distance(...) function, because a regular
927 //
928 // bcid - maxBCSpacing <= ref_bcid <= bcid + maxBCSpacing
929 //
930 // expression wouldn't give the correct answer at the "turnover" of the
931 // bcid numbering. (When evaluating bcid 1 and
932 // BunchCrossing::MAX_BCID.)
933 //
934 const int neighbours =
935 std::count_if( bunches.begin(), bunches.end(),
936 [ maxBCSpacing, &b_itr ]( int bunch ) {
937 return ( Trig::distance( bunch, *b_itr ) <=
938 maxBCSpacing );
939 } );
940
941 //
942 // Now decide if we want to consider this bunch crossing as a single
943 // bunch or not:
944 //
945 ATH_MSG_VERBOSE( " Bunch neighbours: " << neighbours );
946 if( neighbours == 1 ) {
947 ATH_MSG_VERBOSE( " Bunch crossing " << *b_itr
948 << " seems to be a single bunch" );
949 m_singleBunches.insert( BunchCrossing( *b_itr, intensity1,
950 intensity2 ) );
951 }
952
953 // Only step through the intensity vector(s) if it has some elements:
954 if( bunch_int1.size() ) ++i1_itr;
955 if( bunch_int2.size() ) ++i2_itr;
956 }
957
958 //
959 // Finally some debugging message for the end:
960 //
961 ATH_MSG_DEBUG( "Single bunches found: " << m_singleBunches );
962
963 return StatusCode::SUCCESS;
964 }
965
987 loadBunchTrains( const std::vector< int >& bunches,
988 const std::vector< float >& bunch_int1,
989 const std::vector< float >& bunch_int2 ) {
990
991 // Do a small sanity check:
992 if( ( ( bunches.size() != bunch_int1.size() ) && bunch_int1.size() ) ||
993 ( ( bunches.size() != bunch_int2.size() ) && bunch_int2.size() ) ) {
994 ATH_MSG_ERROR( "Received vectors of different sizes for the bunch "
995 "IDs and bunch intensities\n"
996 "Function can not work like this..." );
997 return StatusCode::FAILURE;
998 }
999 if( ! bunch_int1.size() ) {
1000 ATH_MSG_DEBUG( "Not using bunch intensity for the calculation" );
1001 }
1002 if( ( ! bunch_int2.size() ) && bunch_int1.size() ) {
1003 ATH_MSG_DEBUG( "Using 'bunch crossing intensity' for the "
1004 "calculation" );
1005 }
1006
1007 //
1008 // Calculate the allowed maximum BCID separation between single bunches:
1009 //
1010 const int maxBCSpacing = bunchSpacing( bunches );
1011
1012 // Reset the cache:
1013 m_bunchTrains.clear();
1014
1015 //
1016 // Create a cache of the bunches which have not been identified as a
1017 // single bunch:
1018 //
1019 std::set< BunchCrossing > cache;
1020 std::vector< int >::const_iterator b_itr = bunches.begin();
1021 std::vector< int >::const_iterator b_end = bunches.end();
1022 std::vector< float >::const_iterator i1_itr = bunch_int1.begin();
1023 std::vector< float >::const_iterator i2_itr = bunch_int2.begin();
1024 for( ; b_itr != b_end; ++b_itr ) {
1025 if( std::find( m_singleBunches.begin(), m_singleBunches.end(),
1026 BunchCrossing( *b_itr ) ) == m_singleBunches.end() ) {
1027 cache.insert( BunchCrossing( *b_itr,
1028 ( float )( bunch_int1.size() ? *i1_itr :
1029 1.0 ),
1030 ( float )( bunch_int2.size() ? *i2_itr :
1031 0.0 ) ) );
1032 }
1033 if( bunch_int1.size() ) ++i1_itr;
1034 if( bunch_int2.size() ) ++i2_itr;
1035 }
1036
1037 ATH_MSG_VERBOSE( "Bunches considered for trains: " << cache );
1038
1039 //
1040 // Continue the loop until we have unassigned bunches:
1041 //
1042 while( cache.size() ) {
1043
1044 // Create a new bunch train object:
1045 BunchTrain bt;
1046 bt.insert( *cache.begin() );
1047
1048 // Try finding attachable bunches until no other attachable bunch can
1049 // be found:
1050 size_t prev_size = 0;
1051 while( prev_size != cache.size() ) {
1052
1053 // Let's remember the size of the cache:
1054 prev_size = cache.size();
1055
1056 // Find all the bunches that should be a part of this train:
1057 std::set< BunchCrossing >::const_iterator c_itr = cache.begin();
1058 std::set< BunchCrossing >::const_iterator c_end = cache.end();
1059 for( ; c_itr != c_end; ++c_itr ) {
1060 if( bt.distance( *c_itr ) <= maxBCSpacing ) {
1061 ATH_MSG_VERBOSE( "Adding BunchCrossing " << *c_itr
1062 << " to Bunch Train " << bt );
1063 bt.insert( *c_itr );
1064 }
1065 }
1066
1067 // Now remove the selected bunches from the cache:
1068 BunchTrain::const_iterator itr = bt.begin();
1069 BunchTrain::const_iterator end = bt.end();
1070 for( ; itr != end; ++itr ) {
1071 cache.erase( *itr );
1072 }
1073 }
1074
1075 // Finally, remember this train:
1076 if( ! bt.validate() ) {
1077 ATH_MSG_ERROR( "Found a strange bunch train: " << bt );
1078 ATH_MSG_ERROR( "Keeping in it the list of trains!" );
1079 }
1080 m_bunchTrains.insert( bt );
1081 }
1082
1083 //
1084 // Check if the spacing in the bunch trains is the same. (It should be for
1085 // all real configurations.)
1086 //
1087 std::set< BunchTrain >::const_iterator train_itr = m_bunchTrains.begin();
1088 std::set< BunchTrain >::const_iterator train_end = m_bunchTrains.end();
1089 int spacing = -1;
1090 for( ; train_itr != train_end; ++train_itr ) {
1091 if( spacing < 0 ) {
1092 spacing = train_itr->spacing();
1093 continue;
1094 }
1095 if( train_itr->spacing() != spacing ) {
1096 ATH_MSG_WARNING( "The spacing seems to be different between the "
1097 "trains" );
1098 ATH_MSG_WARNING( "This should probably not happen" );
1099 }
1100 }
1101
1102 ATH_MSG_DEBUG( "Bunch trains found: " << m_bunchTrains );
1103
1104 return StatusCode::SUCCESS;
1105 }
1106
1118 loadUnpairedBunches( const std::vector< int >& beam1,
1119 const std::vector< int >& beam2,
1120 const std::vector< float >& bunch_int1,
1121 const std::vector< float >& bunch_int2 ) {
1122
1123 // Do a small sanity check:
1124 if( ( ( beam1.size() != bunch_int1.size() ) && bunch_int1.size() ) ||
1125 ( ( beam2.size() != bunch_int2.size() ) && bunch_int2.size() ) ) {
1126 ATH_MSG_ERROR( "Received vectors of different sizes for the bunch "
1127 "IDs and bunch intensities\n"
1128 "Function can not work like this..." );
1129 return StatusCode::FAILURE;
1130 }
1131 if( ( ! bunch_int1.size() ) && ( ! bunch_int2.size() ) ) {
1132 ATH_MSG_DEBUG( "Not using bunch intensity for the calculation" );
1133 }
1134
1135 // Reset the cache:
1136 m_unpairedBunches.clear();
1137
1138 //
1139 // Add the unpaired bunches from beam 1:
1140 //
1141 std::vector< int >::const_iterator b_itr = beam1.begin();
1142 std::vector< int >::const_iterator b_end = beam1.end();
1143 std::vector< float >::const_iterator i_itr = bunch_int1.begin();
1144 for( ; b_itr != b_end; ++b_itr ) {
1145
1146 // Evaluate the intensity of this unpaired bunch:
1147 const float intensity = bunch_int1.size() ? *i_itr : 1.0;
1148
1149 // Nothing fancy to do, just put it in the cache:
1150 m_unpairedBunches.insert( BunchCrossing( *b_itr, intensity, 0.0 ) );
1151
1152 // Only step through the intensity vector if it has some elements:
1153 if( bunch_int1.size() ) ++i_itr;
1154 }
1155
1156 //
1157 // Add the unpaired bunches from beam 2:
1158 //
1159 b_itr = beam2.begin();
1160 b_end = beam2.end();
1161 i_itr = bunch_int2.begin();
1162 for( ; b_itr != b_end; ++b_itr ) {
1163
1164 // Evaluate the intensity of this unpaired bunch:
1165 const float intensity = bunch_int2.size() ? *i_itr : 1.0;
1166
1167 // Check if this BCID is already known as an unpaired BCID:
1168 std::set< BunchCrossing >::iterator itr =
1169 m_unpairedBunches.find( *b_itr );
1170 if( itr != m_unpairedBunches.end() ) {
1171 // Modify the BCID not to correspond to a particular beam. Most
1172 // implementations don't treat beam 1 and beam 2 separately.
1173 BunchCrossing bc( *itr );
1174 bc.setIntensityBeam2( intensity );
1175 m_unpairedBunches.erase( itr );
1176 m_unpairedBunches.insert( bc );
1177 } else {
1178 // Nothing fancy to do, just put it in the cache:
1179 m_unpairedBunches.insert( BunchCrossing( *b_itr, 0.0, intensity ) );
1180 }
1181
1182 // Only step through the intensity vector if it has some elements:
1183 if( bunch_int2.size() ) ++i_itr;
1184 }
1185
1186 //
1187 // Finally some debugging message for the end:
1188 //
1189 ATH_MSG_DEBUG( "Unpaired bunches found: " << m_unpairedBunches );
1190
1191 return StatusCode::SUCCESS;
1192 }
1193
1200
1201 ATH_MSG_INFO( "No. of coll. bunches : " << m_filledBunches.size() );
1202 ATH_MSG_INFO( "No. of unpaired bunches: " << m_unpairedBunches.size() );
1203 ATH_MSG_INFO( "No. of bunch trains : " << m_bunchTrains.size() );
1204 if( m_bunchTrains.size() ) {
1205 ATH_MSG_INFO( "Bunch spacing in trains: "
1206 << m_bunchTrains.begin()->spacing()
1207 << " ns" );
1208 }
1209
1210 return;
1211 }
1212
1226 bunchSpacing( const std::vector< int >& bunches ) const {
1227
1228 // The maximum BC spacing to start from.
1229 const int maxSpacing = m_maxBunchSpacing / BunchCrossing::BUNCH_SPACING;
1230
1231 // Iterate downwards from the maximum spacing, searching for the minimum
1232 // spacing with which bunches exist.
1233 int result = maxSpacing;
1234 for( ; result > 0; --result ) {
1235
1236 // Test how many bunches have neighbors inside of the current window.
1237 const int nbunches =
1238 std::count_if( bunches.begin(), bunches.end(),
1239 count_bunch_neighbors( bunches, result ) );
1240 ATH_MSG_VERBOSE( "Number of bunches with " << result
1241 << " BC neighbors: " << nbunches );
1242
1243 // If none of them do, then we're finished.
1244 if( ! nbunches ) {
1245 // If we're not at the max spacing anymore, then it means that in
1246 // the previous step there were still bunches with neighbors in this
1247 // window. That's the spacing we need then.
1248 //
1249 // But if we're still at the maximum spacing, then let's just keep
1250 // that as the final answer.
1251 if( result != maxSpacing ) {
1252 ++result;
1253 }
1254 break;
1255 }
1256 }
1257 // If we went down to 0, then the right answer is 1. This is just how this
1258 // algorithm works...
1259 if( result == 0 ) {
1260 result = 1;
1261 }
1262 ATH_MSG_DEBUG( "Bunch spacing: " << result << " BCs" );
1263
1264 // Return the smallest spacing found:
1265 return result;
1266 }
1267
1268} // namespace Trig
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
virtual BunchCrossingType bcType(bcid_type bcid) const
Get the type of the specific bunch crossing.
virtual bool isBeam1(bcid_type bcid) const
Function deciding if there was a bunch from "beam 1" in this bunch crossing.
std::set< Trig::BunchCrossing > m_singleBunches
Internal list of single bunches.
StatusCode loadBunchTrains(const std::vector< int > &bunches, const std::vector< float > &bunch_int1=std::vector< float >(), const std::vector< float > &bunch_int2=std::vector< float >())
Interpret the configuration for bunch trains.
virtual int gapBeforeBunch(bcid_type bcid, BunchDistanceType dtype=NanoSec, BunchFillType ftype=CollidingBunch) const
Gap before a particular bunch.
virtual std::vector< float > bunchIntInFront(bcid_type bcid, int bunches=10, BeamType type=Crossing) const
Function returning the intensities of the bunch crossings before the reference.
int bunchSpacing(const std::vector< int > &bunches) const
Get the apparent bunch spacing in the current configuration.
virtual unsigned int numberOfUnpairedBunches() const
Get the number of unpaired bunches in the current configuration.
virtual int gapBeforeTrain(bcid_type bcid, BunchDistanceType type=NanoSec) const
Gap before the train this BCID is in.
virtual bool isFilled(bcid_type bcid) const
The simplest query: Is the bunch crossing filled or not?
virtual std::vector< float > bunchIntAfter(bcid_type bcid, int bunches=10, BeamType type=Crossing) const
Function returning the intensities of the bunch crossings after the reference.
virtual int gapAfterBunch(bcid_type bcid, BunchDistanceType dtype=NanoSec, BunchFillType ftype=CollidingBunch) const
Gap after a particular bunch.
virtual int distanceFromFront(bcid_type bcid, BunchDistanceType type=NanoSec) const
The distance of the specific bunch crossing from the front of the train.
virtual bool isUnpaired(bcid_type bcid) const
Function deciding if a given bunch crossing has an unpaired bunch.
BunchCrossingToolBase(const std::string &name="BunchCrossingToolBase")
Default constructor.
virtual unsigned int numberOfFilledBunches() const
Get the number of filled bunches in the current configuration.
std::set< Trig::BunchCrossing > m_unpairedBunches
Internal list of unpaired bunches.
virtual std::vector< bool > bunchesInFront(bcid_type bcid, int bunches=10) const
Function returning whether the previous bunches were filled, and how.
virtual int distanceFromTail(bcid_type bcid, BunchDistanceType type=NanoSec) const
The distance of the specific bunch crossing from the tail of the train.
virtual float bcIntensity(bcid_type bcid, BeamType type=Crossing) const
Function returning the "intensity" of a given bunch crossing.
virtual bool isBeam2(bcid_type bcid) const
Function deciding if there was a bunch from "beam 2" in this bunch crossing.
virtual unsigned int numberOfBunchTrains() const
Get the number of the bunch trains in the current configuration.
virtual int gapAfterTrain(bcid_type bcid, BunchDistanceType type=NanoSec) const
Gap after the train this BCID is in.
StatusCode loadSingleBunches(const std::vector< int > &bunches, const std::vector< float > &bunch_int1=std::vector< float >(), const std::vector< float > &bunch_int2=std::vector< float >())
Interpret the configuration for single bunches.
void printConfig() const
Function printing the configuration of the tool.
int m_maxBunchSpacing
The maximum bunch spacing that the tool should consider.
virtual int bunchTrainSpacing(BunchDistanceType type=NanoSec) const
Get the bunch spacing in the trains.
std::set< Trig::BunchCrossing > m_filledBunches
List of colliding bunches.
int m_frontLength
Length of the "front" of a bunch train.
StatusCode loadUnpairedBunches(const std::vector< int > &beam1, const std::vector< int > &beam2, const std::vector< float > &bunch_int1=std::vector< float >(), const std::vector< float > &bunch_int2=std::vector< float >())
Interpret the configuration for unpaired bunches.
virtual std::vector< bool > bunchesAfter(bcid_type bcid=0, int bunches=10) const
Function returning whether the following bunches were filled, and how.
std::set< Trig::BunchTrain > m_bunchTrains
Internal list of bunch trains.
virtual bool isInTrain(bcid_type bcid) const
Function deciding if a given bunch crossing is in a filled train.
int m_tailLength
Length of the "tail" of a bunch train.
A smart integer class representing bunch crossings.
int gapTo(const BunchCrossing &bc) const
Distance to a following bunch crossing.
int distance(const BunchCrossing &bc) const
The distance from another bunch crossing.
int gapFrom(const BunchCrossing &bc) const
Distance from a previous bunch crossing.
static const int MAX_BCID
The maximum number of bunches that can be in the LHC.
static const int BUNCH_SPACING
Minimum spacing between the bunches, in nanoseconds.
void setIntensityBeam2(float intensity)
Set the "intensity" of beam 2 in this bunch crossing.
A smart set of BunchCrossing objects.
Definition BunchTrain.h:35
bool validate()
Check the spacing of the bunches in the train.
int distance(const BunchCrossing &bc) const
"Distance" of a bunch crossing from this bunch train
BunchFillType
Enumeration specifying what kind of bunch to use in the gap functions.
@ CollidingBunch
The gap should be calculated wrt. the closest colling bunch.
@ UnpairedBunch
The gap should be calculated wrt. the closest unpaired bunch.
@ EmptyBunch
The gap should be calculated wrt. the closest empty bunch.
@ UnpairedBeam1
The gap should be calculated wrt.
@ UnpairedBeam2
The gap should be calculated wrt.
unsigned int bcid_type
Declare the interface that this class provides.
BunchDistanceType
Enumeration specifying the units in which to expect the bunch distance type.
@ BunchCrossings
Distance in units of 25 nanoseconds.
@ NanoSec
Distance in nanoseconds.
@ FilledBunches
Distance in units of filled bunches (depends on filling scheme)
BunchCrossingType
Simplified type for a given bunch crossing.
@ Unpaired
This is an unpaired bunch (either beam1 or beam2)
@ FirstEmpty
The first empty bunch after a train.
@ Tail
The BCID belongs to the last few bunces in a train.
@ Empty
An empty bunch far away from filled bunches.
@ Front
The BCID belongs to the first few bunches in a train.
@ Middle
The BCID belongs to the middle bunches in a train.
@ Single
This is a filled, single bunch (not in a train)
@ MiddleEmpty
An empty BCID in the middle of a train.
BeamType
Types of the return values of the bcIntensity function.
@ Beam1
The returned intensity should be for "beam 1".
@ Beam2
The returned intensity should be for "beam 2".
@ Crossing
The returned intensity should describe the BC.
Functor counting how many neighbors a given bunch crossing has.
AsgMetadataTool(const std::string &name)
Normal ASG tool constructor with a name.
The common trigger namespace for trigger analysis tools.
int distance(const BunchCrossing bc1, const BunchCrossing bc2)
I need this function only for technical reasons.