Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-07 04:36:47

0001 #include "L1Trigger/DTTriggerPhase2/interface/MuonPathSLFitter.h"
0002 #include <cmath>
0003 #include <memory>
0004 
0005 using namespace edm;
0006 using namespace std;
0007 using namespace cmsdt;
0008 // ============================================================================
0009 // Constructors and destructor
0010 // ============================================================================
0011 MuonPathSLFitter::MuonPathSLFitter(const ParameterSet &pset,
0012                                    edm::ConsumesCollector &iC,
0013                                    std::shared_ptr<GlobalCoordsObtainer> &globalcoordsobtainer)
0014     : MuonPathFitter(pset, iC, globalcoordsobtainer) {
0015   if (debug_)
0016     LogDebug("MuonPathSLFitter") << "MuonPathSLFitter: constructor";
0017 
0018   //shift theta
0019   int rawId;
0020   double shift;
0021   shift_theta_filename_ = pset.getParameter<edm::FileInPath>("shift_theta_filename");
0022   std::ifstream ifin4(shift_theta_filename_.fullPath());
0023   if (ifin4.fail()) {
0024     throw cms::Exception("Missing Input File")
0025         << "MuonPathSLFitter::MuonPathSLFitter() -  Cannot find " << shift_theta_filename_.fullPath();
0026   }
0027 
0028   while (ifin4.good()) {
0029     ifin4 >> rawId >> shift;
0030     shiftthetainfo_[rawId] = shift;
0031   }
0032 
0033   // LUTs
0034   sl1_filename_ = pset.getParameter<edm::FileInPath>("lut_sl1");
0035   sl2_filename_ = pset.getParameter<edm::FileInPath>("lut_sl2");
0036   sl3_filename_ = pset.getParameter<edm::FileInPath>("lut_sl3");
0037 
0038   fillLuts();
0039 
0040   setChi2Th(pset.getParameter<double>("chi2Th"));
0041   setTanPhiTh(pset.getParameter<double>("tanPhiTh"));
0042 }
0043 
0044 MuonPathSLFitter::~MuonPathSLFitter() {
0045   if (debug_)
0046     LogDebug("MuonPathSLFitter") << "MuonPathSLFitter: destructor";
0047 }
0048 
0049 // ============================================================================
0050 // Main methods (initialise, run, finish)
0051 // ============================================================================
0052 void MuonPathSLFitter::initialise(const edm::EventSetup &iEventSetup) {
0053   if (debug_)
0054     LogDebug("MuonPathSLFitter") << "MuonPathSLFitter::initialiase";
0055 
0056   auto geom = iEventSetup.getHandle(dtGeomH);
0057   dtGeo_ = &(*geom);
0058 }
0059 
0060 void MuonPathSLFitter::run(edm::Event &iEvent,
0061                            const edm::EventSetup &iEventSetup,
0062                            MuonPathPtrs &muonpaths,
0063                            std::vector<lat_vector> &lateralities,
0064                            std::vector<metaPrimitive> &metaPrimitives) {
0065   if (debug_)
0066     LogDebug("MuonPathSLFitter") << "MuonPathSLFitter: run";
0067 
0068   // fit per SL (need to allow for multiple outputs for a single mpath)
0069   // for (auto &muonpath : muonpaths) {
0070   if (!muonpaths.empty()) {
0071     auto muonpath = muonpaths[0];
0072     int rawId = muonpath->primitive(0)->cameraId();
0073     if (muonpath->primitive(0)->cameraId() == -1) {
0074       rawId = muonpath->primitive(1)->cameraId();
0075     }
0076     const DTLayerId dtLId(rawId);
0077     max_drift_tdc = maxdriftinfo_[dtLId.wheel() + 2][dtLId.station() - 1][dtLId.sector() - 1];
0078   }
0079 
0080   for (size_t i = 0; i < muonpaths.size(); i++) {
0081     auto muonpath = muonpaths[i];
0082     auto lats = lateralities[i];
0083     analyze(muonpath, lats, metaPrimitives);
0084   }
0085 }
0086 
0087 void MuonPathSLFitter::finish() {
0088   if (debug_)
0089     LogDebug("MuonPathSLFitter") << "MuonPathSLFitter: finish";
0090 };
0091 
0092 //------------------------------------------------------------------
0093 //--- Metodos privados
0094 //------------------------------------------------------------------
0095 
0096 void MuonPathSLFitter::analyze(MuonPathPtr &inMPath,
0097                                lat_vector lat_combs,
0098                                std::vector<cmsdt::metaPrimitive> &metaPrimitives) {
0099   auto sl = inMPath->primitive(0)->superLayerId();  // 0, 1, 2
0100 
0101   int selected_lay = 1;
0102   if (inMPath->primitive(0)->cameraId() > 0)
0103     selected_lay = 0;
0104 
0105   int dumLayId = inMPath->primitive(selected_lay)->cameraId();
0106   auto dtDumlayerId = DTLayerId(dumLayId);
0107   DTSuperLayerId MuonPathSLId(dtDumlayerId.wheel(), dtDumlayerId.station(), dtDumlayerId.sector(), sl + 1);
0108 
0109   DTChamberId ChId(MuonPathSLId.wheel(), MuonPathSLId.station(), MuonPathSLId.sector());
0110 
0111   DTSuperLayerId MuonPathSL1Id(dtDumlayerId.wheel(), dtDumlayerId.station(), dtDumlayerId.sector(), 1);
0112   DTSuperLayerId MuonPathSL2Id(dtDumlayerId.wheel(), dtDumlayerId.station(), dtDumlayerId.sector(), 2);
0113   DTSuperLayerId MuonPathSL3Id(dtDumlayerId.wheel(), dtDumlayerId.station(), dtDumlayerId.sector(), 3);
0114   DTWireId wireIdSL1(MuonPathSL1Id, 2, 1);
0115   DTWireId wireIdSL2(MuonPathSL2Id, 2, 1);
0116   DTWireId wireIdSL3(MuonPathSL3Id, 2, 1);
0117   auto sl_shift_cm = shiftinfo_[wireIdSL1.rawId()] - shiftinfo_[wireIdSL3.rawId()];
0118 
0119   fit_common_in_t fit_common_in;
0120 
0121   // 8-element vectors, for the 8 layers. As here we are fitting one SL only, we leave the other SL values as dummy ones
0122   fit_common_in.hits = {};
0123   fit_common_in.hits_valid = {};
0124 
0125   int quality = 3;
0126   if (inMPath->missingLayer() != -1)
0127     quality = 1;
0128 
0129   int minISL = 1;
0130   int maxISL = 3;
0131   if (sl < 1) {
0132     minISL = 0;
0133     maxISL = 2;
0134   }
0135 
0136   for (int isl = minISL; isl < maxISL; isl++) {
0137     for (int i = 0; i < NUM_LAYERS; i++) {
0138       if (isl == sl && inMPath->missingLayer() != i) {
0139         // Include both valid and non-valid hits. Non-valid values can be whatever, leaving all as -1 to make debugging easier.
0140         auto ti = inMPath->primitive(i)->tdcTimeStamp();
0141         if (ti != -1)
0142           ti = (int)round(((float)TIME_TO_TDC_COUNTS / (float)LHC_CLK_FREQ) * ti);
0143         auto wi = inMPath->primitive(i)->channelId();
0144         auto ly = inMPath->primitive(i)->layerId();
0145         // int layId = inMPath->primitive(i)->cameraId();
0146         // auto dtlayerId = DTLayerId(layId);
0147         // auto wireId = DTWireId(dtlayerId, wi + 1); // wire start from 1, mixer groups them starting from 0
0148         // int rawId = wireId.rawId();
0149         // wp in tdc counts (still in floating point)
0150         int wp_semicells = (wi - SL1_CELLS_OFFSET) * 2 + 1;
0151         if (ly % 2 == 1)
0152           wp_semicells -= 1;
0153         if (isl == 2)
0154           wp_semicells -= (int)round((sl_shift_cm * 10) / CELL_SEMILENGTH);
0155 
0156         float wp_tdc = wp_semicells * max_drift_tdc;
0157         int wp = (int)((long int)(round(wp_tdc * std::pow(2, WIREPOS_WIDTH))) / (int)std::pow(2, WIREPOS_WIDTH));
0158         fit_common_in.hits.push_back({ti, wi, ly, wp});
0159         // fill valids as well
0160         if (inMPath->missingLayer() == i)
0161           fit_common_in.hits_valid.push_back(0);
0162         else
0163           fit_common_in.hits_valid.push_back(1);
0164       } else {
0165         fit_common_in.hits.push_back({-1, -1, -1, -1});
0166         fit_common_in.hits_valid.push_back(0);
0167       }
0168     }
0169   }
0170 
0171   int smallest_time = 999999, tmp_coarse_wirepos_1 = -1, tmp_coarse_wirepos_3 = -1;
0172   // coarse_bctr is the 12 MSB of the smallest tdc
0173   for (int isl = 0; isl < 3; isl++) {
0174     if (isl != sl)
0175       continue;
0176     int myisl = isl < 2 ? 0 : 1;
0177     for (size_t i = 0; i < NUM_LAYERS; i++) {
0178       if (fit_common_in.hits_valid[NUM_LAYERS * myisl + i] == 0)
0179         continue;
0180       else if (fit_common_in.hits[NUM_LAYERS * myisl + i].ti < smallest_time)
0181         smallest_time = fit_common_in.hits[NUM_LAYERS * myisl + i].ti;
0182     }
0183     if (fit_common_in.hits_valid[NUM_LAYERS * myisl + 0] == 1)
0184       tmp_coarse_wirepos_1 = fit_common_in.hits[NUM_LAYERS * myisl + 0].wp;
0185     else
0186       tmp_coarse_wirepos_1 = fit_common_in.hits[NUM_LAYERS * myisl + 1].wp;
0187     if (fit_common_in.hits_valid[NUM_LAYERS * myisl + 3] == 1)
0188       tmp_coarse_wirepos_3 = fit_common_in.hits[NUM_LAYERS * myisl + 3].wp;
0189     else
0190       tmp_coarse_wirepos_3 = fit_common_in.hits[NUM_LAYERS * myisl + 2].wp;
0191 
0192     tmp_coarse_wirepos_1 = tmp_coarse_wirepos_1 >> WIREPOS_NORM_LSB_IGNORED;
0193     tmp_coarse_wirepos_3 = tmp_coarse_wirepos_3 >> WIREPOS_NORM_LSB_IGNORED;
0194   }
0195   fit_common_in.coarse_bctr = smallest_time >> (WIDTH_FULL_TIME - WIDTH_COARSED_TIME);
0196   fit_common_in.coarse_wirepos = (tmp_coarse_wirepos_1 + tmp_coarse_wirepos_3) >> 1;
0197 
0198   for (auto &lat_comb : lat_combs) {
0199     if (lat_comb[0] == 0 && lat_comb[1] == 0 && lat_comb[2] == 0 && lat_comb[3] == 0)
0200       continue;
0201     fit_common_in.lateralities.clear();
0202 
0203     auto rom_addr = get_rom_addr(inMPath, lat_comb);
0204     coeffs_t coeffs;
0205     if (sl == 0) {
0206       coeffs =
0207           RomDataConvert(lut_sl1[rom_addr], COEFF_WIDTH_SL_T0, COEFF_WIDTH_SL_POSITION, COEFF_WIDTH_SL_SLOPE, 0, 3);
0208     } else if (sl == 1) {
0209       coeffs =
0210           RomDataConvert(lut_sl2[rom_addr], COEFF_WIDTH_SL_T0, COEFF_WIDTH_SL2_POSITION, COEFF_WIDTH_SL_SLOPE, 0, 3);
0211     } else {
0212       coeffs =
0213           RomDataConvert(lut_sl3[rom_addr], COEFF_WIDTH_SL_T0, COEFF_WIDTH_SL_POSITION, COEFF_WIDTH_SL_SLOPE, 4, 7);
0214     }
0215     // Filling lateralities
0216     int minISL = 1;
0217     int maxISL = 3;
0218     if (sl < 1) {
0219       minISL = 0;
0220       maxISL = 2;
0221     }
0222 
0223     for (int isl = minISL; isl < maxISL; isl++) {
0224       for (size_t i = 0; i < NUM_LAYERS; i++) {
0225         if (isl == sl) {
0226           fit_common_in.lateralities.push_back(lat_comb[i]);
0227         } else
0228           fit_common_in.lateralities.push_back(-1);
0229       }
0230     }
0231     fit_common_in.coeffs = coeffs;
0232 
0233     auto fit_common_out = fit(fit_common_in,
0234                               XI_SL_WIDTH,
0235                               COEFF_WIDTH_SL_T0,
0236                               sl == 1 ? COEFF_WIDTH_SL2_POSITION : COEFF_WIDTH_SL_POSITION,
0237                               COEFF_WIDTH_SL_SLOPE,
0238                               PRECISSION_SL_T0,
0239                               PRECISSION_SL_POSITION,
0240                               PRECISSION_SL_SLOPE,
0241                               PROD_RESIZE_SL_T0,
0242                               sl == 1 ? PROD_RESIZE_SL2_POSITION : PROD_RESIZE_SL_POSITION,
0243                               PROD_RESIZE_SL_SLOPE,
0244                               max_drift_tdc,
0245                               sl + 1);
0246 
0247     if (fit_common_out.valid_fit == 1) {
0248       float t0_f = ((float)fit_common_out.t0) * (float)LHC_CLK_FREQ / (float)TIME_TO_TDC_COUNTS;
0249 
0250       float slope_f = -fit_common_out.slope * ((float)CELL_SEMILENGTH / max_drift_tdc) * (1) / (CELL_SEMIHEIGHT * 16.);
0251       if (sl != 1 && std::abs(slope_f) > tanPhiTh_)
0252         continue;
0253 
0254       DTWireId wireId(MuonPathSLId, 2, 1);
0255       float pos_ch_f = (float)(fit_common_out.position) * ((float)CELL_SEMILENGTH / (float)max_drift_tdc) / 10;
0256       pos_ch_f += (SL1_CELLS_OFFSET * CELL_LENGTH) / 10.;
0257       if (sl != 1)
0258         pos_ch_f += shiftinfo_[wireIdSL1.rawId()];
0259       else if (sl == 1)
0260         pos_ch_f += shiftthetainfo_[wireIdSL2.rawId()];
0261 
0262       float pos_sl_f = pos_ch_f - (sl - 1) * slope_f * VERT_PHI1_PHI3 / 2;
0263       float chi2_f = fit_common_out.chi2 * std::pow(((float)CELL_SEMILENGTH / (float)max_drift_tdc), 2) / 100;
0264 
0265       // obtention of global coordinates using luts
0266       int pos = (int)(10 * (pos_sl_f - shiftinfo_[wireId.rawId()]) * INCREASED_RES_POS_POW);
0267 
0268       LogDebug("MuonPathSLFitter")
0269           << "========================= SUPERLAYER PRIMITIVE =================================";
0270       LogDebug("MuonPathSLFitter") << "WHEEL = " << ChId.wheel();
0271       LogDebug("MuonPathSLFitter") << "SECTOR = " << ChId.sector();
0272       LogDebug("MuonPathSLFitter") << "STATION = " << ChId.station();
0273       LogDebug("MuonPathSLFitter") << "SUPERLAYER = " << sl;
0274       LogDebug("MuonPathSLFitter") << "QUALITY = " << quality;
0275       LogDebug("MuonPathSLFitter") << "POSITION = " << (double)fit_common_out.position;
0276       LogDebug("MuonPathSLFitter") << "SLOPE = " << (double)fit_common_out.slope;
0277 
0278       auto global_coords = globalcoordsobtainer_->get_global_coordinates(
0279           ChId.rawId(), sl + 1, fit_common_out.position, fit_common_out.slope);
0280       float phi = global_coords[0];
0281       float phiB = global_coords[1];
0282 
0283       // obtention of global coordinates using cmssw geometry
0284       double z = 0;
0285       if (ChId.station() == 3 or ChId.station() == 4) {
0286         z = Z_SHIFT_MB4;
0287       }
0288       GlobalPoint jm_x_cmssw_global = dtGeo_->chamber(ChId)->toGlobal(LocalPoint(pos_sl_f, 0., z));
0289       int thisec = ChId.sector();
0290       if (thisec == 13)
0291         thisec = 4;
0292       if (thisec == 14)
0293         thisec = 10;
0294       float phi_cmssw = jm_x_cmssw_global.phi() - PHI_CONV * (thisec - 1);
0295       float psi = atan(slope_f);
0296       float phiB_cmssw = hasPosRF(ChId.wheel(), ChId.sector()) ? psi - phi_cmssw : -psi - phi_cmssw;
0297       if (sl == 0)
0298         metaPrimitives.emplace_back(metaPrimitive({MuonPathSLId.rawId(),
0299                                                    t0_f,
0300                                                    (double)(fit_common_out.position),
0301                                                    (double)fit_common_out.slope,
0302                                                    phi,
0303                                                    phiB,
0304                                                    phi_cmssw,
0305                                                    phiB_cmssw,
0306                                                    chi2_f,
0307                                                    quality,
0308                                                    inMPath->primitive(0)->channelId(),
0309                                                    inMPath->primitive(0)->tdcTimeStamp(),
0310                                                    lat_comb[0],
0311                                                    inMPath->primitive(1)->channelId(),
0312                                                    inMPath->primitive(1)->tdcTimeStamp(),
0313                                                    lat_comb[1],
0314                                                    inMPath->primitive(2)->channelId(),
0315                                                    inMPath->primitive(2)->tdcTimeStamp(),
0316                                                    lat_comb[2],
0317                                                    inMPath->primitive(3)->channelId(),
0318                                                    inMPath->primitive(3)->tdcTimeStamp(),
0319                                                    lat_comb[3],
0320                                                    -1,
0321                                                    -1,
0322                                                    -1,
0323                                                    -1,
0324                                                    -1,
0325                                                    -1,
0326                                                    -1,
0327                                                    -1,
0328                                                    -1,
0329                                                    -1,
0330                                                    -1,
0331                                                    -1,
0332                                                    -1}));
0333       else if (sl == 2)
0334         metaPrimitives.emplace_back(metaPrimitive({MuonPathSLId.rawId(),
0335                                                    t0_f,
0336                                                    (double)(fit_common_out.position),
0337                                                    (double)fit_common_out.slope,
0338                                                    phi,
0339                                                    phiB,
0340                                                    phi_cmssw,
0341                                                    phiB_cmssw,
0342                                                    chi2_f,
0343                                                    quality,
0344                                                    -1,
0345                                                    -1,
0346                                                    -1,
0347                                                    -1,
0348                                                    -1,
0349                                                    -1,
0350                                                    -1,
0351                                                    -1,
0352                                                    -1,
0353                                                    -1,
0354                                                    -1,
0355                                                    -1,
0356                                                    inMPath->primitive(0)->channelId(),
0357                                                    inMPath->primitive(0)->tdcTimeStamp(),
0358                                                    lat_comb[0],
0359                                                    inMPath->primitive(1)->channelId(),
0360                                                    inMPath->primitive(1)->tdcTimeStamp(),
0361                                                    lat_comb[1],
0362                                                    inMPath->primitive(2)->channelId(),
0363                                                    inMPath->primitive(2)->tdcTimeStamp(),
0364                                                    lat_comb[2],
0365                                                    inMPath->primitive(3)->channelId(),
0366                                                    inMPath->primitive(3)->tdcTimeStamp(),
0367                                                    lat_comb[3],
0368                                                    -1}));
0369       else if (sl == 1) {
0370         // fw-like calculation
0371         DTLayerId SL2_layer2Id(MuonPathSLId, 2);
0372         double z_shift = shiftthetainfo_[SL2_layer2Id.rawId()];
0373         double pos_cm =
0374             pos / 10 / INCREASED_RES_POS_POW;  // fixed to have z_shift and the position in the same units (MC)
0375         double jm_y = hasPosRF(MuonPathSLId.wheel(), MuonPathSLId.sector()) ? z_shift - pos_cm : z_shift + pos_cm;
0376 
0377         phi = jm_y;
0378 
0379         // Fixed sign of k (MC)
0380         double k_fromfw = hasPosRF(MuonPathSLId.wheel(), MuonPathSLId.sector()) ? slope_f : -slope_f;
0381         phiB = k_fromfw;
0382 
0383         // cmssw-like calculation
0384         LocalPoint wire1_in_layer(dtGeo_->layer(SL2_layer2Id)->specificTopology().wirePosition(1), 0, -0.65);
0385         GlobalPoint wire1_in_global = dtGeo_->layer(SL2_layer2Id)->toGlobal(wire1_in_layer);
0386         LocalPoint wire1_in_sl = dtGeo_->superLayer(MuonPathSLId)->toLocal(wire1_in_global);
0387         double x_shift = wire1_in_sl.x();
0388         jm_y = (dtGeo_->superLayer(MuonPathSLId)
0389                     ->toGlobal(LocalPoint(double(pos) / (10 * pow(2, INCREASED_RES_POS)) + x_shift, 0., 0)))
0390                    .z();
0391         phi_cmssw = jm_y;
0392 
0393         double x_cmssw = (dtGeo_->superLayer(MuonPathSLId)
0394                               ->toGlobal(LocalPoint(double(pos) / (10 * pow(2, INCREASED_RES_POS)) + x_shift, 0., 0)))
0395                              .x();
0396         double y_cmssw = (dtGeo_->superLayer(MuonPathSLId)
0397                               ->toGlobal(LocalPoint(double(pos) / (10 * pow(2, INCREASED_RES_POS)) + x_shift, 0., 0)))
0398                              .y();
0399         double r_cmssw = sqrt(x_cmssw * x_cmssw + y_cmssw * y_cmssw);
0400         double k_cmssw = jm_y / r_cmssw;
0401         phiB_cmssw = k_cmssw;
0402 
0403         metaPrimitives.emplace_back(metaPrimitive({MuonPathSLId.rawId(),
0404                                                    t0_f,
0405                                                    (double)(fit_common_out.position),
0406                                                    (double)fit_common_out.slope,
0407                                                    phi,
0408                                                    phiB,
0409                                                    phi_cmssw,
0410                                                    phiB_cmssw,
0411                                                    chi2_f,
0412                                                    quality,
0413                                                    inMPath->primitive(0)->channelId(),
0414                                                    inMPath->primitive(0)->tdcTimeStamp(),
0415                                                    lat_comb[0],
0416                                                    inMPath->primitive(1)->channelId(),
0417                                                    inMPath->primitive(1)->tdcTimeStamp(),
0418                                                    lat_comb[1],
0419                                                    inMPath->primitive(2)->channelId(),
0420                                                    inMPath->primitive(2)->tdcTimeStamp(),
0421                                                    lat_comb[2],
0422                                                    inMPath->primitive(3)->channelId(),
0423                                                    inMPath->primitive(3)->tdcTimeStamp(),
0424                                                    lat_comb[3],
0425                                                    -1,
0426                                                    -1,
0427                                                    -1,
0428                                                    -1,
0429                                                    -1,
0430                                                    -1,
0431                                                    -1,
0432                                                    -1,
0433                                                    -1,
0434                                                    -1,
0435                                                    -1,
0436                                                    -1,
0437                                                    -1}));
0438       }
0439     }  // (fit_common_out.valid_fit == 1)
0440   }  // loop in lat_combs
0441   return;
0442 }
0443 
0444 void MuonPathSLFitter::fillLuts() {
0445   std::ifstream ifinsl1(sl1_filename_.fullPath());
0446   std::string line;
0447   while (ifinsl1.good()) {
0448     ifinsl1 >> line;
0449 
0450     std::vector<int> myNumbers;
0451     for (size_t i = 0; i < line.size(); i++) {
0452       // This converts the char into an int and pushes it into vec
0453       myNumbers.push_back(line[i] - '0');  // The digits will be in the same order as before
0454     }
0455     std::reverse(myNumbers.begin(), myNumbers.end());
0456     lut_sl1.push_back(myNumbers);
0457   }
0458 
0459   std::ifstream ifinsl2(sl2_filename_.fullPath());
0460   while (ifinsl2.good()) {
0461     ifinsl2 >> line;
0462 
0463     std::vector<int> myNumbers;
0464     for (size_t i = 0; i < line.size(); i++) {
0465       // This converts the char into an int and pushes it into vec
0466       myNumbers.push_back(line[i] - '0');  // The digits will be in the same order as before
0467     }
0468     std::reverse(myNumbers.begin(), myNumbers.end());
0469     lut_sl2.push_back(myNumbers);
0470   }
0471 
0472   std::ifstream ifinsl3(sl3_filename_.fullPath());
0473   while (ifinsl3.good()) {
0474     ifinsl3 >> line;
0475 
0476     std::vector<int> myNumbers;
0477     for (size_t i = 0; i < line.size(); i++) {
0478       // This converts the char into an int and pushes it into vec
0479       myNumbers.push_back(line[i] - '0');  // The digits will be in the same order as before
0480     }
0481     std::reverse(myNumbers.begin(), myNumbers.end());
0482     lut_sl3.push_back(myNumbers);
0483   }
0484 
0485   return;
0486 }
0487 
0488 int MuonPathSLFitter::get_rom_addr(MuonPathPtr &inMPath, latcomb lats) {
0489   std::vector<int> rom_addr;
0490   auto missing_layer = inMPath->missingLayer();
0491   if (missing_layer == -1) {
0492     rom_addr.push_back(1);
0493     rom_addr.push_back(0);
0494   } else {
0495     if (missing_layer == 0) {
0496       rom_addr.push_back(0);
0497       rom_addr.push_back(0);
0498     } else if (missing_layer == 1) {
0499       rom_addr.push_back(0);
0500       rom_addr.push_back(1);
0501     } else if (missing_layer == 2) {
0502       rom_addr.push_back(1);
0503       rom_addr.push_back(0);
0504     } else {  // missing_layer == 3
0505       rom_addr.push_back(1);
0506       rom_addr.push_back(1);
0507     }
0508   }
0509   for (size_t ilat = 0; ilat < lats.size(); ilat++) {
0510     if ((int)ilat == missing_layer)  // only applies to 3-hit, as in 4-hit missL=-1
0511       continue;
0512     auto lat = lats[ilat];
0513     if (lat == -1)
0514       lat = 0;
0515     rom_addr.push_back(lat);
0516   }
0517   std::reverse(rom_addr.begin(), rom_addr.end());
0518   return vhdl_unsigned_to_int(rom_addr);
0519 }