Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:21:01

0001 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0002 
0003 #include "L1Trigger/L1TMuonEndCapPhase2/interface/EMTFContext.h"
0004 #include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DataUtils.h"
0005 #include "L1Trigger/L1TMuonEndCapPhase2/interface/Utils/DebugUtils.h"
0006 
0007 #include "L1Trigger/L1TMuonEndCapPhase2/interface/Algo/TrackBuildingLayer.h"
0008 
0009 using namespace emtf::phase2;
0010 using namespace emtf::phase2::algo;
0011 
0012 // Static
0013 seg_theta_t TrackBuildingLayer::calc_theta_median(std::vector<seg_theta_t> thetas) {
0014   auto i_last = thetas.size() - 1;
0015 
0016   // Sort Thetas
0017   // This will sort ascending order (lower-value means lower-index)
0018   data::mergesort(&thetas[0], thetas.size(), [](seg_theta_t lower_index_value, seg_theta_t larger_index_value) -> int {
0019     return lower_index_value > larger_index_value ? 1 : 0;
0020   });
0021 
0022   // Check if any model_thm_site is null
0023   // Since the theta array has been sorted, it's enough
0024   // to check the last index, because the invalid value will be the max
0025   seg_theta_t invalid_theta = -1;  // This maps to 255 since it underflows
0026 
0027   bool any_invalid = thetas[i_last] == invalid_theta;
0028 
0029   // Calculate median
0030   if (any_invalid) {
0031     // Use the min value as the median if there are any invalid thetas
0032     return thetas[0];
0033   } else {
0034     // Calculate the median if all thetas are valid
0035     return data::getMedianOfSorted(&thetas[0], thetas.size());
0036   }
0037 }
0038 
0039 // Members
0040 TrackBuildingLayer::TrackBuildingLayer(const EMTFContext& context) : context_(context) {}
0041 
0042 void TrackBuildingLayer::apply(const segment_collection_t& segments,
0043                                const std::vector<road_t>& roads,
0044                                const bool& displaced_en,
0045                                std::vector<track_t>& tracks) const {
0046   // Apply
0047   for (unsigned int i_road = 0; i_road < roads.size(); ++i_road) {
0048     // Get road and track
0049     const auto& road = roads[i_road];
0050     auto& track = tracks.emplace_back();
0051 
0052     // Initialize track
0053     track.phi = 0;
0054     track.theta = 0;
0055     track.valid = 0;
0056 
0057     for (unsigned int site_id = 0; site_id < v3::kNumTrackSites; ++site_id) {
0058       track.site_segs[site_id] = 0;
0059       track.site_mask[site_id] = 0;
0060       track.site_rm_mask[site_id] = 0;
0061     }
0062 
0063     for (unsigned int i_feature = 0; i_feature < v3::kNumTrackFeatures; ++i_feature) {
0064       track.features[i_feature] = 0;
0065     }
0066 
0067     // Short-Circuit: If the road has quality-0 skip it
0068     if (road.quality == 0) {
0069       continue;
0070     }
0071 
0072     // Debug Info
0073     if (this->context_.config_.verbosity_ > 1) {
0074       if (i_road == 0) {
0075         edm::LogInfo("L1TEMTFpp") << std::endl;
0076         edm::LogInfo("L1TEMTFpp") << "==========================================================================="
0077                                   << std::endl;
0078         edm::LogInfo("L1TEMTFpp") << "BEGIN TRACK BUILDING" << std::endl;
0079         edm::LogInfo("L1TEMTFpp") << "---------------------------------------------------------------------------"
0080                                   << std::endl;
0081       }
0082 
0083       edm::LogInfo("L1TEMTFpp") << "***************************************************************************"
0084                                 << std::endl;
0085       edm::LogInfo("L1TEMTFpp") << "Begin building track " << i_road << std::endl;
0086     }
0087 
0088     // Attach segments
0089     attachSegments(segments, road, displaced_en, track);
0090 
0091     // Debug Info
0092     if (this->context_.config_.verbosity_ > 1) {
0093       edm::LogInfo("L1TEMTFpp") << "End building track " << i_road << std::endl;
0094 
0095       if (i_road == (roads.size() - 1)) {
0096         edm::LogInfo("L1TEMTFpp") << "---------------------------------------------------------------------------"
0097                                   << std::endl;
0098         edm::LogInfo("L1TEMTFpp") << "END TRACK BUILDING" << std::endl;
0099         edm::LogInfo("L1TEMTFpp") << "==========================================================================="
0100                                   << std::endl;
0101       }
0102     }
0103   }
0104 }
0105 
0106 void TrackBuildingLayer::attachSegments(const segment_collection_t& segments,
0107                                         const road_t& road,
0108                                         const bool& displaced_en,
0109                                         track_t& track) const {
0110   // ===========================================================================
0111   // Constants
0112   // ---------------------------------------------------------------------------
0113   seg_theta_t invalid_theta = -1;  // This will map to 255 since it underflows
0114 
0115   // ===========================================================================
0116   // Unpack road
0117   // ---------------------------------------------------------------------------
0118   // trk_col: Recall that the hitmap is 288 cols wide, and the full chamber hitmap is 315 cols;
0119   // the chamber hitmap doesn't fit in the hitmap, so we skipped the first 27 cols.
0120   // In order to calculate the full hitmap col, we need to add back the 27 cols that we skipped.
0121   // sector_col: The sector's column is the center col of the phi map adding back the 27 skipped cols.
0122   const auto trk_zone = road.zone;
0123   const auto trk_pattern = road.pattern;
0124   const auto trk_quality = road.quality;
0125 
0126   int bit_sel_zone = (1u << trk_zone);
0127 
0128   const trk_col_t trk_col = road.col + v3::kHitmapCropColStart;
0129   const trk_col_t sector_col = static_cast<trk_col_t>(v3::kHitmapNCols / 2) + v3::kHitmapCropColStart;
0130 
0131   // ===========================================================================
0132   // Initialize vars
0133   // ---------------------------------------------------------------------------
0134   std::array<seg_phi_t, v3::kNumTrackSites> trk_seg_phi_diff;
0135   std::array<seg_theta_t, v3::kNumTrackSites> trk_seg_theta;
0136 
0137   for (unsigned int site_id = 0; site_id < v3::kNumTrackSites; ++site_id) {
0138     trk_seg_phi_diff[site_id] = 0;
0139     trk_seg_theta[site_id] = 0;
0140   }
0141 
0142   // ===========================================================================
0143   // Unpack model
0144   // ---------------------------------------------------------------------------
0145   const auto& model = context_.model_;
0146   const auto& model_hm = model.zones_[trk_zone].hitmap;
0147   const auto& model_ftc = model.features_;
0148 
0149   auto* model_pat = &(model.zones_[trk_zone].prompt_patterns[trk_pattern]);
0150 
0151   if (displaced_en) {
0152     model_pat = &(model.zones_[trk_zone].disp_patterns[trk_pattern]);
0153   }
0154 
0155   // ===========================================================================
0156   // Convert column center to emtf_phi units
0157   // ---------------------------------------------------------------------------
0158   // Each column is emtf_phi=1<<n wide, therefore half of this would be 1<<(n-1)
0159   // since shifting to right m, is the same as dividing by 2^m.
0160   seg_phi_t trk_abs_phi =
0161       (static_cast<seg_phi_t>(trk_col) << v3::kHitmapColFactorLog2) + (1 << (v3::kHitmapColFactorLog2 - 1));
0162   seg_phi_t sector_abs_phi =
0163       (static_cast<seg_phi_t>(sector_col) << v3::kHitmapColFactorLog2) + (1 << (v3::kHitmapColFactorLog2 - 1));
0164 
0165   // Calculate track phi
0166   // Note this is the track phi with respect to the sector center
0167   trk_feature_t trk_rel_phi = static_cast<trk_feature_t>(trk_abs_phi) - static_cast<trk_feature_t>(sector_abs_phi);
0168 
0169   // ===========================================================================
0170   // Get pattern info for each row
0171   // ---------------------------------------------------------------------------
0172   std::array<trk_col_t, v3::kHitmapNRows> trk_pat_begin;
0173   std::array<trk_col_t, v3::kHitmapNRows> trk_pat_center;
0174   std::array<trk_col_t, v3::kHitmapNRows> trk_pat_end;
0175   std::array<seg_phi_t, v3::kHitmapNRows> trk_pat_phi;
0176 
0177   for (unsigned int i_row = 0; i_row < v3::kHitmapNRows; ++i_row) {
0178     // Get the model pattern
0179     const auto& model_pat_row = (*model_pat)[i_row];
0180 
0181     // Offset the pattern's begin, center, and end by the track column
0182     trk_pat_begin[i_row] = trk_col + model_pat_row.begin;
0183     trk_pat_center[i_row] = trk_col + model_pat_row.center;
0184     trk_pat_end[i_row] = trk_col + model_pat_row.end;
0185     trk_pat_phi[i_row] = 0;
0186 
0187     // Short-Circuit: If the pattern's center is less than the padding used
0188     // when matching the pattern to the hitmap then the pattern center is 0.
0189     // This is because at that point, the center is out-of-bounds.
0190     if (trk_pat_center[i_row] <= v3::kPatternMatchingPadding)
0191       continue;
0192 
0193     // When the center is beyond the padding, then the pattern
0194     // is in-bound, therefore we subtract the padding offset.
0195     // To get the center in terms of the non-padded row BW we need to remove padding
0196     // since col-padding + 1 should map to 1 in the non-padded hitmap
0197     const auto& temp_trk_pat_center = trk_pat_center[i_row] - v3::kPatternMatchingPadding;
0198 
0199     // Convert the pattern center to emtf_phi units
0200     trk_pat_phi[i_row] = (static_cast<seg_phi_t>(temp_trk_pat_center) << v3::kHitmapColFactorLog2) +
0201                          (1 << (v3::kHitmapColFactorLog2 - 1));
0202   }
0203 
0204   // ===========================================================================
0205   // Select segments using phi only
0206   // ---------------------------------------------------------------------------
0207 
0208   // clang-format off
0209     std::vector<std::vector<unsigned int>> site_chambers = {
0210         {  0,   1,   2,   9,  10,  11,  45}, // ME1/1
0211         {  3,   4,   5,  12,  13,  14,  46}, // ME1/2
0212         { 18,  19,  20,  48,  21,  22,  23,  24,  25,  26,  49}, // ME2/1 + ME2/2
0213         { 27,  28,  29,  50,  30,  31,  32,  33,  34,  35,  51}, // ME3/1 + ME3/2
0214         { 36,  37,  38,  52,  39,  40,  41,  42,  43,  44,  53}, // ME4/1 + ME4/2
0215         { 57,  58,  59,  66,  67,  68, 100}, // RE1/2
0216         { 75,  76,  77,  78,  79,  80, 103}, // RE2/2
0217         { 81,  82,  83, 104,  84,  85,  86,  87,  88,  89, 105}, // RE3/1 + RE3/2
0218         { 90,  91,  92, 106,  93,  94,  95,  96,  97,  98, 107}, // RE4/1 + RE4/2
0219         { 54,  55,  56,  63,  64,  65,  99}, // GE1/1 
0220         { 72,  73,  74, 102}, // GE2/1
0221         {108, 109, 110, 111, 112, 113, 114} // ME0
0222     };
0223 
0224     std::vector<unsigned int> site_chamber_orders = {
0225         0, 0, 2, 2, 2, 0, 0, 2, 2, 0, 1, 0
0226     };
0227 
0228     std::vector<std::vector<int>> chamber_orders = {
0229         {-1, -1,  6, -1,  0,  1, -1,  2,  3, -1,  4,  5},
0230         { 3, -1, -1,  0, -1, -1,  1, -1, -1,  2, -1, -1},
0231         { 3, -1, 10,  0,  4,  5,  1,  6,  7,  2,  8,  9}
0232     };
0233   // clang-format on
0234 
0235   auto n_rows = model_hm.size();
0236 
0237   for (unsigned int i_row = 0; i_row < n_rows; ++i_row) {  // Begin loop rows
0238 
0239     const auto& model_hm_row = model_hm[i_row];
0240 
0241     const auto& trk_pat_row_begin = trk_pat_begin[i_row];
0242     const auto& trk_pat_row_end = trk_pat_end[i_row];
0243     const auto& trk_pat_row_phi = trk_pat_phi[i_row];
0244 
0245     if (this->context_.config_.verbosity_ > 2) {
0246       edm::LogInfo("L1TEMTFpp") << "Pattern Row:"
0247                                 << " row " << i_row << " begin " << trk_pat_row_begin << " end " << trk_pat_row_end
0248                                 << " phi " << trk_pat_row_phi << std::endl;
0249     }
0250 
0251     for (const auto& model_hm_site : model_hm_row) {  // Begin loop sites in row
0252 
0253       const int site_id = static_cast<int>(model_hm_site.id);
0254 
0255       auto& site_seg_id = track.site_segs[site_id];
0256       auto& site_bit = track.site_mask[site_id];
0257       auto& site_min_phi_diff = trk_seg_phi_diff[site_id];
0258 
0259       const auto& s_chambers = site_chambers[site_id];
0260       const auto& s_chamber_order_id = site_chamber_orders[site_id];
0261       const auto& s_chamber_order = chamber_orders[s_chamber_order_id];
0262 
0263       for (const auto& chamber_idx : s_chamber_order) {  // Begin loop chambers in site
0264 
0265         if (chamber_idx == -1)
0266           continue;
0267 
0268         int chamber_id = s_chambers[chamber_idx];
0269 
0270         for (unsigned int i_ch_seg = 0; i_ch_seg < v3::kChamberSegments; ++i_ch_seg) {  // Begin loop segments
0271 
0272           const int seg_id = chamber_id * v3::kChamberSegments + i_ch_seg;
0273           const auto& seg = segments[seg_id];
0274 
0275           // Short-Circuit: If the segment is invalid move on
0276           if (!seg.valid) {
0277             continue;
0278           }
0279 
0280           // Short-Circuit: If the segment is not in the zone move on
0281           if ((seg.zones & bit_sel_zone) != bit_sel_zone) {
0282             continue;
0283           }
0284 
0285           // Short-Circuit: If the segment is outside of the pattern move on
0286           const trk_col_t seg_col = (seg.phi >> 4) + v3::kPatternMatchingPadding;
0287 
0288           if (!(trk_pat_row_begin <= seg_col && seg_col <= trk_pat_row_end)) {
0289             continue;
0290           }
0291 
0292           // Calculate abs diff between the pattern's row phi and the segment's phi
0293           seg_phi_t diff;
0294 
0295           if (trk_pat_row_phi > seg.phi) {
0296             diff = trk_pat_row_phi - seg.phi;
0297           } else {
0298             diff = seg.phi - trk_pat_row_phi;
0299           }
0300 
0301           if (this->context_.config_.verbosity_ > 2) {
0302             edm::LogInfo("L1TEMTFpp") << "Site candidate:"
0303                                       << " site_id " << site_id << " seg_id " << seg_id << " seg_phi " << seg.phi
0304                                       << " seg_theta1 " << seg.theta1 << " seg_theta2 " << seg.theta2 << " seg_bend "
0305                                       << seg.bend << std::endl;
0306           }
0307 
0308           // Short-Circuit: If the difference is larger than the min diff move on
0309           if (site_bit == 1 && site_min_phi_diff <= diff)
0310             continue;
0311 
0312           // Select better segment
0313           site_seg_id = seg_id;
0314           site_bit = 1;
0315           site_min_phi_diff = diff;
0316         }  // End loop segments
0317 
0318       }  // End loop chambers in site
0319 
0320       // Debug Info
0321       if (this->context_.config_.verbosity_ > 2 && site_bit == 1) {
0322         edm::LogInfo("L1TEMTFpp") << "Segment attached:"
0323                                   << " site_id " << site_id << " seg_id " << site_seg_id << " seg_phi "
0324                                   << segments[site_seg_id].phi << " seg_theta1 " << segments[site_seg_id].theta1
0325                                   << " seg_theta2 " << segments[site_seg_id].theta2 << " seg_bend "
0326                                   << segments[site_seg_id].bend << std::endl;
0327       }
0328     }  // End loop sites in row
0329 
0330   }  // End loop rows
0331 
0332   // ===========================================================================
0333   // Calculate theta medians
0334   // ---------------------------------------------------------------------------
0335   const auto& model_thmc = model.theta_medians_;
0336 
0337   std::vector<seg_theta_t> theta_medians;
0338 
0339   for (const auto& model_thm : model_thmc) {  // Begin loop model theta medians
0340 
0341     std::vector<seg_theta_t> group_medians;
0342 
0343     for (const auto& model_thm_group : model_thm) {  // Begin loop theta median groups
0344 
0345       std::vector<seg_theta_t> group;
0346 
0347       for (const auto& model_thm_site : model_thm_group) {  // Begin loop group sites
0348         int site_id = static_cast<int>(model_thm_site.id);
0349 
0350         const auto& site_bit = track.site_mask[site_id];
0351 
0352         // Initialize as invalid theta
0353         auto& theta = group.emplace_back(invalid_theta);
0354 
0355         // Short-Circuit: If no segment was selected, move on.
0356         if (site_bit == 0)
0357           continue;
0358 
0359         // Get selected segment's theta value
0360         const auto& site_seg_id = track.site_segs[site_id];
0361         const auto& site_seg = segments[site_seg_id];
0362 
0363         if (model_thm_site.theta_id == theta_id_t::kTheta1) {
0364           theta = site_seg.theta1;
0365         } else if (model_thm_site.theta_id == theta_id_t::kTheta2) {
0366           theta = site_seg.theta2;
0367         }
0368 
0369         // If the segment theta is 0 this is invalid theta value
0370         if (theta == 0) {
0371           theta = invalid_theta;
0372         }
0373       }  // End loop group sites
0374 
0375       // Calculate theta median
0376       if (this->context_.config_.verbosity_ > 2) {
0377         for (const auto& theta : group) {
0378           edm::LogInfo("L1TEMTFpp") << "theta " << theta << std::endl;
0379         }
0380       }
0381 
0382       auto group_median = calc_theta_median(group);
0383       group_medians.push_back(group_median);
0384 
0385       if (this->context_.config_.verbosity_ > 2) {
0386         edm::LogInfo("L1TEMTFpp") << "group_median " << group_median << std::endl;
0387       }
0388     }  // End loop theta median groups
0389 
0390     // Calculate model_thm_group median
0391     auto theta_median = calc_theta_median(group_medians);
0392     theta_medians.push_back(theta_median);
0393 
0394     if (this->context_.config_.verbosity_ > 2) {
0395       edm::LogInfo("L1TEMTFpp") << "theta_median " << theta_median << std::endl;
0396     }
0397   }  // End loop theta medians
0398 
0399   // ===========================================================================
0400   // Select track theta
0401   // ---------------------------------------------------------------------------
0402   seg_theta_t trk_abs_theta;
0403 
0404   if (trk_zone != 2) {
0405     trk_abs_theta = theta_medians[0];
0406   } else {
0407     trk_abs_theta = theta_medians[1];
0408   }
0409 
0410   // If median is invalid, try station 1 median
0411   if (trk_abs_theta == invalid_theta) {
0412     trk_abs_theta = theta_medians[2];
0413   }
0414 
0415   // If all medians are invalid use 0 (0 is an invalid theta)
0416   if (trk_abs_theta == invalid_theta) {
0417     trk_abs_theta = 0;
0418   }
0419 
0420   // ===========================================================================
0421   // Compare segment theta to track theta
0422   // ---------------------------------------------------------------------------
0423 
0424   // if theta_window < diff, it is invalid
0425 
0426   // clang-format off
0427     std::vector<std::vector<seg_theta_t>> site_theta_window = {
0428         {5, 0, 2, 2, 2, 34, 0, 3, 3, 5, 6, 5},
0429         {5, 9, 5, 4, 5, 14, 7, 7, 7, 7, 7, 4},
0430         {11, 6, 5, 6, 6, 10, 8, 8, 9, 8, 0, 0}
0431     };
0432   // clang-format on
0433 
0434   if (displaced_en) {
0435     // clang-format off
0436         site_theta_window = {
0437             {14, 40, 4, 3, 3, 45, 0, 4, 4, 15, 8, 13},
0438             {16, 18, 7, 5, 5, 22, 7, 7, 8, 17, 9, 14},
0439             {26, 15, 8, 9, 9, 17, 11, 9, 10, 26, 21, 0}
0440         };
0441     // clang-format on
0442   }
0443 
0444   for (unsigned int site_id = 0; site_id < v3::kNumTrackSites; ++site_id) {
0445     auto& site_bit = track.site_mask[site_id];
0446     auto& site_rm_bit = track.site_rm_mask[site_id];
0447 
0448     // Get Theta Window
0449     const auto& theta_window = site_theta_window[trk_zone][site_id];
0450 
0451     // Short-Circuit: If no segment was selected, move on.
0452     if (site_bit == 0)
0453       continue;
0454 
0455     const auto& site_seg_id = track.site_segs[site_id];
0456     const auto& site_seg = segments[site_seg_id];
0457 
0458     // Init differences with out-of-bounds values
0459     seg_theta_t diff_1 = theta_window + 1;
0460     seg_theta_t diff_2 = theta_window + 1;
0461 
0462     // Calculate abs theta 1 diff
0463     if (site_seg.theta1 != 0) {
0464       if (site_seg.theta1 < trk_abs_theta) {
0465         diff_1 = trk_abs_theta - site_seg.theta1;
0466       } else {
0467         diff_1 = site_seg.theta1 - trk_abs_theta;
0468       }
0469     }
0470 
0471     // Calculate abs theta 2 diff
0472     if (site_seg.theta2 != 0) {
0473       if (site_seg.theta2 < trk_abs_theta) {
0474         diff_2 = trk_abs_theta - site_seg.theta2;
0475       } else {
0476         diff_2 = site_seg.theta2 - trk_abs_theta;
0477       }
0478     }
0479 
0480     // Select the theta with the smallest difference
0481     if (diff_1 <= diff_2 && diff_1 < theta_window) {
0482       // Select theta 1 as the correct theta value
0483       trk_seg_theta[site_id] = site_seg.theta1;
0484     } else if (diff_2 < theta_window) {
0485       // Select theta 2 as the correct theta value
0486       trk_seg_theta[site_id] = site_seg.theta2;
0487     } else {
0488       // Invalidate site if both differences are outside of the theta window
0489       site_bit = 0;
0490       site_rm_bit = 1;
0491 
0492       // Debug Info
0493       if (this->context_.config_.verbosity_ > 4) {
0494         edm::LogInfo("L1TEMTFpp") << "Segment outside of theta window; detatched:"
0495                                   << " site_id " << site_id << " seg_id " << site_seg_id << " seg_phi " << site_seg.phi
0496                                   << " seg_theta1 " << site_seg.theta1 << " seg_theta2 " << site_seg.theta2
0497                                   << std::endl;
0498       }
0499     }
0500   }
0501 
0502   // ===========================================================================
0503   // Assign Data
0504   // ---------------------------------------------------------------------------
0505   track.zone = trk_zone;
0506   track.col = trk_col;
0507   track.pattern = trk_pattern;
0508   track.quality = trk_quality;
0509   track.phi = trk_abs_phi;
0510   track.theta = trk_abs_theta;
0511   track.valid = 1;
0512 
0513   // ===========================================================================
0514   // Fill features
0515   // ---------------------------------------------------------------------------
0516   int i_feature = 0;
0517 
0518   for (auto& model_ft : model_ftc) {
0519     for (auto& model_ft_site : model_ft.sites) {
0520       int site_id = static_cast<int>(model_ft_site);
0521 
0522       const auto& site_seg_id = track.site_segs[site_id];
0523       const auto& site_bit = track.site_mask[site_id];
0524       const auto& site_seg = segments[site_seg_id];
0525 
0526       auto& trk_feature = track.features[i_feature++];
0527 
0528       // Short-Circuit: No segment attached
0529       if (site_bit == 0) {
0530         continue;
0531       }
0532 
0533       // Fill features
0534       if (model_ft.id == feature_id_t::kPhi) {
0535         // Note: This is the segment's phi with respect to the track's abs phi
0536         trk_feature = static_cast<trk_feature_t>(site_seg.phi) - static_cast<trk_feature_t>(trk_abs_phi);
0537       } else if (model_ft.id == feature_id_t::kTheta) {
0538         // Note: This is the segment's theta with respect to the track's abs theta
0539         trk_feature = static_cast<trk_feature_t>(trk_seg_theta[site_id]) - static_cast<trk_feature_t>(trk_abs_theta);
0540       } else if (model_ft.id == feature_id_t::kBend) {
0541         trk_feature = site_seg.bend;
0542       } else if (model_ft.id == feature_id_t::kQuality) {
0543         trk_feature = site_seg.qual1;
0544       }
0545     }
0546   }
0547 
0548   // Additional features
0549   track.features[i_feature++] = trk_quality > 0 ? trk_rel_phi : decltype(trk_rel_phi)(0);
0550   track.features[i_feature++] = trk_quality > 0 ? trk_abs_theta : decltype(trk_abs_theta)(0);
0551   track.features[i_feature++] = trk_quality;
0552   track.features[i_feature++] = 0;  // unused
0553 
0554   // Debug Info
0555   if (this->context_.config_.verbosity_ > 1) {
0556     edm::LogInfo("L1TEMTFpp") << "Track"
0557                               << " zone " << track.zone << " col " << track.col << " pat " << track.pattern << " qual "
0558                               << track.quality << " sector_abs_phi " << sector_abs_phi << " abs_phi " << track.phi
0559                               << " rel_phi " << trk_rel_phi << " abs_theta " << track.theta << " features "
0560                               << std::endl;
0561 
0562     for (unsigned int i = 0; i < v3::kNumTrackFeatures; ++i) {
0563       if (i > 0) {
0564         edm::LogInfo("L1TEMTFpp") << " ";
0565       }
0566 
0567       edm::LogInfo("L1TEMTFpp") << track.features[i];
0568     }
0569 
0570     edm::LogInfo("L1TEMTFpp") << std::endl;
0571   }
0572 }