Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 14:22:02

0001 //-------------------------------------------------------------
0002 //
0003 //   Class: DTTracoChip
0004 //
0005 //   Description: Implementation of TRACO
0006 //                trigger algorithm
0007 //
0008 //
0009 //   Author List:
0010 //   SV 4/II/2003
0011 //   Modifications:
0012 //   22/VI/04 SV : last trigger code update
0013 //   16/I/07  SV : new DTConfig update
0014 //   3/IV/07  SV : setTracoAcceptance moved from card to chip
0015 //   30/10/09 SV : lut parameters from DB are used in code
0016 //   110208 SV   : TRACO hardware bug included
0017 //------------------------------------------------------------
0018 
0019 //-----------------------
0020 // This Class's Header --
0021 //-----------------------
0022 #include "L1Trigger/DTTraco/interface/DTTracoChip.h"
0023 
0024 //-------------------------------
0025 // Collaborating Class Headers --
0026 //-------------------------------
0027 #include "L1Trigger/DTBti/interface/DTBtiTrigData.h"
0028 #include "L1Trigger/DTTraco/interface/DTTracoCand.h"
0029 #include "L1Trigger/DTTraco/interface/DTTracoCard.h"
0030 #include "L1Trigger/DTTraco/interface/DTTracoTrig.h"
0031 #include "L1Trigger/DTTraco/interface/DTTracoTrigData.h"
0032 #include "L1Trigger/DTTriggerServerTheta/interface/DTTSTheta.h"
0033 #include "L1TriggerConfig/DTTPGConfig/interface/BitArray.h"
0034 
0035 //---------------
0036 // C++ Headers --
0037 //---------------
0038 #include <algorithm>
0039 #include <cmath>
0040 #include <iostream>
0041 #include <string>
0042 
0043 //----------------
0044 // Constructors --
0045 //----------------
0046 
0047 DTTracoChip::DTTracoChip(DTTracoCard *card, int n, DTConfigTraco *conf) : _card(card), _config(conf) {
0048   _geom = _card->geom();
0049 
0050   // n=traco number 1,2,...
0051   if (config()->debug() == 4) {
0052     std::cout << "DTTracoChip constructor called for TRACO number " << n << std::endl;
0053   }
0054 
0055   // set acceptances from CMSSW geometry
0056   setTracoAcceptances();
0057 
0058   // reserve the appropriate amount of space for vectors
0059   int i = 0;
0060   for (i = 0; i < DTConfigTraco::NSTEPL - DTConfigTraco::NSTEPF; i++) {
0061     _innerCand[i].reserve(DTConfigTraco::NBTITC);
0062     _outerCand[i].reserve(3 * DTConfigTraco::NBTITC);
0063     _tracotrig[i].reserve(2);
0064   }
0065 
0066   // the identifier
0067   DTChamberId sid = _geom->statId();
0068   _id = DTTracoId(sid, n);
0069 
0070   // Flags for LTS
0071   _bxlts.zero();
0072   for (int is = 0; is < DTConfigTraco::NSTEPL - DTConfigTraco::NSTEPF + 1; is++) {
0073     _flag[is].zero();
0074   }
0075 
0076   // debugging
0077   if (config()->debug() == 4) {
0078     std::cout << "CMS position:" << CMSPosition() << std::endl;
0079     std::cout << " psiRad=" << psiRad() << " KRad=" << KRad() << std::endl;
0080   }
0081 
0082   // init traco parameters from traco config file
0083   _krad = config()->KRAD();
0084   _btic = config()->BTIC();
0085 
0086   // offset from geometry (x1-x3 FE view): converted from cm to ST units (0.9999
0087   // for rounding)
0088   _ibtioff = static_cast<int>(config()->BTIC() / (_geom->cellPitch()) * (_geom->phiSLOffset() / 0.9999));
0089 
0090   // 091030 SV lut parameters from DB
0091   // SV 08/12/12 : added flag for computing luts from DB parameters
0092   if (_card->lutFromDBFlag() == 1) {
0093     // int board = int( (n-1)/4 );
0094     // int traco = int(fmod( double(n-1),4.));
0095     // 110208 SV for TRACO hardware bug included SL_shift
0096     // SL shift
0097     float xBTI1_3 = _geom->localPosition(DTBtiId(DTSuperLayerId(sid.wheel(), sid.station(), sid.sector(), 3), 1)).x();
0098     float xBTI1_1 = _geom->localPosition(DTBtiId(DTSuperLayerId(sid.wheel(), sid.station(), sid.sector(), 1), 1)).x();
0099     float SL_shift = xBTI1_3 - xBTI1_1;
0100 
0101     _lutsCCB = new Lut(_card->config_luts(), n, SL_shift);
0102     _luts = nullptr;
0103   } else
0104   // this is always the case with new DTConfig SV 15/I/2007
0105   // if( config()->trigSetupGeom()==0 ){
0106   {
0107     _luts = nullptr;
0108     _lutsCCB = nullptr;
0109   }
0110   /*
0111     //SV 21/V/03 for testbeam purpose: parameters from hardware setup
0112     if(config()->trigSetupGeom()==1){
0113       //init traco parameters
0114       _dd=config()->DD();
0115       _krad=config()->KRAD();
0116       _btic=config()->BTIC();
0117       _ibtioff=config()->IBTIOFF();
0118 
0119       //const char* testfile = "traco";   //FIXTB
0120       std::string  testfile = "traco_";
0121       int it = number() - 4 - 1;
0122       if(it<10)
0123         testfile += it+'0';
0124       if(it>9){
0125         testfile += int(float(it)/10.0) + '0';                //add decimal char
0126         testfile += int(fmod(float(it),float(10))) + '0';     //add unit char
0127       }
0128 
0129       //const char* name = testfile;
0130       if(config()->debug()==4)
0131         std::cout << "Loading " << testfile << " luts for traco " << number() <<
0132     std::endl; _luts = new DTTracoLUTs(testfile); _luts->reset(); _luts->load();
0133       if(config()->debug()==4)
0134         _luts->print();
0135     }//end hardware setup
0136 
0137     //TB 2004 setup : luts from minicrate ccb equations
0138     if(config()->trigSetupGeom()==2){
0139       int board = int( (n-1)/4 );
0140       int traco = fmod( double(n-1),4. );
0141       _lutsCCB = new Lut(sid.station(),board,traco);
0142       // 091030 SV this constructur is obsolete now, use setForTestBeam instead
0143     }//end TB2004
0144   */
0145 }
0146 
0147 DTTracoChip::DTTracoChip(const DTTracoChip &traco)
0148     : _geom(traco._geom), _id(traco._id), _card(traco._card), _luts(traco._luts) {
0149   int i = 0;
0150   for (i = 0; i < DTConfigTraco::NSTEPL - DTConfigTraco::NSTEPF; i++) {
0151     _innerCand[i].reserve(DTConfigTraco::NBTITC);
0152     std::vector<DTTracoCand>::const_iterator p;
0153     for (p = traco._innerCand[i].begin(); p < traco._innerCand[i].end(); p++) {
0154       _innerCand[i].push_back(*p);
0155     }
0156     _outerCand[i].reserve(3 * DTConfigTraco::NBTITC);
0157     for (p = traco._outerCand[i].begin(); p < traco._outerCand[i].end(); p++) {
0158       _outerCand[i].push_back(*p);
0159     }
0160     _tracotrig[i].reserve(2);
0161     std::vector<DTTracoTrig *>::const_iterator p1;
0162     for (p1 = traco._tracotrig[i].begin(); p1 < traco._tracotrig[i].end(); p1++) {
0163       _tracotrig[i].push_back(*p1);
0164     }
0165   }
0166   _bxlts = traco._bxlts;
0167   for (int is = 0; is < DTConfigTraco::NSTEPL - DTConfigTraco::NSTEPF + 1; is++) {
0168     _flag[is] = traco._flag[is];
0169   }
0170 }
0171 
0172 //--------------
0173 // Destructor --
0174 //--------------
0175 DTTracoChip::~DTTracoChip() {
0176   clear();
0177   /*
0178   if(config()->trigSetupGeom()==1){
0179     _luts->reset();
0180     delete _luts;
0181   }
0182 
0183   if(config()->trigSetupGeom()==2)
0184     delete _lutsCCB;
0185   */
0186 
0187   if (_card->lutFromDBFlag() == 1)
0188     delete _lutsCCB;
0189 }
0190 
0191 //--------------
0192 // Operations --
0193 //--------------
0194 
0195 DTTracoChip &DTTracoChip::operator=(const DTTracoChip &traco) {
0196   if (this != &traco) {
0197     _geom = traco._geom;
0198     _id = traco._id;
0199     _card = traco._card;
0200     int i = 0;
0201     for (i = 0; i < DTConfigTraco::NSTEPL - DTConfigTraco::NSTEPF; i++) {
0202       _innerCand[i].reserve(DTConfigTraco::NBTITC);
0203       std::vector<DTTracoCand>::const_iterator p;
0204       for (p = traco._innerCand[i].begin(); p < traco._innerCand[i].end(); p++) {
0205         _innerCand[i].push_back(*p);
0206       }
0207       _outerCand[i].reserve(3 * DTConfigTraco::NBTITC);
0208       for (p = traco._outerCand[i].begin(); p < traco._outerCand[i].end(); p++) {
0209         _outerCand[i].push_back(*p);
0210       }
0211       _tracotrig[i].reserve(2);
0212       std::vector<DTTracoTrig *>::const_iterator p1;
0213       for (p1 = traco._tracotrig[i].begin(); p1 < traco._tracotrig[i].end(); p1++) {
0214         _tracotrig[i].push_back(*p1);
0215       }
0216     }
0217     _bxlts = traco._bxlts;
0218     for (int is = 0; is < DTConfigTraco::NSTEPL - DTConfigTraco::NSTEPF + 1; is++) {
0219       _flag[is] = traco._flag[is];
0220     }
0221   }
0222   return *this;
0223 }
0224 
0225 void DTTracoChip::clear() {
0226   std::vector<DTTracoTrig *>::iterator p1;
0227   for (int is = 0; is < DTConfigTraco::NSTEPL - DTConfigTraco::NSTEPF + 1; is++) {
0228     for (p1 = _tracotrig[is].begin(); p1 < _tracotrig[is].end(); p1++) {
0229       delete (*p1);
0230     }
0231     _tracotrig[is].clear();
0232     _innerCand[is].clear();
0233     _outerCand[is].clear();
0234     _flag[is].zero();
0235   }
0236   _bxlts.zero();
0237 }
0238 
0239 void DTTracoChip::run() {
0240   // Debugging...
0241   if (config()->debug() > 1) {
0242     std::cout << "DTTracoChip::run: Processing TRACO " << _id.traco() << std::endl;
0243   }
0244   // End debugging
0245 
0246   int maxtc = static_cast<int>(ceil(float(geom()->nCell(1)) / float(DTConfigTraco::NBTITC)));
0247 
0248   if (_id.traco() < 1 || _id.traco() > maxtc) {
0249     if (config()->debug() == 4)
0250       std::cout << "DTTracoChip::run: wrong TRACO number " << _id.traco() << std::endl;
0251     return;
0252   }
0253 
0254   // Loop on step
0255   for (int is = DTConfigTraco::NSTEPF; is <= DTConfigTraco::NSTEPL; is++) {
0256     if (config()->debug() > 1) {
0257       std::cout << "\n STEP: " << is << std::endl;
0258       std::cout << " ================" << std::endl;
0259     }
0260 
0261     // skip if no cand. at this step
0262     if (_innerCand[is - DTConfigTraco::NSTEPF].empty() && _outerCand[is - DTConfigTraco::NSTEPF].empty())
0263       continue;
0264 
0265     // Debugging...
0266     if (config()->debug() == 4) {
0267       std::cout << " --> "
0268                 << _innerCand[is - DTConfigTraco::NSTEPF].size() + _outerCand[is - DTConfigTraco::NSTEPF].size();
0269       std::cout << " candidates " << std::endl;
0270     }
0271     // End debugging
0272 
0273     // Multiple trigger detection between consecutive TRACO's
0274     setFlag(is);
0275 
0276     // check if there is a H in bx for LVALIDIFH flag
0277     if (config()->LVALIDIFH()) {
0278       for (unsigned int e = 0; e < _innerCand[is - DTConfigTraco::NSTEPF].size(); e++) {
0279         if (_innerCand[is - DTConfigTraco::NSTEPF][e].BtiTrig()->code() == 8) {
0280           _flag[is - DTConfigTraco::NSTEPF].set(9);
0281           break;
0282         }
0283       }
0284       for (unsigned int e = 0; e < _outerCand[is - DTConfigTraco::NSTEPF].size(); e++) {
0285         if (_outerCand[is - DTConfigTraco::NSTEPF][e].BtiTrig()->code() == 8) {
0286           _flag[is - DTConfigTraco::NSTEPF].set(9);
0287           break;
0288         }
0289       }
0290     }
0291 
0292     // Loop over first/second tracks
0293     // for(int itk=0; itk < DTConfigTraco::NMAXCAND; itk++){
0294     // FIX this hardcoded 2!!
0295     for (int itk = 0; itk < 2; itk++) {
0296       // Get the best inner and outer segments
0297       if (config()->debug() == 4)
0298         std::cout << "Inner:" << std::endl;
0299       DTTracoCand *inner = bestCand(itk, _innerCand[is - DTConfigTraco::NSTEPF]);
0300       if (config()->debug() == 4)
0301         std::cout << "Outer:" << std::endl;
0302       DTTracoCand *outer = bestCand(itk, _outerCand[is - DTConfigTraco::NSTEPF]);
0303 
0304       // debug
0305       if (config()->debug() > 1) {
0306         if (inner || outer)
0307           std::cout << "Best candidates for track " << itk + 1 << " are:" << std::endl;
0308         if (inner) {
0309           std::cout << "inner->";
0310           inner->print();
0311         }
0312         if (outer) {
0313           std::cout << "outer->";
0314           outer->print();
0315         }
0316       }
0317 
0318       // Skip to next step if no suitable candidates found
0319       if (inner == nullptr && outer == nullptr)
0320         break;
0321 
0322       // suppression of LTRIG on BTI close to selected HTRIG
0323       // SV 24/IX/03 : AND suppression of LTRIG close to H in adiacent Traco
0324       // SV 31/III/03 : test : only if htprf is off--> NO, it's worse
0325       // if( config()->prefHtrig(0) && config()->prefHtrig(1) ){
0326       if (inner) {
0327         DoAdjBtiLts(inner, _innerCand[is - DTConfigTraco::NSTEPF]);
0328       }
0329       if (outer) {
0330         DoAdjBtiLts(outer, _outerCand[is - DTConfigTraco::NSTEPF]);
0331       }
0332       //}
0333 
0334       // set candidates unusable by further steps
0335       if (inner)
0336         inner->setUsed();
0337       if (outer)
0338         outer->setUsed();
0339       // Create a new TRACO trigger with preview for TS
0340       DTTracoTrig *tct = setPV(itk, inner, outer);
0341 
0342       // skip if no TRACO trigger has been created with this trigger
0343       if (!tct)
0344         break;  // something nasty happened. Go to next step
0345 
0346       // try a correlation between segments
0347       int stored = 0;
0348       if (inner && outer) {
0349         stored = storeCorr(tct, inner, outer, itk);
0350       }
0351 
0352       if (!stored) {
0353         // No suitable candidate found or no correlation possible
0354         // Fill single trigger
0355         stored = storeUncorr(tct, inner, outer, itk);
0356       }
0357 
0358       // if trigger has been filled store it in TRACO, otherway delete it
0359       if (stored) {
0360         addTrig(is, tct);
0361       } else {
0362         delete tct;
0363         // break;-> II track is computed even if no I track found...
0364       }
0365 
0366     }  // end loop on first/second track
0367 
0368     // Inhibit second track at previous bunch crossing
0369     if (config()->debug() == 4)
0370       std::cout << "Checking overlap I-II track..." << std::endl;
0371     if (!_tracotrig[is - DTConfigTraco::NSTEPF].empty() && is > DTConfigTraco::NSTEPF &&
0372         (_tracotrig[is - DTConfigTraco::NSTEPF])[0]->isFirst()) {        // I track at bx
0373       if (nTrig(is - 1) > 0) {                                           // there is a track at bx-1
0374         if (!(trigger(is - 1, 1)->isFirst()) ||                          // trig 1 is II track
0375             (nTrig(is - 1) == 2 && !(trigger(is - 1, 2)->isFirst()))) {  // trig 2 is II track
0376           raiseOverlap(is);
0377           if (config()->debug() == 4) {
0378             std::cout << "II track at step " << std::hex << is - 1 << std::dec << "marked rej." << std::endl;
0379             std::cout << "I track overlap flag at step " << std::hex << is << std::dec << " setted" << std::endl;
0380           }
0381         }
0382       }
0383     }
0384     // debug...
0385     for (int isd = 0; isd <= DTConfigTraco::NSTEPL - DTConfigTraco::NSTEPF + 1; isd++)
0386       if (config()->debug() == 4) {
0387         std::cout << "overlap flag step = " << isd + DTConfigTraco::NSTEPF << "  " << _flag[isd].element(1)
0388                   << std::endl;
0389       }
0390     // debugging...
0391     if (config()->debug() > 0) {
0392       if (nTrig(is) > 0) {
0393         for (int cc = 1; cc <= nTrig(is); cc++) {
0394           trigger(is, cc)->print();
0395         }
0396       }
0397     }  // end debugging
0398   }    // end loop on step
0399 }
0400 
0401 void DTTracoChip::raiseOverlap(int step) {
0402   _flag[step - DTConfigTraco::NSTEPF].set(1);      // overlap flag raised
0403   _flag[step - DTConfigTraco::NSTEPF - 1].set(2);  // mark II rej.
0404 }
0405 
0406 void DTTracoChip::setFlag(int step, int ext) {
0407   if (ext == 0) {
0408     // this is the original: flags from card
0409     DTTracoChip *prevTraco = _card->getTRACO(_id.traco() - 1);
0410     if (prevTraco != nullptr) {
0411       if (prevTraco->edgeBTI(step, 1, 2))
0412         _flag[step - DTConfigTraco::NSTEPF].set(3);
0413       if (prevTraco->edgeBTI(step, 2, 2))
0414         _flag[step - DTConfigTraco::NSTEPF].set(5);
0415     }
0416     DTTracoChip *nextTraco = _card->getTRACO(_id.traco() + 1);
0417     if (nextTraco != nullptr) {
0418       if (nextTraco->edgeBTI(step, 1, 1))
0419         _flag[step - DTConfigTraco::NSTEPF].set(4);
0420       if (nextTraco->edgeBTI(step, 2, 1))
0421         _flag[step - DTConfigTraco::NSTEPF].set(6);
0422     }
0423   } else {
0424     // SV III/03: flags from input EXT: only for testing purpose
0425     for (int i = 0; i < 6; i++) {
0426       int ibit = ext >> i;
0427       if (ibit & 0x01)  // bit i+1 -> flag 3,4,5,6 : IL,IR,OL,OR
0428         _flag[step - DTConfigTraco::NSTEPF].set(i + 1 + 2);
0429     }
0430   }
0431 
0432   // debug:
0433   if (config()->debug() == 4) {
0434     std::cout << "Flags set for bx=" << step << std::endl;
0435     std::cout << _flag[step - DTConfigTraco::NSTEPF].element(1) << "  ";
0436     std::cout << _flag[step - DTConfigTraco::NSTEPF].element(2) << "  ";
0437     std::cout << _flag[step - DTConfigTraco::NSTEPF].element(3) << "  ";
0438     std::cout << _flag[step - DTConfigTraco::NSTEPF].element(4) << "  ";
0439     std::cout << _flag[step - DTConfigTraco::NSTEPF].element(5) << "  ";
0440     std::cout << _flag[step - DTConfigTraco::NSTEPF].element(6) << "  ";
0441     std::cout << _flag[step - DTConfigTraco::NSTEPF].element(7) << "  ";
0442     std::cout << _flag[step - DTConfigTraco::NSTEPF].element(8) << "  ";
0443     std::cout << _flag[step - DTConfigTraco::NSTEPF].element(9) << "  " << std::endl;
0444   }  // end debugging
0445 }
0446 
0447 DTTracoCand *DTTracoChip::bestCand(int itk, std::vector<DTTracoCand> &tclist) {
0448   // Return if no candidates
0449   if (tclist.empty())
0450     return nullptr;
0451 
0452   // stl function: sort in Ktc ascending or descending order according
0453   // to user request comparing by default with user-defined <
0454   // NB don't reverse if candidates are two with same K
0455   stable_sort(tclist.begin(), tclist.end());  // 0=K ascending, 1=K descending
0456   if (config()->sortKascend(itk) && !(tclist.size() == 2 && tclist[0].K() == tclist[1].K())) {
0457     reverse(tclist.begin(), tclist.end());
0458     if (config()->debug() == 4)
0459       std::cout << "Reversing order of sorted candidate list..." << std::endl;
0460   }
0461 
0462   /*
0463   if(!config()->sortKascend(itk)){
0464     stable_sort( tclist.begin(),tclist.end(),DTTracoCand::closer );
0465   } else {
0466     stable_sort( tclist.begin(),tclist.end(),DTTracoCand::wider );
0467   }
0468  */
0469 
0470   // debugging...
0471   if (config()->debug() == 4) {
0472     std::cout << "DTTracoChip::findBest - Looking for track number " << itk + 1 << std::endl;
0473     std::cout << "Sorted std::vector of usable track candidates is:" << std::endl;
0474     int i = 1;
0475     for (std::vector<DTTracoCand>::iterator p = tclist.begin(); p < tclist.end(); p++) {
0476       if ((*p).usable()) {
0477         std::cout << " DTTracoChip Candidate # " << i++;
0478         (*p).print();
0479       }
0480     }
0481     std::cout << "--------------------------------------------------" << std::endl;
0482   }
0483   // end debugging
0484 
0485   // return the best candidate
0486   int i = 0;
0487   DTTracoCand *bestltrig = nullptr;
0488   std::vector<DTTracoCand>::iterator p;
0489   for (p = tclist.begin(); p < tclist.end(); ++p) {
0490     i++;
0491     // candidate must be usable and not suppressed by LTS
0492     if (AdjBtiLTSuppressed(&(*p)))
0493       if (config()->debug() == 4)
0494         std::cout << "Candidate # " << i << " supp. because next to H in adiacent Tracos" << std::endl;
0495     if ((*p).usable() && !AdjBtiLTSuppressed(&(*p))) {
0496       // check if preference to HTRIG is set and return first trigger
0497       if (!config()->prefHtrig(itk))
0498         return &(*p);
0499       if ((*p).BtiTrig()->code() == 8)
0500         return &(*p);
0501       if (bestltrig == nullptr)
0502         bestltrig = &(*p);
0503     }
0504   }
0505   return bestltrig;
0506 }
0507 
0508 void DTTracoChip::DoAdjBtiLts(DTTracoCand *candidate, std::vector<DTTracoCand> &tclist) {
0509   // If requested, do suppression of LTRIG on BTI close to selected HTRIG in
0510   // same traco
0511   // if(!(config()->adjBtiLts()) && candidate->BtiTrig()->code()==8) {
0512   // SV this is done always, not parametrized !!
0513   if (candidate->BtiTrig()->code() == 8) {
0514     std::vector<DTTracoCand>::iterator p;
0515     for (p = tclist.begin(); p < tclist.end(); p++) {
0516       if ((*p).BtiTrig()->code() < 8 && abs((*p).BtiTrig()->btiNumber() - candidate->BtiTrig()->btiNumber()) < 2) {
0517         (*p).setUsed();
0518         if (config()->debug() == 4) {
0519           std::cout << "Candidate :";
0520           (*p).print();
0521           std::cout << "Suppressed because adiacent to H trig" << std::endl;
0522         }  // end debug
0523       }    // end if
0524     }      // end candidate loop
0525   }        // end if H
0526 }
0527 
0528 int DTTracoChip::AdjBtiLTSuppressed(DTTracoCand *candidate) {
0529   // If requested, do suppression of LTRIG on adjacent BTI -> obsolete!
0530   // if(!(config()->adjBtiLts()) && candidate->BtiTrig()->code()<8) {
0531   // SV: Ltrig always suppressed in hardware if Htrig in adj traco!
0532   if (candidate->BtiTrig()->code() < 8) {
0533     if (_flag[candidate->step() - DTConfigTraco::NSTEPF].element(3) && candidate->position() == 1)
0534       return 1;
0535     if (_flag[candidate->step() - DTConfigTraco::NSTEPF].element(4) && candidate->position() == DTConfigTraco::NBTITC)
0536       return 1;
0537     if (_flag[candidate->step() - DTConfigTraco::NSTEPF].element(5) &&
0538         candidate->position() == DTConfigTraco::NBTITC + 1)
0539       return 1;
0540     if (_flag[candidate->step() - DTConfigTraco::NSTEPF].element(6) &&
0541         candidate->position() == DTConfigTraco::NBTITC * 4)
0542       return 1;
0543   }
0544   //}
0545   return 0;
0546 }
0547 
0548 DTTracoTrig *DTTracoChip::setPV(int itk, DTTracoCand *inner, DTTracoCand *outer) {
0549   // debugging...
0550   if (config()->debug() == 4) {
0551     std::cout << "DTTracoChip::setPV called for candidates : " << std::endl;
0552     if (inner)
0553       inner->print();
0554     if (outer)
0555       outer->print();
0556     std::cout << "--------------------------------------------------" << std::endl;
0557   }
0558   // end debugging
0559 
0560   // first or second track. This is tricky:
0561   // itk=0 menas first track  ==> first= true=1
0562   // itk=1 menas second track ==> first=false=0
0563   int first = (itk == 0) ? 1 : 0;
0564 
0565   // preview selector: the same as priority selector I !!
0566   // select which of the inner/outer segments should be used
0567 
0568   DTTracoCand *candidate = nullptr;
0569   if (inner != nullptr && outer != nullptr) {
0570     //    if(config()->prefHtrig(itk)){
0571     //    ---> BUG! selection is ALWAYS for H trigs
0572     //    ---> fixed by Sara Vanini 25/III/03
0573     if (inner->BtiTrig()->code() == 8 && outer->BtiTrig()->code() < 8) {
0574       candidate = inner;
0575     } else if (inner->BtiTrig()->code() < 8 && outer->BtiTrig()->code() == 8) {
0576       candidate = outer;
0577     } else {  // for same quality tracks, pref. to in/out selection
0578       if (!config()->prefInner(itk)) {
0579         candidate = inner;
0580       } else {
0581         candidate = outer;
0582       }
0583     }
0584     //    } //end if(config()->prefHtrig...
0585     /*
0586         else {
0587           if(!config()->prefInner(itk)) {
0588             candidate=inner;
0589           } else {
0590             candidate=outer;
0591           }
0592         }
0593     */
0594   } else if (inner == nullptr && outer != nullptr) {
0595     candidate = outer;
0596   } else if (inner != nullptr && outer == nullptr) {
0597     candidate = inner;
0598   } else {
0599     return nullptr;  // no candidates
0600   }
0601 
0602   // create new trigger with this candidate
0603   DTTracoTrig *tct = new DTTracoTrig(this, candidate->step());
0604   // store preview for TS
0605   int cod = candidate->BtiTrig()->code();
0606   if (candidate->BtiTrig()->btiSL() == 1)
0607     cod *= 10;
0608   // k output is 5 bits!!! SV
0609   int K = candidate->K();
0610   if (K > 31)
0611     K -= 32;
0612   int ioflag = 0;
0613   if (candidate->position() > 4)
0614     ioflag = 1;
0615   tct->setPV(first, cod, K, ioflag);  // this is already BTI_K-KRAD
0616 
0617   if (config()->debug() == 4) {
0618     std::cout << "Selected candidate stored for preview is: ";
0619     candidate->print();
0620   }
0621   return tct;
0622 }
0623 
0624 int DTTracoChip::storeCorr(DTTracoTrig *tctrig, DTTracoCand *inner, DTTracoCand *outer, int tkn) {
0625   // Bunch crossing
0626   int is = tctrig->step();
0627 
0628   // Debugging...
0629   if (config()->debug() == 4) {
0630     std::cout << "DTTracoChip::storeCorr called with candidates: " << std::endl;
0631     if (inner)
0632       inner->print();
0633     if (outer)
0634       outer->print();
0635     std::cout << "--------------------------------------------------" << std::endl;
0636   }
0637   // End debugging
0638 
0639   // old orca shift definition
0640   float shift = 0.;
0641   // if( config()->trigSetupGeom()!=1 )
0642   shift = (int)(_geom->distSL() / _geom->cellH() + 0.5);
0643   // else
0644   // shift = DD();
0645 
0646   int kcor = 9999;
0647   int xcor = 0;
0648   int icor = 0;
0649 
0650   // Check correlation only if --> this cuts LL follow by H in next 4 bx
0651   // SV 1/IV/04 BUG FIX: this cuts LL preview also, traco outputs preview when
0652   // LTS cut!!!
0653   // if( !config()->TcBxLts() ||          // BX LTS is not enabled or
0654   //    !_bxlts.element(is) ||           // no HTRIG in next 4 BX or
0655   //    inner->BtiTrig()->code()==8 ||   // inner track is HTRIG  or
0656   //    outer->BtiTrig()->code()==8 ){   // outer track is HTRIG
0657   // otherwise in and out trig are L, and necessary one is suppressed for LTS
0658 
0659   int xq1 = inner->X();
0660   int xq2 = outer->X();
0661   xcor = (xq2 + xq1) / 2;
0662   kcor = (xq1 - xq2) + 512;
0663   int kq1 = int(shift / 2.) * (inner->BtiTrig()->K() - BTIC()) + 512;
0664   int kq2 = int(shift / 2.) * (outer->BtiTrig()->K() - BTIC()) + 512;
0665   // int kd1 = abs(kcor/16-kq1/16);
0666   // int kd2 = abs(kcor/16-kq2/16);
0667   int kd1 = abs(kcor / 16 - kq1 / 16);
0668   int kd2 = abs(kcor / 16 - kq2 / 16);
0669 
0670   icor = kd1 <= config()->TcKToll(tkn) && kd2 <= config()->TcKToll(tkn) && xcor > 0;
0671 
0672   // Debugging...
0673   if (config()->debug() == 4) {
0674     std::cout << "*************************************************************";
0675     std::cout << std::endl;
0676     std::cout << " shift = " << shift;
0677     std::cout << " xq1 = " << xq1;
0678     std::cout << " xq2 = " << xq2;
0679     std::cout << " xcor = " << xcor;
0680     std::cout << " kcor = " << kcor;
0681     std::cout << " kq1 = " << kq1;
0682     std::cout << " kq2 = " << kq2;
0683     std::cout << " kd1 = " << kd1;
0684     std::cout << " kd2 = " << kd2;
0685     std::cout << " icor = " << icor;
0686     std::cout << std::endl;
0687     std::cout << "*************************************************************";
0688     std::cout << std::endl;
0689   }  // End debugging
0690 
0691   //}//end if TcBxLts....
0692 
0693   if (icor) {
0694     // correlation was successfull
0695     // set the preview correlation bit. It isn't reset if outside ang. window
0696     tctrig->setPVCorr(1);
0697     // set K and X
0698     tctrig->setK(kcor - 512);
0699     // std::cout<<"Set K " << kcor << " instead of " << kcor-512 << std::endl;
0700     // tctrig->setK(kcor);
0701     tctrig->setX(xcor);
0702     // set codes
0703     tctrig->setCodeIn(inner->BtiTrig()->code());
0704     tctrig->setCodeOut(outer->BtiTrig()->code());
0705     // set position mask
0706     // tctrig->setPosIn(inner->position());
0707     // tctrig->setPosOut(outer->position());
0708     // SV number of bti instead of position...
0709     tctrig->setPosIn(inner->BtiTrig()->btiNumber());
0710     tctrig->setPosOut(outer->BtiTrig()->btiNumber());
0711     // SV store also equation: pattern numbers are 1-32
0712     tctrig->setEqIn(inner->BtiTrig()->eq() + 1);
0713     tctrig->setEqOut(outer->BtiTrig()->eq() + 1);
0714 
0715     // calculate psi, psi_r and Delta(psi_r)
0716     calculateAngles(tctrig);
0717     // check angular window for LL  --> fixed by SV 27/III/03 --> NO, for all!
0718     // if( (tctrig->qdec()==4) && !insideAngWindow(tctrig)) {
0719     if (!insideAngWindow(tctrig)) {
0720       // reset codes, K, X and angles
0721       tctrig->resetVar();
0722     }
0723     // SV 1/IV/04 BUG FIX: check LTS after angle cut...
0724     else if (tctrig->qdec() == 4 &&  // cut only LL
0725              config()->TcBxLts()) {  // BX LTS is  enabled or
0726       // reset codes, K, X and angles
0727       if (tkn == 0 && _bxlts.element(is))  // I track : there is H -4,+1
0728         tctrig->resetVar();
0729       if (tkn == 1 && _bxlts.element(is + 1))  // II track : there is H -4,+1 1 bx later
0730         tctrig->resetVar();
0731     } else {
0732       // set links to BTI triggers
0733       tctrig->addDTBtiTrig(inner->BtiTrig());
0734       tctrig->addDTBtiTrig(outer->BtiTrig());
0735     }
0736 
0737     // Debugging...
0738     if (config()->debug() > 1) {
0739       std::cout << "*************************************************************";
0740       std::cout << std::endl;
0741       std::cout << "               Correlation was successfull:                  ";
0742       std::cout << std::endl;
0743       std::cout << " Code = " << tctrig->code();
0744       std::cout << " K = " << tctrig->K();
0745       std::cout << " X = " << tctrig->X();
0746       std::cout << std::endl;
0747       std::cout << "*************************************************************";
0748       std::cout << std::endl;
0749     }
0750     // End debugging
0751 
0752   } else {
0753     // Debugging...
0754     if (config()->debug() > 1) {
0755       std::cout << "*************************************************************";
0756       std::cout << std::endl;
0757       std::cout << "               No correlation possible                       ";
0758       std::cout << std::endl;
0759       std::cout << "*************************************************************";
0760       std::cout << std::endl;
0761     }
0762     // End debugging
0763   }
0764 
0765   return icor;
0766 }
0767 
0768 int DTTracoChip::storeUncorr(DTTracoTrig *tctrig, DTTracoCand *inner, DTTracoCand *outer, int tkn) {
0769   // Bunch crossing
0770   int is = tctrig->step();
0771 
0772   // Debugging...
0773   if (config()->debug() == 4) {
0774     std::cout << "DTTracoChip::storeUncorr called with candidates: " << std::endl;
0775     if (inner)
0776       inner->print();
0777     if (outer)
0778       outer->print();
0779     std::cout << "--------------------------------------------------" << std::endl;
0780   }
0781 
0782   // End debugging
0783   // priority selector
0784   // select which of the inner/outer segments should be used
0785   // allow re-use of other segment according to configuration
0786   DTTracoCand *candidate = nullptr;
0787   if (inner != nullptr && outer != nullptr) {
0788     //    if(config()->prefHtrig(tkn)){
0789     // --> BUG: selector I preference is ALWAYS for H trig
0790     // fixed by Sara Vanini - 25/III/03
0791     if (inner->BtiTrig()->code() == 8 && outer->BtiTrig()->code() < 8) {
0792       candidate = inner;
0793       // if(config()->TcReuse(1)) outer->setUnused(); // reusable
0794     } else if (inner->BtiTrig()->code() < 8 && outer->BtiTrig()->code() == 8) {
0795       candidate = outer;
0796       // if(config()->TcReuse(0)) inner->setUnused(); // reusable
0797     } else {  // for the same quality triggers:
0798       if (!config()->prefInner(tkn)) {
0799         candidate = inner;
0800         // if(config()->TcReuse(1))  outer->setUnused(); // reusable
0801       } else {
0802         candidate = outer;
0803         // if(config()->TcReuse(0))  inner->setUnused(); // reusable
0804       }
0805     }  // end else
0806     /*
0807         } else {//no Htrig preference
0808           if(!config()->prefInner(tkn)) {
0809             candidate=inner;
0810             if(config()->TcReuse(1))  outer->setUnused(); // reusable
0811           } else {
0812             candidate=outer;
0813             if(config()->TcReuse(0))  inner->setUnused(); // reusable
0814           }
0815         }
0816     */
0817   } else if (inner == nullptr && outer != nullptr) {
0818     candidate = outer;
0819   } else if (inner != nullptr && outer == nullptr) {
0820     candidate = inner;
0821   } else {
0822     return 0;  // no candidates
0823   }
0824 
0825   // SV *** FOR TESTBEAM OR TEST BENCH PURPOSE ***
0826   // theta trigger bin present(1) or absent(0)
0827   // int thTr = (_flag[is-DTConfigTraco::NSTEPF].element(7)) ?
0828   //   _flag[is-DTConfigTraco::NSTEPF].element(7):
0829   //   _flag[is-DTConfigTraco::NSTEPF].element(8);
0830 
0831   // priority selector II: accept or discard candidate according to masks:
0832   // ** LOW TRIGGERS
0833   if (candidate->BtiTrig()->code() < 8) {
0834     // first check with LVALIDIFH: if 1, accept low if there is a H in traco at
0835     // bx
0836     if (config()->LVALIDIFH() && _flag[is - DTConfigTraco::NSTEPF].element(9)) {
0837       if (config()->debug() > 1)
0838         std::cout << "Low accepted because LVALIDIFH on...." << std::endl;
0839     } else {  // LVALIDIFH==0 or there isn't H in traco in bx : check theta!
0840       // theta check
0841       if (!config()->singleLenab(tkn)) {
0842         // LTF: single LTRIG not always en. Check cond.:
0843         if (config()->singleLflag(tkn) == 1 ||  // always discarded
0844             (config()->singleLflag(tkn) == 2 && !(_card->TSTh()->nHTrig(is))) ||
0845             (config()->singleLflag(tkn) == 0 && !(_card->TSTh()->nTrig(is)))) {
0846           // SV --> for TESTS version
0847           //        config()->singleLflag(tkn)==0 && thTr==0 ||   //only with
0848           //        theta trig. config()->singleLflag(tkn)==2 && thTr==0  ){
0849           //        //only with theta H trig (not hw)
0850           if (config()->debug() > 1)
0851             std::cout << "Single low trigger discarded by preview and "
0852                       << "priority selector for ltmsk!" << std::endl;
0853           return 0;
0854         }
0855         //       ^-------- trigger is suppressed and will not be stored
0856       }  // end theta
0857 
0858     }  // end else
0859     // REUSE : mark candidates reusable HERE! SV BUG FIX 6IV04
0860     if (candidate == inner && config()->TcReuse(1) && outer)
0861       outer->setUnused();
0862     if (candidate == outer && config()->TcReuse(0) && inner)
0863       inner->setUnused();
0864 
0865     // LTS suppression
0866     if (config()->TcBxLts()) {
0867       if ((tkn == 0 && _bxlts.element(is))            // I track : there is H -4,+1
0868           || (tkn == 1 && _bxlts.element(is + 1))) {  // II track : there is H -4,+1 1 bx later
0869         tctrig->resetVar();
0870         if (config()->debug() > 1)
0871           std::cout << "Low trigger suppressed because H in next 4 bx "
0872                     << " and LTS flag on...." << std::endl;
0873         return 1;  // trigger is suppressed but preview will be stored
0874       }
0875     }  // end lts
0876 
0877     //    } //end else
0878   }  // Low trigs
0879 
0880   // Preview Htmsk not implemented: awaiting decision
0881   // --> implemented in priority selector by SV
0882   else {  // HTRIG
0883     // if(config()->singleHflag(tkn)==1 && thTr==0 )  //this is for testing
0884     if (config()->singleHflag(tkn) == 1 && !(_card->TSTh()->nTrig(is)))
0885       return 0;
0886     // ^-----trigger is suppressed and will not be stored
0887 
0888     // mark candidates reusable HERE! SV BUG FIX 6IV04
0889     if (candidate == inner && config()->TcReuse(1) && outer)
0890       outer->setUnused();
0891     if (candidate == outer && config()->TcReuse(0) && inner)
0892       inner->setUnused();
0893   }
0894 
0895   // set code, position, K and X
0896   float shift;
0897   // if(config()->trigSetupGeom()!=1 )
0898   shift = (int)(_geom->distSL() / _geom->cellH() + 0.5);
0899   // else
0900   // shift = DD();  //SV 19/III/03
0901   int kucor = (int)(0.5 * shift * (candidate->BtiTrig()->K() - BTIC()));
0902   tctrig->setK(kucor);
0903   tctrig->setX(candidate->X());
0904   // correlation wasn't successfull
0905   // set the preview correlation bit.
0906   tctrig->setPVCorr(0);
0907   if (candidate->BtiTrig()->btiSL() == 1) {  // inner track
0908     tctrig->setCodeIn(candidate->BtiTrig()->code());
0909     tctrig->setCodeOut(0);
0910     // tctrig->setPosIn(candidate->position());
0911     // SV number of bti instead of position...
0912     tctrig->setPosIn(candidate->BtiTrig()->btiNumber());
0913     tctrig->setPosOut(0);
0914     // SV store also equation
0915     tctrig->setEqIn(candidate->BtiTrig()->eq() + 1);
0916     tctrig->setEqOut(0);
0917   } else {  // outer track
0918     tctrig->setCodeIn(0);
0919     tctrig->setCodeOut(candidate->BtiTrig()->code());
0920     tctrig->setPosIn(0);
0921     // SV number of bti instead of position...
0922     tctrig->setPosOut(candidate->BtiTrig()->btiNumber());
0923     // tctrig->setPosOut(candidate->position());
0924     // SV store also equation
0925     tctrig->setEqIn(0);
0926     tctrig->setEqOut(candidate->BtiTrig()->eq() + 1);
0927   }
0928 
0929   // coordinate converter LUT
0930   // calculate psi, psi_r and Delta(psi_r)
0931   calculateAngles(tctrig);
0932   // check angular window only for Low!!  --> fixed SV 27/III/03--> NO, for all!
0933   // if( candidate->BtiTrig()->code() < 8 && !insideAngWindow(tctrig) ){
0934   if (!insideAngWindow(tctrig)) {
0935     // reset codes, K, X and angles
0936     tctrig->resetVar();
0937     if (config()->debug() > 1)
0938       std::cout << "L rejected because outside angular window!" << std::endl;
0939   } else {
0940     // set links to BTI trigger
0941     tctrig->addDTBtiTrig(candidate->BtiTrig());
0942   }
0943 
0944   // Debugging...
0945   if (config()->debug() > 1) {
0946     std::cout << "*************************************************************";
0947     std::cout << std::endl;
0948     std::cout << "               Single trigger stored:                        ";
0949     std::cout << std::endl;
0950     std::cout << " Code = " << tctrig->code();
0951     std::cout << " K = " << tctrig->K();
0952     std::cout << " X = " << tctrig->X();
0953     std::cout << std::endl;
0954     std::cout << "*************************************************************";
0955     std::cout << std::endl;
0956   }
0957   // End debugging
0958 
0959   return 1;
0960 }
0961 
0962 void DTTracoChip::add_btiT(int step, int pos, const DTBtiTrigData *btitrig) {
0963   if (pos < 1 || pos > 4 * DTConfigTraco::NBTITC) {
0964     std::cout << "DTTracoChip::add_btiT: wrong position: " << pos;
0965     std::cout << "trigger not added!" << std::endl;
0966     return;
0967   }
0968   if (step < DTConfigTraco::NSTEPF || step > DTConfigTraco::NSTEPL) {
0969     std::cout << "DTTracoChip::add_btiT: step out of range: " << step;
0970     std::cout << "trigger not added!" << std::endl;
0971     return;
0972   }
0973 
0974   if (!config()->usedBti(pos)) {
0975     if (config()->debug() == 4) {
0976       std::cout << "DTTracoChip::add_btiT: position: " << pos;
0977       std::cout << "has disconnected bti" << std::endl;
0978     }
0979     return;
0980   }
0981 
0982   // 091103 SV: acceptances are taken from geometry if useAcceptParam()=false
0983   // otherwise cuts based on LL,LH,CL,CH,RL,RH taken from  configuration are
0984   // applied in TracoCard::loadTraco
0985   if (_card->useAcceptParamFlag() == false) {
0986     // check K inside acceptance
0987     if (btitrig->K() < _PSIMIN[pos - 1] || btitrig->K() > _PSIMAX[pos - 1]) {
0988       if (config()->debug() > 1) {
0989         std::cout << "In TRACO num. " << number() << " BTI trig. in pos " << pos << " outside K acceptance (";
0990         std::cout << _PSIMIN[pos - 1] << "-->";
0991         std::cout << _PSIMAX[pos - 1] << ") - Not added" << std::endl;
0992       }
0993       return;
0994     }
0995   }
0996 
0997   // Store trigger candidate
0998   if (pos <= DTConfigTraco::NBTITC) {
0999     _innerCand[step - DTConfigTraco::NSTEPF].push_back(DTTracoCand(this, btitrig, pos, step));
1000   } else {
1001     _outerCand[step - DTConfigTraco::NSTEPF].push_back(DTTracoCand(this, btitrig, pos, step));
1002   }
1003 
1004   // Fill array for BX LTS
1005   if (btitrig->code() == 8) {
1006     for (int is = step - 4; is < step; is++) {  // set flag for 4 previous BX
1007       if (is > 0 && is <= DTConfigTraco::NSTEPL)
1008         _bxlts.set(is);
1009     }
1010     // SV 1/IV/04 BUG FIX
1011     _bxlts.set(step + 1);
1012     // Debugging
1013     if (config()->debug() == 4)
1014       for (int is = 0; is < DTConfigTraco::NSTEPL; is++)
1015         std::cout << "_bxlts[" << is << "]=" << _bxlts.element(is) << std::endl;
1016   }
1017 
1018   // Debugging
1019   if (config()->debug() > 1) {
1020     std::cout << "BTI Trigger added at step " << step;
1021     std::cout << " to TRACO " << _id.traco() << " at position " << pos << std::endl;
1022     btitrig->print();
1023   }  // End debugging
1024 }
1025 
1026 void DTTracoChip::addTrig(int step, DTTracoTrig *tctrig) {
1027   if (step < DTConfigTraco::NSTEPF || step > DTConfigTraco::NSTEPL) {
1028     std::cout << "DTTracoChip::addTrig: step out of range: " << step;
1029     std::cout << " trigger not added!" << std::endl;
1030     return;
1031   }
1032   _tracotrig[step - DTConfigTraco::NSTEPF].push_back(tctrig);
1033 
1034   // Debugging...
1035 
1036   if (config()->debug() == 4) {
1037     std::cout << "DTTracoChip::addTrig: adding trigger:" << std::endl;
1038     tctrig->print();
1039   }
1040   // End debugging
1041 }
1042 
1043 int DTTracoChip::nTrig(int step) const {
1044   if (step < DTConfigTraco::NSTEPF || step > DTConfigTraco::NSTEPL) {
1045     std::cout << "DTTracoChip::nTrig: step out of range: " << step;
1046     std::cout << " 0 returned!" << std::endl;
1047     return 0;
1048   }
1049   return _tracotrig[step - DTConfigTraco::NSTEPF].size();
1050 }
1051 
1052 DTTracoTrig *DTTracoChip::trigger(int step, unsigned n) const {
1053   if (step < DTConfigTraco::NSTEPF || step > DTConfigTraco::NSTEPL) {
1054     std::cout << "DTTracoChip::trigger: step out of range: " << step;
1055     std::cout << " empty pointer returned!" << std::endl;
1056     return nullptr;
1057   }
1058   if (n < 1 || n > _tracotrig[step - DTConfigTraco::NSTEPF].size()) {
1059     std::cout << "DTTracoChip::trigger: requested trigger doesn't exist: " << n;
1060     std::cout << " empty pointer returned!" << std::endl;
1061     return nullptr;
1062   }
1063   std::vector<DTTracoTrig *>::const_iterator p = _tracotrig[step - DTConfigTraco::NSTEPF].begin() + n - 1;
1064   return *p;
1065 }
1066 
1067 DTTracoTrigData DTTracoChip::triggerData(int step, unsigned n) const {
1068   if (step < DTConfigTraco::NSTEPF || step > DTConfigTraco::NSTEPL) {
1069     std::cout << "DTTracoChip::triggerData: step out of range: " << step;
1070     std::cout << " dummy trigger returned!" << std::endl;
1071     return DTTracoTrigData();
1072   }
1073   if (n < 1 || n > _tracotrig[step - DTConfigTraco::NSTEPF].size()) {
1074     std::cout << "DTTracoChip::trigger: requested trigger doesn't exist: " << n;
1075     std::cout << " dummy trigger returned!" << std::endl;
1076     return DTTracoTrigData();
1077   }
1078   std::vector<DTTracoTrig *>::const_iterator p = _tracotrig[step - DTConfigTraco::NSTEPF].begin() + n - 1;
1079   return (*p)->data();
1080 }
1081 
1082 float DTTracoChip::psiRad(int sl) const {
1083   /*
1084     // Radial angle of correlator center in mrad in CMS frame
1085     LocalPoint p = localPosition();
1086     float x = p.x();
1087     float y = p.y();
1088     float z = p.z();
1089     if        (sl==1) {
1090       z -= 0.5 * _geom->distSL();
1091     } else if (sl==3) {
1092       z += 0.5 * _geom->distSL();
1093     }
1094     float fpsir = _geom->stat()->toGlobal(LocalPoint(x,y,z)).phi()-
1095                   _geom->phiCh();
1096     if(fpsir<-M_PI)fpsir+=M_PI*2;
1097     if(fpsir>M_PI)fpsir-=M_PI*2;
1098     return fpsir*1000;
1099   */
1100   return 0.0;
1101 }
1102 
1103 int DTTracoChip::KRad() const {
1104   // K parameter of the radial angle of correlator center
1105   // float distp2 = (int)(2*_geom->cellH()*config()->ST()/_geom->cellPitch());
1106   // return -(int)(tan(psiRad(sl)/1000)*distp2); // sign is reverted!!!
1107   // return _krad;
1108 
1109   // SV V/03: for harware bug in traco....
1110   int KRad = 0;
1111   return KRad;
1112 }
1113 
1114 int DTTracoChip::useSecondTrack(int step) const {
1115   // return 1 if II track use is allow
1116   // return 0 if II track has been rejected
1117   if (step < DTConfigTraco::NSTEPF || step > DTConfigTraco::NSTEPL) {
1118     std::cout << "DTTracoChip::useSecondTrack: step out of range: " << step;
1119     std::cout << " 0 returned!" << std::endl;
1120     return 0;
1121   }
1122   return !(_flag[step - DTConfigTraco::NSTEPF].element(2));
1123 }
1124 
1125 int DTTracoChip::edgeBTI(int step, int io, int lr) const {
1126   if (step < DTConfigTraco::NSTEPF || step > DTConfigTraco::NSTEPL) {
1127     std::cout << "DTTracoChip::edgeBTI: step out of range: " << step;
1128     std::cout << " 0 returned!" << std::endl;
1129     return 0;
1130   }
1131   //
1132   // inner supl ==> io=1; outer supl ==> io=2      |21   |     |   22|
1133   // right edge ==> rl=1;  left edge ==> rl=2            |11 12|
1134   //
1135   std::vector<DTTracoCand>::const_iterator p;
1136   if (io == 1) {
1137     if (!_innerCand[step - DTConfigTraco::NSTEPF].empty()) {
1138       // SV 24/IX/03 fix: only HTRIG accepted
1139       for (p = _innerCand[step - DTConfigTraco::NSTEPF].begin(); p < _innerCand[step - DTConfigTraco::NSTEPF].end();
1140            p++) {
1141         if (lr == 1 && (*p).position() == 1 && (*p).BtiTrig()->code() == 8)
1142           return 1;
1143         if (lr == 2 && (*p).position() == DTConfigTraco::NBTITC && (*p).BtiTrig()->code() == 8)
1144           return 1;
1145       }
1146     }
1147   } else {
1148     if (!_outerCand[step - DTConfigTraco::NSTEPF].empty()) {
1149       for (p = _outerCand[step - DTConfigTraco::NSTEPF].begin(); p < _outerCand[step - DTConfigTraco::NSTEPF].end();
1150            p++) {
1151         // SV: is the following correct???FIX if using _card to set _flag
1152         // if(lr==1 && (*p).position()==DTConfigTraco::NBTITC+1)return 1; //or
1153         // pos=8?? if(lr==2 && (*p).position()==DTConfigTraco::NBTITC*4)return
1154         // 1;
1155         // //or pos=13?? SV 24/IX/03 fix
1156         if (lr == 1 && (*p).position() == DTConfigTraco::NBTITC * 3 + 1 && (*p).BtiTrig()->code() == 8)
1157           return 1;
1158         if (lr == 2 && (*p).position() == DTConfigTraco::NBTITC * 2 && (*p).BtiTrig()->code() == 8)
1159           return 1;
1160       }
1161     }
1162   }
1163   return 0;
1164 }
1165 
1166 void DTTracoChip::calculateAngles(DTTracoTrig *tct) {
1167   int ipsi = 0;
1168   int iphir = 0;
1169   int idpsir = 0;
1170   /* obsolete
1171     //TB 2004 luts formula from minicrate CCB
1172     if( config()->trigSetupGeom()==2 ){
1173       ipsi = _lutsCCB->get_k( (tct->K()+511) );
1174 
1175       int flag = 0;
1176       int qual=tct->data().qdec();
1177       if(qual==3 || qual==1)                //case 0:outer
1178         flag=0;
1179       if(qual==2 || qual==0)                //case 1:inner
1180         flag=1;
1181       if(qual==6 || qual==5 || qual==4)     //case 2:correlated
1182         flag=2;
1183 
1184       iphir = _lutsCCB->get_x( (tct->X()+512*flag) );
1185 
1186       idpsir = ipsi - iphir/8;
1187     }
1188 
1189    //TB 2003 luts data format
1190    if( config()->trigSetupGeom()==1 ){
1191       //compute bending angles of traco output with lookup tables
1192       //SV TB2003: first trigger board isn't connected;
1193       ipsi = _luts->getPsi(tct->K());
1194       int flag = 0;
1195       int qual=tct->data().qdec();
1196       if(qual==3 || qual==1)                //case 0:outer
1197         flag=0;
1198       if(qual==2 || qual==0)                //case 1:inner
1199         flag=1;
1200       if(qual==6 || qual==5 || qual==4)     //case 2:correlated
1201         flag=2;
1202       iphir = _luts->getPhiRad( tct->X(), flag);
1203       idpsir = _luts->getBendAng( tct->X(), tct->K(), flag);
1204     }
1205    */
1206 
1207   // 091030 SV angles computed from DB lut parameters
1208   if (_card->lutFromDBFlag() == 1) {
1209     ipsi = _lutsCCB->get_k((tct->K() + 512));
1210 
1211     int flag = 0;
1212     int qual = tct->data().qdec();
1213     if (qual == 3 || qual == 1)  // case 0:outer
1214       flag = 0;
1215     if (qual == 2 || qual == 0)  // case 1:inner
1216       flag = 1;
1217     if (qual == 6 || qual == 5 || qual == 4)  // case 2:correlated
1218       flag = 2;
1219 
1220     iphir = _lutsCCB->get_x((tct->X() + 512 * flag));
1221 
1222     idpsir = ipsi - iphir / 8;
1223   } else
1224   // compute angles from CMSSW geometry
1225   // if( config()->trigSetupGeom()==0 )
1226   {
1227     DTTracoTrigData td = tct->data();
1228     // psi
1229     //  float fpsi = atan( (float)(tct->K()) * _geom->cellPitch() /
1230     //           (_geom->distSL() * config()->ST()) );
1231     float fpsi = atan(_card->localDirection(&td).x() /  // e.g. x>0 and
1232                       _card->localDirection(&td).z());  //      z<0 => fpsi<0
1233 
1234     // Change sign in case of wheel<0 or wheel==0 and station == 1,4,5,8,9,12
1235     int mywh = tct->ChamberId().wheel();
1236     if (mywh < 0 || (mywh == 0 && (tct->ChamberId().sector() % 4) < 2))
1237       fpsi = -fpsi;
1238 
1239     fpsi *= DTConfigTraco::RESOLPSI;
1240     if (fpsi <= 0)
1241       fpsi -= 1.0;
1242     ipsi = (int)fpsi;
1243     // if outside range set to lower edge
1244     if (ipsi >= DTConfigTraco::RESOLPSI || ipsi < -DTConfigTraco::RESOLPSI)
1245       ipsi = -DTConfigTraco::RESOLPSI;
1246 
1247     // psi_r
1248     float fpsir = _card->CMSPosition(&td).phi() - _geom->phiCh();
1249 
1250     if (fpsir < -M_PI)
1251       fpsir += M_PI * 2;
1252     if (fpsir > M_PI)
1253       fpsir -= M_PI * 2;
1254     fpsir *= DTConfigTraco::RESOLPSIR;
1255     if (fpsir <= 0)
1256       fpsir -= 1.0;
1257     iphir = (int)fpsir;
1258     // if outside range set to lower edge
1259     if (iphir >= DTConfigTraco::RESOLPSIR / 2 || iphir < -DTConfigTraco::RESOLPSIR / 2)
1260       iphir = -DTConfigTraco::RESOLPSIR / 2;
1261 
1262     // Delta(psi_r)
1263     int dpsir = (iphir * DTConfigTraco::RESOLPSI) / DTConfigTraco::RESOLPSIR;
1264     idpsir = ipsi - dpsir;
1265     // if outside range set to lower edge
1266     if (idpsir >= DTConfigTraco::RESOLPSI || idpsir < -DTConfigTraco::RESOLPSI)
1267       idpsir = -DTConfigTraco::RESOLPSI;
1268   }
1269 
1270   tct->setAngles(ipsi, iphir, idpsir);
1271 
1272   // debugging
1273   if (config()->debug() == 4) {
1274     std::cout << "DTTracoChip::calculateAngles :" << std::endl;
1275     tct->print();
1276     std::cout << std::dec << "K = " << tct->K() << " X = " << tct->X();
1277     std::cout << " ipsi = " << ipsi << " iphir = " << iphir;
1278     std::cout << " idpsir = " << idpsir << std::endl;
1279     if (_card->lutFromDBFlag() == 1)
1280       std::cout << "Angles are calculated from LUT parameters from DB!" << std::endl;
1281   }  // end debugging
1282 }
1283 
1284 int DTTracoChip::insideAngWindow(DTTracoTrig *tctrig) const {
1285   // check angular window for every station type
1286   // return 1 for accept, 0 for reject
1287   // abs value of bending angle is 9 bits
1288 
1289   BitArray<10> bendAng;
1290   bendAng.assign(0, 10, tctrig->DeltaPsiR());
1291   // bendAng.print();
1292   if (bendAng.element(9))  // negativo!
1293     bendAng.twoComplement();
1294   int bendAngINT = bendAng.read(0, 9);
1295   // std::cout<<"abs bend angle int ="<< bendAngINT <<std::endl;
1296 
1297   if (config()->BendingAngleCut() != -1 && bendAngINT > 2 * (config()->BendingAngleCut())) {
1298     int absBendAng = tctrig->DeltaPsiR() & 0x1FF;
1299     if (config()->debug() == 4)
1300       std::cout << "Attention: abs(bendAng)=" << absBendAng << " > " << 2 * config()->BendingAngleCut()
1301                 << "!! reject trigger" << std::endl;
1302     return 0;
1303   }
1304   return 1;
1305 }
1306 
1307 void DTTracoChip::setTracoAcceptances() {
1308   // Set K acceptances of DTTracoChip MT ports: Ktraco = Xinner - Xouter
1309   float h = _geom->cellH();
1310   float pitch = _geom->cellPitch();
1311   float distsl = _geom->distSL();
1312   float K0 = config()->BTIC();
1313   float shiftSL = _geom->phiSLOffset() / pitch * K0;
1314 
1315   // mt  ports from orca geometry: this is always the case with new DTConfig
1316   // if(config_traco(tracoid)->trigSetupGeom() != 1){
1317   {
1318     // Master Plane
1319     int i = 0;
1320     for (i = 0; i < DTConfig::NBTITC; i++) {
1321       float Xin_min = (i + DTConfig::NBTITC) * K0 + shiftSL;
1322       float Xin_max = Xin_min + K0;
1323       float Xout_min = 0;
1324       float Xout_max = 3 * DTConfig::NBTITC * K0;
1325       _PSIMAX[i] = int(2. * h / distsl * (Xin_max - Xout_min) + K0 + 1.01);
1326       _PSIMIN[i] = int(2. * h / distsl * (Xin_min - Xout_max) + K0);
1327     }
1328 
1329     // Slave Plane
1330     for (i = 0; i < 3 * DTConfig::NBTITC; i++) {
1331       float Xin_min = (DTConfig::NBTITC)*K0 + shiftSL;
1332       float Xin_max = 2. * DTConfig::NBTITC * K0 + shiftSL;
1333       float Xout_min = i * K0;
1334       float Xout_max = Xout_min + K0;
1335       _PSIMAX[DTConfig::NBTITC + i] = int(2. * h / distsl * (Xin_max - Xout_min) + K0 + 1.01);
1336       _PSIMIN[DTConfig::NBTITC + i] = int(2. * h / distsl * (Xin_min - Xout_max) + K0);
1337     }
1338   }
1339 
1340   // debugging
1341   if (config()->debug() == 4) {
1342     // if(wheel()==2&&station()==3&&sector()==1){ // only 1 chamber
1343     std::cout << "Acceptance of mt ports for offset (cell unit) " << _geom->phiSLOffset() / pitch << std::endl;
1344     for (int i = 0; i < 4 * DTConfig::NBTITC; i++) {
1345       std::cout << "Port " << i + 1 << " : ";
1346       std::cout << _PSIMIN[i] << " --> " << _PSIMAX[i] << std::endl;
1347     }
1348     //}
1349   }  // end debugging
1350 }