Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-25 02:14:14

0001 #include "Event.h"
0002 #include "RecoTracker/MkFitCore/interface/IterationConfig.h"
0003 #include "RecoTracker/MkFitCore/interface/TrackerInfo.h"
0004 
0005 //#define DEBUG
0006 #include "RecoTracker/MkFitCore/src/Debug.h"
0007 
0008 #ifdef TBB
0009 #include "oneapi/tbb/parallel_for.h"
0010 #endif
0011 
0012 #include <memory>
0013 
0014 namespace {
0015   std::unique_ptr<mkfit::Validation> dummyValidation(mkfit::Validation::make_validation("dummy", nullptr));
0016 }
0017 
0018 namespace mkfit {
0019 
0020   std::mutex Event::printmutex;
0021 
0022   Event::Event(int evtID, int nLayers) : validation_(*dummyValidation), evtID_(evtID) {
0023     layerHits_.resize(nLayers);
0024     layerHitMasks_.resize(nLayers);
0025   }
0026 
0027   Event::Event(Validation &v, int evtID, int nLayers) : validation_(v), evtID_(evtID) {
0028     layerHits_.resize(nLayers);
0029     layerHitMasks_.resize(nLayers);
0030     validation_.resetValidationMaps();  // need to reset maps for every event.
0031   }
0032 
0033   void Event::reset(int evtID) {
0034     evtID_ = evtID;
0035 
0036     for (auto &&l : layerHits_) {
0037       l.clear();
0038     }
0039     for (auto &&l : layerHitMasks_) {
0040       l.clear();
0041     }
0042 
0043     simHitsInfo_.clear();
0044     simTrackStates_.clear();
0045     simTracks_.clear();
0046     simTracksExtra_.clear();
0047     seedTracks_.clear();
0048     seedTracksExtra_.clear();
0049     candidateTracks_.clear();
0050     candidateTracksExtra_.clear();
0051     fitTracks_.clear();
0052     fitTracksExtra_.clear();
0053     cmsswTracks_.clear();
0054     cmsswTracksExtra_.clear();
0055     beamSpot_ = {};
0056 
0057     validation_.resetValidationMaps();  // need to reset maps for every event.
0058   }
0059 
0060   void Event::validate() {
0061     // special map needed for sim_val_for_cmssw + set the track scores
0062     if (Config::sim_val_for_cmssw) {
0063       validation_.makeRecoTkToSeedTkMapsDumbCMSSW(*this);
0064       validation_.setTrackScoresDumbCMSSW(*this);
0065     }
0066 
0067     // standard eff/fr/dr validation
0068     if (Config::sim_val || Config::sim_val_for_cmssw) {
0069       validation_.setTrackExtras(*this);
0070       validation_.makeSimTkToRecoTksMaps(*this);
0071       validation_.makeSeedTkToRecoTkMaps(*this);
0072       validation_.fillEfficiencyTree(*this);
0073       validation_.fillFakeRateTree(*this);
0074     }
0075 
0076     // special cmssw to mkfit validation
0077     if (Config::cmssw_val) {
0078       validation_.makeCMSSWTkToSeedTkMap(*this);
0079       validation_.makeRecoTkToRecoTkMaps(*this);
0080       validation_.setTrackExtras(*this);
0081       validation_.makeCMSSWTkToRecoTksMaps(*this);
0082       validation_.fillCMSSWEfficiencyTree(*this);
0083       validation_.fillCMSSWFakeRateTree(*this);
0084     }
0085 
0086     if (Config::fit_val) {  // fit val for z-phi tuning
0087       validation_.fillFitTree(*this);
0088     }
0089   }
0090 
0091   void Event::printStats(const TrackVec &trks, TrackExtraVec &trkextras) {
0092     int miss(0), found(0), fp_10(0), fp_20(0), hit8(0), h8_10(0), h8_20(0);
0093 
0094     for (auto &&trk : trks) {
0095       auto &&extra = trkextras[trk.label()];
0096       extra.setMCTrackIDInfo(trk, layerHits_, simHitsInfo_, simTracks_, false, true);
0097       if (extra.mcTrackID() < 0) {
0098         ++miss;
0099       } else {
0100         auto &&mctrk = simTracks_[extra.mcTrackID()];
0101         auto pr = trk.pT() / mctrk.pT();
0102         found++;
0103         bool h8 = trk.nFoundHits() >= 8;
0104         bool pt10 = pr > 0.9 && pr < 1.1;
0105         bool pt20 = pr > 0.8 && pr < 1.2;
0106         fp_10 += pt10;
0107         fp_20 += pt20;
0108         hit8 += h8;
0109         h8_10 += h8 && pt10;
0110         h8_20 += h8 && pt20;
0111       }
0112     }
0113     std::cout << "found tracks=" << found << "  in pT 10%=" << fp_10 << "  in pT 20%=" << fp_20
0114               << "     no_mc_assoc=" << miss << std::endl
0115               << "  nH >= 8   =" << hit8 << "  in pT 10%=" << h8_10 << "  in pT 20%=" << h8_20 << std::endl;
0116   }
0117 
0118   void Event::write_out(DataFile &data_file) {
0119     FILE *fp = data_file.f_fp;
0120 
0121     static std::mutex writemutex;
0122     std::lock_guard<std::mutex> writelock(writemutex);
0123 
0124     auto start = ftell(fp);
0125     int evsize = sizeof(int);
0126     fwrite(&evsize, sizeof(int), 1, fp);  // this will be overwritten at the end
0127 
0128     evsize += write_tracks(fp, simTracks_);
0129 
0130     if (data_file.hasSimTrackStates()) {
0131       int nts = simTrackStates_.size();
0132       fwrite(&nts, sizeof(int), 1, fp);
0133       fwrite(&simTrackStates_[0], sizeof(TrackState), nts, fp);
0134       evsize += sizeof(int) + nts * sizeof(TrackState);
0135     }
0136 
0137     int nl = layerHits_.size();
0138     fwrite(&nl, sizeof(int), 1, fp);
0139     evsize += sizeof(int);
0140     for (int il = 0; il < nl; ++il) {
0141       int nh = layerHits_[il].size();
0142       fwrite(&nh, sizeof(int), 1, fp);
0143       fwrite(&layerHits_[il][0], sizeof(Hit), nh, fp);
0144       evsize += sizeof(int) + nh * sizeof(Hit);
0145     }
0146 
0147     if (data_file.hasHitIterMasks()) {
0148       //sizes are the same as in layerHits_
0149       for (int il = 0; il < nl; ++il) {
0150         int nh = layerHitMasks_[il].size();
0151         assert(nh == (int)layerHits_[il].size());
0152         fwrite(&layerHitMasks_[il][0], sizeof(uint64_t), nh, fp);
0153         evsize += nh * sizeof(uint64_t);
0154       }
0155     }
0156 
0157     int nm = simHitsInfo_.size();
0158     fwrite(&nm, sizeof(int), 1, fp);
0159     fwrite(&simHitsInfo_[0], sizeof(MCHitInfo), nm, fp);
0160     evsize += sizeof(int) + nm * sizeof(MCHitInfo);
0161 
0162     if (data_file.hasSeeds()) {
0163       evsize += write_tracks(fp, seedTracks_);
0164     }
0165 
0166     if (data_file.hasCmsswTracks()) {
0167       evsize += write_tracks(fp, cmsswTracks_);
0168     }
0169 
0170     if (data_file.hasBeamSpot()) {
0171       fwrite(&beamSpot_, sizeof(BeamSpot), 1, fp);
0172       evsize += sizeof(BeamSpot);
0173     }
0174 
0175     fseek(fp, start, SEEK_SET);
0176     fwrite(&evsize, sizeof(int), 1, fp);
0177     fseek(fp, 0, SEEK_END);
0178 
0179     //layerHitMap_ is recreated afterwards
0180 
0181     /*
0182   printf("write %i tracks\n",nt);
0183   for (int it = 0; it<nt; it++) {
0184     printf("track with pT=%5.3f\n",simTracks_[it].pT());
0185     for (int ih=0; ih<simTracks_[it].nTotalHits(); ++ih) {
0186       printf("hit lyr:%2d idx=%i\n", simTracks_[it].getHitLyr(ih), simTracks_[it].getHitIdx(ih));
0187     }
0188   }
0189   printf("write %i layers\n",nl);
0190   for (int il = 0; il<nl; il++) {
0191     printf("write %i hits in layer %i\n",layerHits_[il].size(),il);
0192     for (int ih = 0; ih<layerHits_[il].size(); ih++) {
0193       printf("hit with r=%5.3f x=%5.3f y=%5.3f z=%5.3f\n",layerHits_[il][ih].r(),layerHits_[il][ih].x(),layerHits_[il][ih].y(),layerHits_[il][ih].z());
0194     }
0195   }
0196   */
0197   }
0198 
0199   // #define DUMP_SEEDS
0200   // #define DUMP_SEED_HITS
0201   // #define DUMP_TRACKS
0202   // #define DUMP_TRACK_HITS
0203   // #define DUMP_LAYER_HITS
0204   // #define DUMP_REC_TRACKS
0205   // #define DUMP_REC_TRACK_HITS
0206 
0207   void Event::read_in(DataFile &data_file, FILE *in_fp) {
0208     FILE *fp = in_fp ? in_fp : data_file.f_fp;
0209 
0210     data_file.advancePosToNextEvent(fp);
0211 
0212     int nt = read_tracks(fp, simTracks_);
0213     Config::nTracks = nt;
0214 
0215     if (data_file.hasSimTrackStates()) {
0216       int nts;
0217       fread(&nts, sizeof(int), 1, fp);
0218       simTrackStates_.resize(nts);
0219       fread(&simTrackStates_[0], sizeof(TrackState), nts, fp);
0220     }
0221 
0222     int nl;
0223     fread(&nl, sizeof(int), 1, fp);
0224     layerHits_.resize(nl);
0225     layerHitMasks_.resize(nl);
0226     for (int il = 0; il < nl; ++il) {
0227       int nh;
0228       fread(&nh, sizeof(int), 1, fp);
0229       layerHits_[il].resize(nh);
0230       layerHitMasks_[il].resize(nh, 0);  //init to 0 by default
0231       fread(&layerHits_[il][0], sizeof(Hit), nh, fp);
0232     }
0233 
0234     if (data_file.hasHitIterMasks()) {
0235       for (int il = 0; il < nl; ++il) {
0236         int nh = layerHits_[il].size();
0237         fread(&layerHitMasks_[il][0], sizeof(uint64_t), nh, fp);
0238       }
0239     }
0240 
0241     int nm;
0242     fread(&nm, sizeof(int), 1, fp);
0243     simHitsInfo_.resize(nm);
0244     fread(&simHitsInfo_[0], sizeof(MCHitInfo), nm, fp);
0245 
0246     if (data_file.hasSeeds()) {
0247       int ns = read_tracks(fp, seedTracks_, Config::seedInput != cmsswSeeds);
0248       (void)ns;
0249 
0250 #ifdef DUMP_SEEDS
0251       printf("Read %i seedtracks (neg value means actual reading was skipped)\n", ns);
0252       for (int it = 0; it < ns; it++) {
0253         const Track &ss = seedTracks_[it];
0254         printf("  %-3i q=%+i pT=%7.3f eta=% 7.3f nHits=%i label=%4i algo=%2i\n",
0255                it,
0256                ss.charge(),
0257                ss.pT(),
0258                ss.momEta(),
0259                ss.nFoundHits(),
0260                ss.label(),
0261                (int)ss.algorithm());
0262 #ifdef DUMP_SEED_HITS
0263         for (int ih = 0; ih < seedTracks_[it].nTotalHits(); ++ih) {
0264           int lyr = seedTracks_[it].getHitLyr(ih);
0265           int idx = seedTracks_[it].getHitIdx(ih);
0266           if (idx >= 0) {
0267             const Hit &hit = layerHits_[lyr][idx];
0268             printf("    hit %2d lyr=%3d idx=%4d pos r=%7.3f z=% 8.3f   mc_hit=%3d mc_trk=%3d\n",
0269                    ih,
0270                    lyr,
0271                    idx,
0272                    layerHits_[lyr][idx].r(),
0273                    layerHits_[lyr][idx].z(),
0274                    hit.mcHitID(),
0275                    hit.mcTrackID(simHitsInfo_));
0276           } else
0277             printf("    hit %2d idx=%i\n", ih, seedTracks_[it].getHitIdx(ih));
0278         }
0279 #endif
0280       }
0281 #endif
0282     }
0283 
0284     int nert = -99999;
0285     if (data_file.hasCmsswTracks()) {
0286       nert = read_tracks(fp, cmsswTracks_, !Config::readCmsswTracks);
0287       (void)nert;
0288     }
0289 
0290     /*
0291     // HACK TO ONLY SELECT ONE PROBLEMATIC TRACK.
0292     // Note that MC matching gets screwed.
0293     // Works for MC seeding.
0294     //
0295     printf("************** SIM SELECTION HACK IN FORCE ********************\n");
0296     TrackVec x;
0297     x.push_back(simTracks_[3]);
0298     simTracks_.swap(x);
0299     nt = 1;
0300   */
0301 
0302 #ifdef DUMP_TRACKS
0303     printf("Read %i simtracks\n", nt);
0304     for (int it = 0; it < nt; it++) {
0305       const Track &t = simTracks_[it];
0306       printf("  %-3i q=%+i pT=%7.3f eta=% 7.3f nHits=%2d  label=%4d\n",
0307              it,
0308              t.charge(),
0309              t.pT(),
0310              t.momEta(),
0311              t.nFoundHits(),
0312              t.label());
0313 #ifdef DUMP_TRACK_HITS
0314       for (int ih = 0; ih < t.nTotalHits(); ++ih) {
0315         int lyr = t.getHitLyr(ih);
0316         int idx = t.getHitIdx(ih);
0317         if (idx >= 0) {
0318           const Hit &hit = layerHits_[lyr][idx];
0319           printf("    hit %2d lyr=%2d idx=%3d pos r=%7.3f x=% 8.3f y=% 8.3f z=% 8.3f   mc_hit=%3d mc_trk=%3d\n",
0320                  ih,
0321                  lyr,
0322                  idx,
0323                  layerHits_[lyr][idx].r(),
0324                  layerHits_[lyr][idx].x(),
0325                  layerHits_[lyr][idx].y(),
0326                  layerHits_[lyr][idx].z(),
0327                  hit.mcHitID(),
0328                  hit.mcTrackID(simHitsInfo_));
0329         } else
0330           printf("    hit %2d idx=%i\n", ih, t.getHitIdx(ih));
0331       }
0332 #endif
0333     }
0334 #endif
0335 #ifdef DUMP_LAYER_HITS
0336     // clang-format off
0337     printf("Read %i layers\n", nl);
0338     int total_hits = 0;
0339     float min_delta = 100, max_delta = -100;
0340     for (int il = 0; il < nl; il++) {
0341       if (layerHits_[il].empty())
0342         continue;
0343 
0344       const LayerInfo &linfo = Config::TrkInfo[il];
0345       printf("Read %i hits in layer %i, is_brl=%d is_pix=%d\n",
0346              (int)layerHits_[il].size(), il, linfo.is_barrel(), linfo.is_pixel());
0347       total_hits += layerHits_[il].size();
0348       for (int ih = 0; ih < (int)layerHits_[il].size(); ih++) {
0349         const Hit &hit = layerHits_[il][ih];
0350         unsigned int mid = hit.detIDinLayer();
0351         const ModuleInfo &mi = linfo.module_info(mid);
0352 
0353         if ( ! linfo.is_pixel() && ! linfo.is_barrel()) {
0354           float delta = mi.half_length - std::sqrt(3)*std::sqrt(hit.exx() + hit.eyy());
0355           min_delta = std::min(min_delta, delta);
0356           max_delta = std::max(max_delta, delta);
0357         }
0358         // continue;
0359 
0360         printf("  mcHitID=%-5d r=%7g x=%8g y=%8g z=%8g"
0361                "  sx=%10.4g sy=%10.4e sz=%10.4e sxy=%10.4e, mhl=%10.4e, delta=%10.4e"
0362                "  chg_pcm=%u (%u - %u)\n",
0363                hit.mcHitID(), hit.r(), hit.x(), hit.y(), hit.z(),
0364                std::sqrt(hit.exx()), std::sqrt(hit.eyy()), std::sqrt(hit.ezz()),
0365                std::sqrt(hit.exx() + hit.eyy()),
0366                mi.half_length,
0367                mi.half_length - std::sqrt(3)*std::sqrt(hit.exx() + hit.eyy()),
0368                hit.chargePerCM(), hit.minChargePerCM(), hit.maxChargePerCM());
0369       }
0370     }
0371     printf("Total hits in all layers = %d; endcap strips: min_delta=%.5f  max_delta=%.5f\n",
0372            total_hits, min_delta, max_delta);
0373     // clang-format on
0374 #endif
0375 #ifdef DUMP_REC_TRACKS
0376     printf("Read %i rectracks\n", nert);
0377     for (int it = 0; it < nert; it++) {
0378       const Track &t = cmsswTracks_[it];
0379       printf("  %-3i with q=%+i pT=%7.3f eta=% 7.3f nHits=%2d  label=%4d algo=%2d\n",
0380              it,
0381              t.charge(),
0382              t.pT(),
0383              t.momEta(),
0384              t.nFoundHits(),
0385              t.label(),
0386              (int)t.algorithm());
0387 #ifdef DUMP_REC_TRACK_HITS
0388       for (int ih = 0; ih < t.nTotalHits(); ++ih) {
0389         int lyr = t.getHitLyr(ih);
0390         int idx = t.getHitIdx(ih);
0391         if (idx >= 0) {
0392           const Hit &hit = layerHits_[lyr][idx];
0393           printf("    hit %2d lyr=%2d idx=%3d pos r=%7.3f z=% 8.3f   mc_hit=%3d mc_trk=%3d\n",
0394                  ih,
0395                  lyr,
0396                  idx,
0397                  hit.r(),
0398                  hit.z(),
0399                  hit.mcHitID(),
0400                  hit.mcTrackID(simHitsInfo_));
0401         } else
0402           printf("    hit %2d        idx=%i\n", ih, t.getHitIdx(ih));
0403       }
0404 #endif
0405     }
0406 #endif
0407 
0408     if (data_file.hasBeamSpot()) {
0409       fread(&beamSpot_, sizeof(BeamSpot), 1, fp);
0410     }
0411 
0412     if (Config::kludgeCmsHitErrors) {
0413       kludge_cms_hit_errors();
0414     }
0415 
0416     if (!Config::silent)
0417       printf("Read complete, %d simtracks on file.\n", nt);
0418   }
0419 
0420   //------------------------------------------------------------------------------
0421 
0422   int Event::write_tracks(FILE *fp, const TrackVec &tracks) {
0423     // Returns total number of bytes written.
0424 
0425     int n_tracks = tracks.size();
0426     fwrite(&n_tracks, sizeof(int), 1, fp);
0427 
0428     auto start = ftell(fp);
0429     int data_size = 2 * sizeof(int) + n_tracks * sizeof(Track);
0430     fwrite(&data_size, sizeof(int), 1, fp);
0431 
0432     fwrite(tracks.data(), sizeof(Track), n_tracks, fp);
0433 
0434     for (int i = 0; i < n_tracks; ++i) {
0435       fwrite(tracks[i].beginHitsOnTrack(), sizeof(HitOnTrack), tracks[i].nTotalHits(), fp);
0436       data_size += tracks[i].nTotalHits() * sizeof(HitOnTrack);
0437     }
0438 
0439     fseek(fp, start, SEEK_SET);
0440     fwrite(&data_size, sizeof(int), 1, fp);
0441     fseek(fp, 0, SEEK_END);
0442 
0443     return data_size;
0444   }
0445 
0446   int Event::read_tracks(FILE *fp, TrackVec &tracks, bool skip_reading) {
0447     // Returns number of read tracks (negative if actual reading was skipped).
0448 
0449     int n_tracks, data_size;
0450     fread(&n_tracks, sizeof(int), 1, fp);
0451     fread(&data_size, sizeof(int), 1, fp);
0452 
0453     if (skip_reading) {
0454       fseek(fp, data_size - 2 * sizeof(int), SEEK_CUR);  // -2 because data_size counts itself and n_tracks too
0455       n_tracks = -n_tracks;
0456     } else {
0457       tracks.resize(n_tracks);
0458 
0459       fread(tracks.data(), sizeof(Track), n_tracks, fp);
0460 
0461       for (int i = 0; i < n_tracks; ++i) {
0462         tracks[i].resizeHitsForInput();
0463         fread(tracks[i].beginHitsOnTrack_nc(), sizeof(HitOnTrack), tracks[i].nTotalHits(), fp);
0464       }
0465     }
0466 
0467     return n_tracks;
0468   }
0469 
0470   //------------------------------------------------------------------------------
0471 
0472   void Event::setInputFromCMSSW(std::vector<HitVec> hits, TrackVec seeds) {
0473     layerHits_ = std::move(hits);
0474     seedTracks_ = std::move(seeds);
0475   }
0476 
0477   //------------------------------------------------------------------------------
0478 
0479   void Event::kludge_cms_hit_errors() {
0480     // Enforce Vxy on all layers, Vz on pixb only.
0481 
0482     const float Exy = 15 * 1e-4, Vxy = Exy * Exy;
0483     const float Ez = 30 * 1e-4, Vz = Ez * Ez;
0484 
0485     int nl = layerHits_.size();
0486 
0487     int cnt = 0;
0488 
0489     for (int il = 0; il < nl; il++) {
0490       if (layerHits_[il].empty())
0491         continue;
0492 
0493       for (Hit &h : layerHits_[il]) {
0494         SVector6 &c = h.error_nc();
0495 
0496         float vxy = c[0] + c[2];
0497         if (vxy < Vxy) {
0498           c[0] *= Vxy / vxy;
0499           c[2] *= Vxy / vxy;
0500           ++cnt;
0501         }
0502         if (il < 4 && c[5] < Vz) {
0503           c[5] = Vz;
0504           ++cnt;
0505         }
0506       }
0507     }
0508 
0509     printf("Event::kludge_cms_hit_errors processed %d layers, kludged %d entries.\n", nl, cnt);
0510   }
0511 
0512   //------------------------------------------------------------------------------
0513 
0514   int Event::clean_cms_simtracks() {
0515     // Sim tracks from cmssw have the following issues:
0516     // - hits are not sorted by layer;
0517     // - there are tracks with too low number of hits, even 0;
0518     // - even with enough hits, there can be too few layers (esp. in endcap);
0519     // - tracks from secondaries can have extremely low pT.
0520     // Possible further checks:
0521     // - make sure enough hits exist in seeding layers.
0522     //
0523     // What is done:
0524     // 1. Hits are sorted by layer;
0525     // 2. Non-findable tracks are marked with Track::Status::not_findable flag.
0526     //
0527     // Returns number of passed simtracks.
0528 
0529     dprintf("Event::clean_cms_simtracks processing %lu simtracks.\n", simTracks_.size());
0530 
0531     int n_acc = 0;
0532     int i = -1;  //wrap in ifdef DEBUG?
0533     for (Track &t : simTracks_) {
0534       i++;
0535 
0536       t.sortHitsByLayer();
0537 
0538       const int lyr_cnt = t.nUniqueLayers();
0539 
0540       //const int lasthit = t.getLastFoundHitPos();
0541       //const float eta = layerHits_[t.getHitLyr(lasthit)][t.getHitIdx(lasthit)].eta();
0542 
0543       if (lyr_cnt < Config::cmsSelMinLayers)  // || Config::TrkInfo.is_transition(eta))
0544       {
0545         dprintf("Rejecting simtrack %d, n_hits=%d, n_layers=%d, pT=%f\n", i, t.nFoundHits(), lyr_cnt, t.pT());
0546         t.setNotFindable();
0547       } else {
0548         dprintf("Accepting simtrack %d, n_hits=%d, n_layers=%d, pT=%f\n", i, t.nFoundHits(), lyr_cnt, t.pT());
0549         ++n_acc;
0550       }
0551     }
0552 
0553     return n_acc;
0554   }
0555 
0556   void Event::print_tracks(const TrackVec &tracks, bool print_hits) const {
0557     const int nt = tracks.size();
0558     auto score_func = IterationConfig::get_track_scorer("default");
0559     //WARNING: Printouts for hits will not make any sense if mkFit is not run with a validation flag such as --quality-val
0560     printf("Event::print_tracks printing %d tracks %s hits:\n", nt, (print_hits ? "with" : "without"));
0561     for (int it = 0; it < nt; it++) {
0562       const Track &t = tracks[it];
0563       printf("  %i with q=%+i pT=%7.3f eta=% 7.3f nHits=%2d  label=%4d findable=%d score=%7.3f chi2=%7.3f\n",
0564              it,
0565              t.charge(),
0566              t.pT(),
0567              t.momEta(),
0568              t.nFoundHits(),
0569              t.label(),
0570              t.isFindable(),
0571              getScoreCand(score_func, t),
0572              t.chi2());
0573 
0574       if (print_hits) {
0575         for (int ih = 0; ih < t.nTotalHits(); ++ih) {
0576           int lyr = t.getHitLyr(ih);
0577           int idx = t.getHitIdx(ih);
0578           if (idx >= 0) {
0579             const Hit &hit = layerHits_[lyr][idx];
0580             printf("    hit %2d lyr=%2d idx=%3d pos r=%7.3f z=% 8.3f   mc_hit=%3d mc_trk=%3d\n",
0581                    ih,
0582                    lyr,
0583                    idx,
0584                    layerHits_[lyr][idx].r(),
0585                    layerHits_[lyr][idx].z(),
0586                    hit.mcHitID(),
0587                    hit.mcTrackID(simHitsInfo_));
0588           } else
0589             printf("    hit %2d lyr=%2d idx=%3d\n", ih, t.getHitLyr(ih), t.getHitIdx(ih));
0590         }
0591       }
0592     }
0593   }
0594 
0595   int Event::clean_cms_seedtracks(TrackVec *seed_ptr) {
0596     const float etamax_brl = Config::c_etamax_brl;
0597     const float dpt_common = Config::c_dpt_common;
0598     const float dzmax_brl = Config::c_dzmax_brl;
0599     const float drmax_brl = Config::c_drmax_brl;
0600     const float ptmin_hpt = Config::c_ptmin_hpt;
0601     const float dzmax_hpt = Config::c_dzmax_hpt;
0602     const float drmax_hpt = Config::c_drmax_hpt;
0603     const float dzmax_els = Config::c_dzmax_els;
0604     const float drmax_els = Config::c_drmax_els;
0605 
0606     const float dzmax2_inv_brl = 1.f / (dzmax_brl * dzmax_brl);
0607     const float drmax2_inv_brl = 1.f / (drmax_brl * drmax_brl);
0608     const float dzmax2_inv_hpt = 1.f / (dzmax_hpt * dzmax_hpt);
0609     const float drmax2_inv_hpt = 1.f / (drmax_hpt * drmax_hpt);
0610     const float dzmax2_inv_els = 1.f / (dzmax_els * dzmax_els);
0611     const float drmax2_inv_els = 1.f / (drmax_els * drmax_els);
0612 
0613     TrackVec &seeds = (seed_ptr != nullptr) ? *seed_ptr : seedTracks_;
0614     const int ns = seeds.size();
0615 
0616     TrackVec cleanSeedTracks;
0617     cleanSeedTracks.reserve(ns);
0618     std::vector<bool> writetrack(ns, true);
0619 
0620     const float invR1GeV = 1.f / Config::track1GeVradius;
0621 
0622     std::vector<int> nHits(ns);
0623     std::vector<int> charge(ns);
0624     std::vector<float> oldPhi(ns);
0625     std::vector<float> pos2(ns);
0626     std::vector<float> eta(ns);
0627     std::vector<float> ctheta(ns);
0628     std::vector<float> invptq(ns);
0629     std::vector<float> pt(ns);
0630     std::vector<float> x(ns);
0631     std::vector<float> y(ns);
0632     std::vector<float> z(ns);
0633 
0634     for (int ts = 0; ts < ns; ts++) {
0635       const Track &tk = seeds[ts];
0636       nHits[ts] = tk.nFoundHits();
0637       charge[ts] = tk.charge();
0638       oldPhi[ts] = tk.momPhi();
0639       pos2[ts] = std::pow(tk.x(), 2) + std::pow(tk.y(), 2);
0640       eta[ts] = tk.momEta();
0641       ctheta[ts] = 1.f / std::tan(tk.theta());
0642       invptq[ts] = tk.charge() * tk.invpT();
0643       pt[ts] = tk.pT();
0644       x[ts] = tk.x();
0645       y[ts] = tk.y();
0646       z[ts] = tk.z();
0647     }
0648 
0649     for (int ts = 0; ts < ns; ts++) {
0650       if (not writetrack[ts])
0651         continue;  //FIXME: this speed up prevents transitive masking; check build cost!
0652 
0653       const float oldPhi1 = oldPhi[ts];
0654       const float pos2_first = pos2[ts];
0655       const float Eta1 = eta[ts];
0656       const float Pt1 = pt[ts];
0657       const float invptq_first = invptq[ts];
0658 
0659       //#pragma simd /* Vectorization via simd had issues with icc */
0660       for (int tss = ts + 1; tss < ns; tss++) {
0661         const float Pt2 = pt[tss];
0662 
0663         ////// Always require charge consistency. If different charge is assigned, do not remove seed-track
0664         if (charge[tss] != charge[ts])
0665           continue;
0666 
0667         const float thisDPt = std::abs(Pt2 - Pt1);
0668         ////// Require pT consistency between seeds. If dpT is large, do not remove seed-track.
0669         if (thisDPt > dpt_common * (Pt1))
0670           continue;
0671 
0672         const float Eta2 = eta[tss];
0673         const float deta2 = std::pow(Eta1 - Eta2, 2);
0674 
0675         const float oldPhi2 = oldPhi[tss];
0676 
0677         const float pos2_second = pos2[tss];
0678         const float thisDXYSign05 = pos2_second > pos2_first ? -0.5f : 0.5f;
0679 
0680         const float thisDXY = thisDXYSign05 * sqrt(std::pow(x[ts] - x[tss], 2) + std::pow(y[ts] - y[tss], 2));
0681 
0682         const float invptq_second = invptq[tss];
0683 
0684         const float newPhi1 = oldPhi1 - thisDXY * invR1GeV * invptq_first;
0685         const float newPhi2 = oldPhi2 + thisDXY * invR1GeV * invptq_second;
0686 
0687         const float dphi = cdist(std::abs(newPhi1 - newPhi2));
0688 
0689         const float dr2 = deta2 + dphi * dphi;
0690 
0691         const float thisDZ = z[ts] - z[tss] - thisDXY * (ctheta[ts] + ctheta[tss]);
0692         const float dz2 = thisDZ * thisDZ;
0693 
0694         ////// Reject tracks within dR-dz elliptical window.
0695         ////// Adaptive thresholds, based on observation that duplicates are more abundant at large pseudo-rapidity and low track pT
0696         if (std::abs(Eta1) < etamax_brl) {
0697           if (dz2 * dzmax2_inv_brl + dr2 * drmax2_inv_brl < 1.0f)
0698             writetrack[tss] = false;
0699         } else if (Pt1 > ptmin_hpt) {
0700           if (dz2 * dzmax2_inv_hpt + dr2 * drmax2_inv_hpt < 1.0f)
0701             writetrack[tss] = false;
0702         } else {
0703           if (dz2 * dzmax2_inv_els + dr2 * drmax2_inv_els < 1.0f)
0704             writetrack[tss] = false;
0705         }
0706       }
0707 
0708       if (writetrack[ts])
0709         cleanSeedTracks.emplace_back(seeds[ts]);
0710     }
0711 
0712     seeds.swap(cleanSeedTracks);
0713 
0714 #ifdef DEBUG
0715     {
0716       const int ns2 = seeds.size();
0717       printf("Number of CMS seeds before %d --> after %d cleaning\n", ns, ns2);
0718 
0719       for (int it = 0; it < ns2; it++) {
0720         const Track &ss = seeds[it];
0721         printf("  %3i q=%+i pT=%7.3f eta=% 7.3f nHits=%i label=% i\n",
0722                it,
0723                ss.charge(),
0724                ss.pT(),
0725                ss.momEta(),
0726                ss.nFoundHits(),
0727                ss.label());
0728       }
0729     }
0730 #endif
0731 
0732     return seeds.size();
0733   }
0734 
0735   int Event::select_tracks_iter(unsigned int n) {
0736     if (n == 0)
0737       return 1;
0738 
0739     unsigned int algorithms[] = {4, 22, 23, 5, 24, 7, 8, 9, 10, 6};  //to be stored somewhere common
0740 
0741     //saving seeds by algorithm
0742     const int ns = seedTracks_.size();
0743 
0744     TrackVec cleanSeedTracks;
0745     cleanSeedTracks.reserve(ns);
0746 
0747     for (int ts = 0; ts < ns; ts++) {
0748       const Track &tk = seedTracks_[ts];
0749       unsigned int algo = (unsigned int)tk.algorithm();
0750       if (std::find(algorithms, algorithms + n, algo) != algorithms + n)
0751         cleanSeedTracks.emplace_back(seedTracks_[ts]);
0752     }
0753     seedTracks_.swap(cleanSeedTracks);
0754 
0755     //saving tracks by algorithm
0756     const int nt = cmsswTracks_.size();
0757 
0758     TrackVec cleanTracks;
0759     cleanTracks.reserve(nt);
0760 
0761     for (int ts = 0; ts < nt; ts++) {
0762       const Track &tk = cmsswTracks_[ts];
0763       unsigned int algo = (unsigned int)tk.algorithm();
0764       if (std::find(algorithms, algorithms + n, algo) != algorithms + n)
0765         cleanTracks.emplace_back(cmsswTracks_[ts]);
0766     }
0767     cmsswTracks_.swap(cleanTracks);
0768     return cmsswTracks_.size() + seedTracks_.size();
0769   }
0770 
0771   int Event::clean_cms_seedtracks_badlabel() {
0772     printf("***\n*** REMOVING SEEDS WITH BAD LABEL. This is a development hack. ***\n***\n");
0773     TrackVec buf;
0774     seedTracks_.swap(buf);
0775     std::copy_if(
0776         buf.begin(), buf.end(), std::back_inserter(seedTracks_), [](const Track &t) { return t.label() >= 0; });
0777     return seedTracks_.size();
0778   }
0779 
0780   int Event::use_seeds_from_cmsswtracks() {
0781     int ns = seedTracks_.size();
0782 
0783     TrackVec cleanSeedTracks;
0784     cleanSeedTracks.reserve(ns);
0785 
0786     for (auto &&cmsswtrack : cmsswTracks_) {
0787       cleanSeedTracks.emplace_back(seedTracks_[cmsswtrack.label()]);
0788     }
0789 
0790     seedTracks_.swap(cleanSeedTracks);
0791 
0792     return seedTracks_.size();
0793   }
0794 
0795   void Event::relabel_bad_seedtracks() {
0796     int newlabel = 0;
0797     for (auto &&track : seedTracks_) {
0798       if (track.label() < 0)
0799         track.setLabel(--newlabel);
0800     }
0801   }
0802 
0803   void Event::relabel_cmsswtracks_from_seeds() {
0804     std::map<int, int> cmsswLabelMap;
0805     for (size_t iseed = 0; iseed < seedTracks_.size(); iseed++) {
0806       for (size_t icmssw = 0; icmssw < cmsswTracks_.size(); icmssw++) {
0807         if (cmsswTracks_[icmssw].label() == static_cast<int>(iseed)) {
0808           cmsswLabelMap[icmssw] = seedTracks_[iseed].label();
0809           break;
0810         }
0811       }
0812     }
0813     for (size_t icmssw = 0; icmssw < cmsswTracks_.size(); icmssw++) {
0814       cmsswTracks_[icmssw].setLabel(cmsswLabelMap[icmssw]);
0815     }
0816   }
0817 
0818   //==============================================================================
0819   // HitMask handling
0820   //==============================================================================
0821 
0822   void Event::fill_hitmask_bool_vectors(int track_algo, std::vector<std::vector<bool>> &layer_masks) {
0823     // Convert from per-hit uint64_t to per layer bool-vectors for given
0824     // iteration.
0825 
0826     uint64_t iter_mask = 1 << track_algo;
0827 
0828     const int n_lay = (int)layerHits_.size();
0829     layer_masks.resize(n_lay);
0830 
0831     for (int l = 0; l < n_lay; ++l) {
0832       const int n_hit = (int)layerHits_[l].size();
0833       layer_masks[l].resize(n_hit);
0834 
0835       for (int i = 0; i < n_hit; ++i) {
0836         layer_masks[l][i] = layerHitMasks_[l][i] & iter_mask;
0837       }
0838     }
0839   }
0840 
0841   void Event::fill_hitmask_bool_vectors(std::vector<int> &track_algo_vec, std::vector<std::vector<bool>> &layer_masks) {
0842     // Convert from per-hit uint64_t to per layer bool-vectors for a list of
0843     // iterations.
0844     // A hit mask is set if it is set for _all_ listed iterations.
0845 
0846     uint64_t iter_mask = 0;
0847     for (auto ta : track_algo_vec)
0848       iter_mask |= 1 << ta;
0849 
0850     const int n_lay = (int)layerHits_.size();
0851     layer_masks.resize(n_lay);
0852 
0853     for (int l = 0; l < n_lay; ++l) {
0854       const int n_hit = (int)layerHits_[l].size();
0855       layer_masks[l].resize(n_hit);
0856 
0857       for (int i = 0; i < n_hit; ++i) {
0858         uint64_t hitmasks = layerHitMasks_[l][i];
0859         layer_masks[l][i] = ((iter_mask ^ hitmasks) & iter_mask) == 0;
0860       }
0861     }
0862   }
0863 
0864   //==============================================================================
0865   // Handling of current seed vectors and MC label reconstruction from hit data
0866   //==============================================================================
0867 
0868   void Event::setCurrentSeedTracks(const TrackVec &seeds) {
0869     currentSeedTracks_ = &seeds;
0870     currentSeedSimFromHits_.clear();
0871   }
0872 
0873   const Track &Event::currentSeed(int i) const { return (*currentSeedTracks_)[i]; }
0874 
0875   Event::SimLabelFromHits Event::simLabelForCurrentSeed(int i) const {
0876     assert(currentSeedTracks_ != nullptr);
0877 
0878     if (currentSeedSimFromHits_.empty()) {
0879       currentSeedSimFromHits_.resize(currentSeedTracks_->size());
0880 
0881       for (int si = 0; si < (int)currentSeedTracks_->size(); ++si) {
0882         const Track &s = currentSeed(si);
0883         // printf("%3d (%d): [", si, s.label());
0884         std::map<int, int> lab_cnt;
0885         for (int hi = 0; hi < s.nTotalHits(); ++hi) {
0886           auto hot = s.getHitOnTrack(hi);
0887           // printf(" %d", hot.index);
0888           if (hot.index < 0)
0889             continue;
0890           const Hit &h = layerHits_[hot.layer][hot.index];
0891           int hl = simHitsInfo_[h.mcHitID()].mcTrackID_;
0892           // printf(" (%d)", hl);
0893           if (hl >= 0)
0894             ++lab_cnt[hl];
0895         }
0896         int max_c = -1, max_l = -1;
0897         for (auto &x : lab_cnt) {
0898           if (x.second > max_c) {
0899             max_l = x.first;
0900             max_c = x.second;
0901           } else if (x.second == max_c) {
0902             max_l = -1;
0903           }
0904         }
0905         if (max_c < 0) {
0906           max_c = 0;
0907           max_l = -1;
0908         }
0909         // printf(" ] -> %d %d => %d\n", s.nTotalHits(), max_c, max_l);
0910         currentSeedSimFromHits_[si] = {s.nTotalHits(), max_c, max_l};
0911       }
0912     }
0913 
0914     return currentSeedSimFromHits_[i];
0915   }
0916 
0917   void Event::resetCurrentSeedTracks() {
0918     currentSeedTracks_ = nullptr;
0919     currentSeedSimFromHits_.clear();
0920   }
0921 
0922   //==============================================================================
0923   // DataFile
0924   //==============================================================================
0925 
0926   int DataFile::openRead(const std::string &fname, int expected_n_layers) {
0927     constexpr int min_ver = 7;
0928     constexpr int max_ver = 7;
0929 
0930     f_fp = fopen(fname.c_str(), "r");
0931     assert(f_fp != 0 && "Opening of input file failed.");
0932 
0933     fread(&f_header, sizeof(DataFileHeader), 1, f_fp);
0934 
0935     if (f_header.f_magic != 0xBEEF) {
0936       fprintf(stderr, "Incompatible input file (wrong magick).\n");
0937       exit(1);
0938     }
0939     if (f_header.f_format_version < min_ver || f_header.f_format_version > max_ver) {
0940       fprintf(stderr,
0941               "Unsupported file version %d. Supported versions are from %d to %d.\n",
0942               f_header.f_format_version,
0943               min_ver,
0944               max_ver);
0945       exit(1);
0946     }
0947     if (f_header.f_sizeof_track != sizeof(Track)) {
0948       fprintf(stderr,
0949               "sizeof(Track) on file (%d) different from current value (%d).\n",
0950               f_header.f_sizeof_track,
0951               (int)sizeof(Track));
0952       exit(1);
0953     }
0954     if (f_header.f_sizeof_hit != sizeof(Hit)) {
0955       fprintf(stderr,
0956               "sizeof(Hit) on file (%d) different from current value (%d).\n",
0957               f_header.f_sizeof_hit,
0958               (int)sizeof(Hit));
0959       exit(1);
0960     }
0961     if (f_header.f_sizeof_hot != sizeof(HitOnTrack)) {
0962       fprintf(stderr,
0963               "sizeof(HitOnTrack) on file (%d) different from current value (%d).\n",
0964               f_header.f_sizeof_hot,
0965               (int)sizeof(HitOnTrack));
0966       exit(1);
0967     }
0968     if (f_header.f_n_layers != expected_n_layers) {
0969       fprintf(stderr,
0970               "Number of layers on file (%d) is different from current TrackerInfo (%d).\n",
0971               f_header.f_n_layers,
0972               expected_n_layers);
0973       exit(1);
0974     }
0975 
0976     printf("Opened file '%s', format version %d, n_layers %d, n_events %d\n",
0977            fname.c_str(),
0978            f_header.f_format_version,
0979            f_header.f_n_layers,
0980            f_header.f_n_events);
0981     if (f_header.f_extra_sections) {
0982       printf("  Extra sections:");
0983       if (f_header.f_extra_sections & ES_SimTrackStates)
0984         printf(" SimTrackStates");
0985       if (f_header.f_extra_sections & ES_Seeds)
0986         printf(" Seeds");
0987       if (f_header.f_extra_sections & ES_CmsswTracks)
0988         printf(" CmsswTracks");
0989       printf("\n");
0990     }
0991 
0992     if (Config::seedInput == cmsswSeeds && !hasSeeds()) {
0993       fprintf(stderr, "Reading of CmsswSeeds requested but data not available on file.\n");
0994       exit(1);
0995     }
0996 
0997     if (Config::readCmsswTracks && !hasCmsswTracks()) {
0998       fprintf(stderr, "Reading of CmsswTracks requested but data not available on file.\n");
0999       exit(1);
1000     }
1001 
1002     return f_header.f_n_events;
1003   }
1004 
1005   void DataFile::openWrite(const std::string &fname, int n_layers, int n_ev, int extra_sections) {
1006     f_fp = fopen(fname.c_str(), "w");
1007     f_header.f_n_layers = n_layers;
1008     f_header.f_n_events = n_ev;
1009     f_header.f_extra_sections = extra_sections;
1010 
1011     fwrite(&f_header, sizeof(DataFileHeader), 1, f_fp);
1012   }
1013 
1014   void DataFile::rewind() {
1015     std::lock_guard<std::mutex> readlock(f_next_ev_mutex);
1016     f_pos = sizeof(DataFileHeader);
1017     fseek(f_fp, f_pos, SEEK_SET);
1018   }
1019 
1020   int DataFile::advancePosToNextEvent(FILE *fp) {
1021     int evsize;
1022 
1023     std::lock_guard<std::mutex> readlock(f_next_ev_mutex);
1024 
1025     fseek(fp, f_pos, SEEK_SET);
1026     fread(&evsize, sizeof(int), 1, fp);
1027     if (Config::loopOverFile) {
1028       // File ended, rewind back to beginning
1029       if (feof(fp) != 0) {
1030         f_pos = sizeof(DataFileHeader);
1031         fseek(fp, f_pos, SEEK_SET);
1032         fread(&evsize, sizeof(int), 1, fp);
1033       }
1034     }
1035 
1036     f_pos += evsize;
1037 
1038     return evsize;
1039   }
1040 
1041   void DataFile::skipNEvents(int n_to_skip) {
1042     int evsize;
1043 
1044     std::lock_guard<std::mutex> readlock(f_next_ev_mutex);
1045 
1046     while (n_to_skip-- > 0) {
1047       fseek(f_fp, f_pos, SEEK_SET);
1048       fread(&evsize, sizeof(int), 1, f_fp);
1049       f_pos += evsize;
1050     }
1051   }
1052 
1053   void DataFile::close() {
1054     fclose(f_fp);
1055     f_fp = 0;
1056     f_header = DataFileHeader();
1057   }
1058 
1059   void DataFile::CloseWrite(int n_written) {
1060     if (f_header.f_n_events != n_written) {
1061       fseek(f_fp, 0, SEEK_SET);
1062       f_header.f_n_events = n_written;
1063       fwrite(&f_header, sizeof(DataFileHeader), 1, f_fp);
1064     }
1065     close();
1066   }
1067 
1068   //==============================================================================
1069   // Misc debug / printout
1070   //==============================================================================
1071 
1072   void print(std::string pfx, int itrack, const Track &trk, const Event &ev) {
1073     std::cout << std::endl
1074               << pfx << ": " << itrack << " hits: " << trk.nFoundHits() << " label: " << trk.label()
1075               << " State:" << std::endl;
1076     print(trk.state());
1077 
1078     for (int i = 0; i < trk.nTotalHits(); ++i) {
1079       auto hot = trk.getHitOnTrack(i);
1080       printf("  %2d: lyr %2d idx %5d", i, hot.layer, hot.index);
1081       if (hot.index >= 0) {
1082         auto &h = ev.layerHits_[hot.layer][hot.index];
1083         int hl = ev.simHitsInfo_[h.mcHitID()].mcTrackID_;
1084         printf("  %4d  %8.3f %8.3f %8.3f  r=%.3f\n", hl, h.x(), h.y(), h.z(), h.r());
1085       } else {
1086         printf("\n");
1087       }
1088     }
1089   }
1090 
1091 }  // end namespace mkfit