106 :
p_eff1_vs_x_N(new TProfile(
"",
";x_{N} (mm);efficiency", 50, 0., 25.)),
107 p_eff1_vs_xi_N(new TProfile(
"",
";#xi_{si,N};efficiency", 50, 0., 0.25)),
109 p_eff2_vs_x_N(new TProfile(
"",
";x_{N} (mm);efficiency", 50, 0., 25.)),
110 p_eff2_vs_xi_N(new TProfile(
"",
";#xi_{si,N};efficiency", 50, 0., 0.25)),
139 std::map<unsigned int, std::map<unsigned int, EffPlots>>
effPlots;
144 h_de_x(new TH1D(
"",
";x_{F} - x_{N} (mm)", 200, -1., +1.)),
145 h_de_y(new TH1D(
"",
";y_{F} - y_{N} (mm)", 200, -1., +1.)),
146 h2_de_y_vs_de_x(new TH2D(
"",
";x_{F} - x_{N} (mm);y_{F} - y_{N} (mm)", 100, -1., +1., 100, -1., +1.)),
153 for (
unsigned int nsi = 0; nsi <
n_sigmas.size(); ++nsi) {
167 sprintf(
buf,
"g_de_y_vs_de_x_n_si=%.1f", n_si);
168 TGraph *
g =
new TGraph();
180 TDirectory *d_top = gDirectory;
182 for (
const auto &nep_p :
effPlots) {
183 if (nep_p.first == 0)
184 sprintf(
buf,
"exp prot all");
186 sprintf(
buf,
"exp prot %u", nep_p.first);
188 TDirectory *d_nep = d_top->mkdir(
buf);
190 for (
const auto &nsi_p : nep_p.second) {
193 TDirectory *d_nsi = d_nep->mkdir(
buf);
197 nsi_p.second.write();
207 for (
const auto &
p : ofc) {
218 edm::LogError(
"ArmData::UpdateOptics") <<
"Cannot find optical functions for RP " <<
rpId_N;
222 std::vector<double> xiValues =
225 s_x_to_xi_N = std::make_shared<TSpline3>(
"", xDValues.data(), xiValues.data(), xiValues.size());
229 std::map<unsigned int, ArmData>
data_;
245 tokenRecoProtonsMultiRP_(
251 useNewLHCInfo_(iConfig.getParameter<
bool>(
"useNewLHCInfo")),
254 ppsAssociationCutsToken_(
257 pixelDiscardBXShiftedTracks_(iConfig.getParameter<
bool>(
"pixelDiscardBXShiftedTracks")),
259 localAngleXMin_(iConfig.getParameter<double>(
"localAngleXMin")),
260 localAngleXMax_(iConfig.getParameter<double>(
"localAngleXMax")),
261 localAngleYMin_(iConfig.getParameter<double>(
"localAngleYMin")),
262 localAngleYMax_(iConfig.getParameter<double>(
"localAngleYMax")),
264 n_prep_events_(iConfig.getParameter<unsigned
int>(
"n_prep_events")),
265 n_exp_prot_max_(iConfig.getParameter<unsigned
int>(
"n_exp_prot_max")),
266 n_sigmas_(iConfig.getParameter<
std::
vector<double>>(
"n_sigmas")),
268 outputFile_(iConfig.getParameter<
string>(
"outputFile")),
270 verbosity_(iConfig.getUntrackedParameter<unsigned
int>(
"verbosity")),
272 ff_(new TF1(
"ff",
"[0] * exp(- (x-[1])*(x-[1]) / 2 / [2]/[2]) + [4]")) {
292 desc.add<
std::string>(
"lhcInfoLabel",
"")->setComment(
"label of the LHCInfo record");
293 desc.add<
std::string>(
"lhcInfoPerLSLabel",
"")->setComment(
"label of the LHCInfoPerLS record");
294 desc.add<
std::string>(
"lhcInfoPerFillLabel",
"")->setComment(
"label of the LHCInfoPerFill record");
295 desc.add<
bool>(
"useNewLHCInfo",
false)->setComment(
"flag whether to use new LHCInfoPer* records or old LHCInfo");
296 desc.add<
string>(
"opticsLabel",
"")->setComment(
"label of optics data");
297 desc.add<
string>(
"ppsAssociationCutsLabel",
"")->setComment(
"label of PPSAssociationCuts data");
299 desc.add<
bool>(
"pixelDiscardBXShiftedTracks",
false)
300 ->setComment(
"whether to discard pixel tracks built from BX-shifted planes");
302 desc.add<
double>(
"localAngleXMin", -0.03)->setComment(
"minimal accepted value of local horizontal angle (rad)");
303 desc.add<
double>(
"localAngleXMax", +0.03)->setComment(
"maximal accepted value of local horizontal angle (rad)");
304 desc.add<
double>(
"localAngleYMin", -0.04)->setComment(
"minimal accepted value of local vertical angle (rad)");
305 desc.add<
double>(
"localAngleYMax", +0.04)->setComment(
"maximal accepted value of local vertical angle (rad)");
307 desc.add<
unsigned int>(
"n_prep_events", 1000)
308 ->setComment(
"number of preparatory events (to determine de x and de y window)");
310 desc.add<
unsigned int>(
"n_exp_prot_max", 5)->setComment(
"maximum number of expected protons per event and per arm");
312 desc.add<std::vector<double>>(
"n_sigmas", {3., 5., 7.})->setComment(
"list of n_sigma values");
314 desc.add<
unsigned int>(
"rpId_45_N", 0)->setComment(
"decimal RP id for 45 near");
315 desc.add<
unsigned int>(
"rpId_45_F", 0)->setComment(
"decimal RP id for 45 far");
316 desc.add<
unsigned int>(
"rpId_56_N", 0)->setComment(
"decimal RP id for 56 near");
317 desc.add<
unsigned int>(
"rpId_56_F", 0)->setComment(
"decimal RP id for 56 far");
319 desc.add<
std::string>(
"outputFile",
"output.root")->setComment(
"output file name");
321 desc.addUntracked<
unsigned int>(
"verbosity", 0)->setComment(
"verbosity level");
323 descriptions.
add(
"ctppsProtonReconstructionEfficiencyEstimatorDataDefault",
desc);
330 std::ostringstream os;
352 std::vector<unsigned int> sel_track_idc;
354 std::map<unsigned int, std::vector<unsigned int>> trackingSelection;
356 for (
unsigned int idx = 0;
idx < hTracks->size(); ++
idx) {
357 const auto &tr = hTracks->at(
idx);
369 sel_track_idc.push_back(
idx);
373 const bool trackerRP =
377 trackingSelection[rpId.arm()].push_back(
idx);
382 os <<
"* tracks (pre-selected):" << std::endl;
384 for (
const auto idx : sel_track_idc) {
385 const auto &tr = hTracks->at(
idx);
387 unsigned int decRPId = rpId.arm() * 100 + rpId.station() * 10 + rpId.rp();
389 os <<
" [" <<
idx <<
"] RP=" <<
decRPId <<
", x=" << tr.x() <<
", y=" << tr.y() << std::endl;
392 os <<
"* protons:" << std::endl;
393 for (
unsigned int i = 0;
i < hRecoProtonsMultiRP->size(); ++
i) {
394 const auto &
pr = (*hRecoProtonsMultiRP)[
i];
395 os <<
" [" <<
i <<
"] track indices: ";
396 for (
const auto &trr :
pr.contributingLocalTracks())
397 os << trr.key() <<
", ";
403 map<unsigned int, bool> hasTracksInArm;
405 for (
const auto idx_i : sel_track_idc) {
406 const auto &tr_i = hTracks->at(idx_i);
408 unsigned int decRPId_i = rpId_i.
arm() * 100 + rpId_i.station() * 10 + rpId_i.rp();
410 for (
const auto idx_j : sel_track_idc) {
411 const auto &tr_j = hTracks->at(idx_j);
413 unsigned int decRPId_j = rpId_j.
arm() * 100 + rpId_j.station() * 10 + rpId_j.rp();
416 unsigned int arm = 123;
417 for (
const auto &ap :
data_) {
418 if (ap.second.rpId_N == decRPId_i && ap.second.rpId_F == decRPId_j)
426 hasTracksInArm[
arm] =
true;
430 const double de_x = tr_j.x() - tr_i.x();
431 const double de_y = tr_j.y() - tr_i.y();
434 ad.h_de_x->Fill(
de_x);
435 ad.h_de_y->Fill(
de_y);
438 ad.h2_de_y_vs_de_x->Fill(
de_x,
de_y);
443 for (
auto &ap :
data_) {
444 if (hasTracksInArm[ap.first])
445 ap.second.n_events_with_tracks++;
449 for (
auto &ap :
data_) {
450 auto &ad = ap.second;
453 if (ad.de_x_sigma > 0. && ad.de_y_sigma > 0.)
456 std::vector<std::pair<unsigned int, TH1D *>>
m;
457 m.emplace_back(0, ad.h_de_x.get());
458 m.emplace_back(1, ad.h_de_y.get());
460 for (
const auto &
p :
m) {
461 double max_pos = -1E100, max_val = -1.;
462 for (
int bi = 1; bi <
p.second->GetNbinsX(); ++bi) {
463 const double pos =
p.second->GetBinCenter(bi);
464 const double val =
p.second->GetBinContent(bi);
472 const double sig = 0.2;
474 ff_->SetParameters(max_val, max_pos, sig, 0.);
475 p.second->Fit(
ff_.get(),
"Q",
"", max_pos - 3. * sig, max_pos + 3. * sig);
476 p.second->Fit(
ff_.get(),
"Q",
"", max_pos - 3. * sig, max_pos + 3. * sig);
479 ad.de_x_mean =
ff_->GetParameter(1);
480 ad.de_x_sigma = fabs(
ff_->GetParameter(2));
483 ad.de_y_mean =
ff_->GetParameter(1);
484 ad.de_y_sigma = fabs(
ff_->GetParameter(2));
489 os <<
"* fitting arm " << ap.first << std::endl
490 <<
" de_x: mean = " << ad.de_x_mean <<
", sigma = " << ad.de_x_sigma << std::endl
491 <<
" de_y: mean = " << ad.de_y_mean <<
", sigma = " << ad.de_y_sigma;
504 struct ArmEventData {
506 std::map<unsigned int, std::set<unsigned int>> matched_track_idc;
509 std::set<unsigned int> reco_proton_idc;
512 std::map<unsigned int, std::set<unsigned int>> matched_track_with_prot_idc, matched_track_without_prot_idc;
515 struct EvaluatedPair {
516 unsigned idx_N, idx_F;
522 vector<EvaluatedPair> evaluatedPairs;
525 std::map<unsigned int, ArmEventData> armEventData;
528 for (
const auto idx_i : sel_track_idc) {
529 const auto &tr_i = hTracks->at(idx_i);
531 unsigned int decRPId_i = rpId_i.
arm() * 100 + rpId_i.station() * 10 + rpId_i.rp();
533 for (
const auto idx_j : sel_track_idc) {
534 const auto &tr_j = hTracks->at(idx_j);
536 unsigned int decRPId_j = rpId_j.
arm() * 100 + rpId_j.station() * 10 + rpId_j.rp();
539 unsigned int arm = 123;
540 for (
const auto &ap :
data_) {
541 if (ap.second.rpId_N == decRPId_i && ap.second.rpId_F == decRPId_j)
550 const double de_x = tr_j.x() - tr_i.x();
551 const double de_y = tr_j.y() - tr_i.y();
553 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
554 const double n_si = ad.n_sigmas[nsi];
555 const bool match_x = fabs(
de_x - ad.de_x_mean) < n_si * ad.de_x_sigma;
556 const bool match_y = fabs(
de_y - ad.de_y_mean) < n_si * ad.de_y_sigma;
557 if (match_x && match_y)
558 armEventData[
arm].matched_track_idc[nsi].insert(idx_i);
564 for (
unsigned int i = 0;
i < hRecoProtonsMultiRP->size(); ++
i) {
565 const auto &proton = (*hRecoProtonsMultiRP)[
i];
567 CTPPSDetId rpId((*proton.contributingLocalTracks().begin())->rpId());
568 unsigned int arm = rpId.arm();
570 if (proton.validFit())
571 armEventData[
arm].reco_proton_idc.insert(
i);
576 os <<
"* cmp matched tracks vs. reco protons" << std::endl;
578 for (
auto &ap : armEventData) {
579 auto &ad =
data_[ap.first];
582 os <<
" arm " << ap.first << std::endl;
584 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
586 os <<
" nsi = " << nsi << std::endl;
588 for (
const auto &tri : ap.second.matched_track_idc[nsi]) {
589 const auto &
track = hTracks->at(tri);
591 bool some_proton_matching =
false;
594 os <<
" tri = " << tri << std::endl;
596 for (
const auto &pri : ap.second.reco_proton_idc) {
597 const auto &proton = (*hRecoProtonsMultiRP)[pri];
599 bool proton_matching =
false;
601 for (
const auto &pr_tr : proton.contributingLocalTracks()) {
603 unsigned int decRPId = rpId.arm() * 100 + rpId.station() * 10 + rpId.rp();
608 const double x = pr_tr->x();
609 const double y = pr_tr->y();
610 const double th = 1E-3;
615 os <<
" pri = " << pri <<
": x_tr = " <<
track.x() <<
", x_pr = " <<
x 616 <<
", match = " <<
match << std::endl;
619 proton_matching =
true;
624 if (proton_matching) {
625 some_proton_matching =
true;
631 os <<
" --> some_proton_matching " << some_proton_matching << std::endl;
633 if (some_proton_matching)
634 ap.second.matched_track_with_prot_idc[nsi].insert(tri);
636 ap.second.matched_track_without_prot_idc[nsi].insert(tri);
642 for (
auto &ap : armEventData) {
643 const auto &
arm = ap.first;
647 auto &aed = ap.second;
649 auto &ass_cut = ppsAssociationCuts.getAssociationCuts(
arm);
653 map<unsigned int, unsigned> matching_multiplicity;
657 const auto &tr_i = hTracks->at(
i);
658 const auto &tr_j = hTracks->at(
j);
663 const unsigned rpDecId_i = id_i.
arm() * 100 + id_i.station() * 10 + id_i.rp();
664 const unsigned rpDecId_j = id_j.arm() * 100 + id_j.station() * 10 + id_j.rp();
666 if (rpDecId_i != ad.rpId_N || rpDecId_j != ad.rpId_F)
669 ArmEventData::EvaluatedPair evp;
674 ass_cut.isSatisfied(ass_cut.qX, tr_i.x(), tr_i.y(), lhcInfoCombined.
crossingAngle(), tr_i.x() - tr_j.x());
676 ass_cut.isSatisfied(ass_cut.qY, tr_i.x(), tr_i.y(), lhcInfoCombined.
crossingAngle(), tr_i.y() - tr_j.y());
678 evp.match = evp.x_cut && evp.y_cut;
680 aed.evaluatedPairs.push_back(evp);
683 matching_multiplicity[
i]++;
684 matching_multiplicity[
j]++;
689 for (
auto &evp : aed.evaluatedPairs)
690 evp.unique = (matching_multiplicity[evp.idx_N] == 1) && (matching_multiplicity[evp.idx_F] == 1);
695 for (
auto &ap : armEventData) {
696 auto &ad =
data_[ap.first];
698 if (ad.de_x_sigma <= 0. && ad.de_y_sigma <= 0.)
701 os <<
"* results for arm " << ap.first << std::endl;
703 os <<
" reco_proton_idc: ";
704 for (
const auto &
idx : ap.second.reco_proton_idc)
708 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
709 os <<
" n_si = " << ad.n_sigmas[nsi] << std::endl;
711 os <<
" matched_track_idc: ";
712 for (
const auto &
idx : ap.second.matched_track_idc[nsi])
716 os <<
" matched_track_with_prot_idc: ";
717 for (
const auto &
idx : ap.second.matched_track_with_prot_idc[nsi])
721 os <<
" matched_track_without_prot_idc: ";
722 for (
const auto &
idx : ap.second.matched_track_without_prot_idc[nsi])
727 os <<
" evaluated pairs: ";
728 for (
const auto &
p : ap.second.evaluatedPairs)
729 os <<
"(" <<
p.idx_N <<
"-" <<
p.idx_F <<
",M" <<
p.match <<
",U" <<
p.unique <<
")" 736 for (
auto &ap : armEventData) {
737 const auto &
arm = ap.first;
741 if (ad.de_x_sigma <= 0. && ad.de_y_sigma <= 0.)
745 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
746 const unsigned int n_exp_prot = ap.second.matched_track_idc[nsi].size();
747 const unsigned int n_rec_prot = ap.second.reco_proton_idc.size();
750 if (n_exp_prot < 1 || n_exp_prot > ad.n_exp_prot_max)
754 const double eff = double(n_rec_prot) / n_exp_prot;
756 for (
unsigned int tri : ap.second.matched_track_idc[nsi]) {
757 const double x_N = hTracks->at(tri).x();
758 const double xi_N = ad.s_x_to_xi_N->Eval(x_N * 1E-1);
760 ad.effPlots[0][nsi].p_eff1_vs_x_N->Fill(x_N, eff);
761 ad.effPlots[0][nsi].p_eff1_vs_xi_N->Fill(xi_N, eff);
763 ad.effPlots[n_exp_prot][nsi].p_eff1_vs_x_N->Fill(x_N, eff);
764 ad.effPlots[n_exp_prot][nsi].p_eff1_vs_xi_N->Fill(xi_N, eff);
768 for (
const auto &tri : ap.second.matched_track_with_prot_idc[nsi]) {
769 const double x_N = hTracks->at(tri).x();
770 const double xi_N = ad.s_x_to_xi_N->Eval(x_N * 1E-1);
772 ad.effPlots[0][nsi].p_eff2_vs_x_N->Fill(x_N, 1.);
773 ad.effPlots[0][nsi].p_eff2_vs_xi_N->Fill(xi_N, 1.);
775 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_x_N->Fill(x_N, 1.);
776 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_xi_N->Fill(xi_N, 1.);
779 for (
const auto &tri : ap.second.matched_track_without_prot_idc[nsi]) {
780 const double x_N = hTracks->at(tri).x();
781 const double xi_N = ad.s_x_to_xi_N->Eval(x_N * 1E-1);
783 ad.effPlots[0][nsi].p_eff2_vs_x_N->Fill(x_N, 0.);
784 ad.effPlots[0][nsi].p_eff2_vs_xi_N->Fill(xi_N, 0.);
786 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_x_N->Fill(x_N, 0.);
787 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_xi_N->Fill(xi_N, 0.);
791 for (
const auto &
cand : ap.second.matched_track_idc[nsi])
793 const double x_N = hTracks->at(
cand).x();
795 auto &
plots = ad.effPlots[n_exp_prot][nsi];
797 bool hasMatchingAndUniquePair =
false;
798 bool hasMatchingAndNonUniquePair =
false;
799 for (
const auto &pair : ap.second.evaluatedPairs)
802 if (
cand != pair.idx_N)
805 if (pair.match && pair.unique)
806 hasMatchingAndUniquePair =
true;
808 if (pair.match && !pair.unique)
809 hasMatchingAndNonUniquePair =
true;
812 if (!pair.x_cut && !pair.y_cut)
814 if (pair.x_cut && !pair.y_cut)
816 if (!pair.x_cut && pair.y_cut)
818 if (pair.x_cut && pair.y_cut)
827 plots.p_fr_match_unique->Fill(x_N, (hasMatchingAndUniquePair) ? 1 : 0);
828 plots.p_fr_match_non_unique->Fill(x_N, (hasMatchingAndNonUniquePair) ? 1 : 0);
834 edm::LogInfo(
"CTPPSProtonReconstructionEfficiencyEstimatorData") << os.str();
840 auto f_out = std::make_unique<TFile>(
outputFile_.c_str(),
"recreate");
842 for (
const auto &ait :
data_) {
844 sprintf(
buf,
"arm %u", ait.first);
845 TDirectory *d_arm = f_out->mkdir(
buf);
std::unique_ptr< TProfile > p_eff2_vs_xi_N
CTPPSProtonReconstructionEfficiencyEstimatorData(const edm::ParameterSet &)
T getParameter(std::string const &) const
std::vector< double > n_sigmas_
std::map< unsigned int, std::map< unsigned int, EffPlots > > effPlots
std::unique_ptr< TProfile > p_fr_signature_12
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
std::unique_ptr< TProfile > p_fr_signature_0
float crossingAngle() const
const edm::ESGetToken< LHCInfoPerFill, LHCInfoPerFillRcd > lhcInfoPerFillToken_
std::unique_ptr< TH1D > h_de_y
std::map< unsigned int, ArmData > data_
std::shared_ptr< const TSpline3 > s_x_to_xi_N
std::unique_ptr< TProfile > p_fr_signature_2
unsigned int n_exp_prot_max
Log< level::Error, false > LogError
std::unique_ptr< TProfile > p_eff1_vs_x_N
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
void UpdateOptics(const LHCInterpolatedOpticalFunctionsSetCollection &ofc)
std::unique_ptr< TProfile > p_fr_match_non_unique
def unique(seq, keepstr=True)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::unique_ptr< TProfile > p_fr_match_unique
edm::EDGetTokenT< reco::ForwardProtonCollection > tokenRecoProtonsMultiRP_
const edm::ESGetToken< LHCInfoPerLS, LHCInfoPerLSRcd > lhcInfoPerLSToken_
#define DEFINE_FWK_MODULE(type)
const bool useNewLHCInfo_
std::unique_ptr< TF1 > ff_
std::unique_ptr< TH1D > h_de_x
const edm::ESGetToken< LHCInfo, LHCInfoRcd > lhcInfoToken_
bool pixelDiscardBXShiftedTracks_
unsigned int n_exp_prot_max_
Log< level::Info, false > LogInfo
std::unique_ptr< TProfile > p_eff1_vs_xi_N
std::vector< CTPPSLocalTrackLite > CTPPSLocalTrackLiteCollection
Collection of CTPPSLocalTrackLite objects.
edm::ESGetToken< LHCInterpolatedOpticalFunctionsSetCollection, CTPPSInterpolatedOpticsRcd > opticsESToken_
Set of optical functions corresponding to one scoring plane along LHC, including splines for interpol...
void add(std::string const &label, ParameterSetDescription const &psetDescription)
std::unique_ptr< TProfile > p_eff2_vs_x_N
bool check(const edm::EventSetup &iSetup)
Base class for CTPPS detector IDs.
std::unique_ptr< TProfile > p_fr_signature_1
edm::EDGetTokenT< CTPPSLocalTrackLiteCollection > tokenTracks_
unsigned int n_prep_events_
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
std::vector< ForwardProton > ForwardProtonCollection
Collection of ForwardProton objects.
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined signature
edm::ESWatcher< CTPPSInterpolatedOpticsRcd > opticsWatcher_
edm::ESGetToken< PPSAssociationCuts, PPSAssociationCutsRcd > ppsAssociationCutsToken_
unsigned int n_events_with_tracks
std::unique_ptr< TH2D > h2_de_y_vs_de_x
void analyze(const edm::Event &, const edm::EventSetup &) override
std::vector< double > n_sigmas