104 :
p_eff1_vs_x_N(new TProfile(
"",
";x_{N} (mm);efficiency", 50, 0., 25.)),
105 p_eff1_vs_xi_N(new TProfile(
"",
";#xi_{si,N};efficiency", 50, 0., 0.25)),
107 p_eff2_vs_x_N(new TProfile(
"",
";x_{N} (mm);efficiency", 50, 0., 25.)),
108 p_eff2_vs_xi_N(new TProfile(
"",
";#xi_{si,N};efficiency", 50, 0., 0.25)),
137 std::map<unsigned int, std::map<unsigned int, EffPlots>>
effPlots;
142 h_de_x(new TH1D(
"",
";x_{F} - x_{N} (mm)", 200, -1., +1.)),
143 h_de_y(new TH1D(
"",
";y_{F} - y_{N} (mm)", 200, -1., +1.)),
144 h2_de_y_vs_de_x(new TH2D(
"",
";x_{F} - x_{N} (mm);y_{F} - y_{N} (mm)", 100, -1., +1., 100, -1., +1.)),
151 for (
unsigned int nsi = 0; nsi <
n_sigmas.size(); ++nsi) {
165 sprintf(buf,
"g_de_y_vs_de_x_n_si=%.1f", n_si);
166 TGraph *
g =
new TGraph();
178 TDirectory *d_top = gDirectory;
180 for (
const auto &nep_p :
effPlots) {
181 if (nep_p.first == 0)
182 sprintf(buf,
"exp prot all");
184 sprintf(buf,
"exp prot %u", nep_p.first);
186 TDirectory *d_nep = d_top->mkdir(buf);
188 for (
const auto &nsi_p : nep_p.second) {
189 sprintf(buf,
"nsi = %.1f", n_sigmas[nsi_p.first]);
191 TDirectory *d_nsi = d_nep->mkdir(buf);
195 nsi_p.second.write();
205 for (
const auto &
p : ofc) {
207 unsigned int decRPId = rpId.
arm() * 100 + rpId.
station() * 10 + rpId.
rp();
216 edm::LogError(
"ArmData::UpdateOptics") <<
"Cannot find optical functions for RP " <<
rpId_N;
220 std::vector<double> xiValues =
223 s_x_to_xi_N = std::make_shared<TSpline3>(
"", xDValues.data(), xiValues.data(), xiValues.size());
227 std::map<unsigned int, ArmData>
data_;
243 tokenRecoProtonsMultiRP_(
248 ppsAssociationCutsToken_(
251 pixelDiscardBXShiftedTracks_(iConfig.getParameter<bool>(
"pixelDiscardBXShiftedTracks")),
253 localAngleXMin_(iConfig.getParameter<double>(
"localAngleXMin")),
254 localAngleXMax_(iConfig.getParameter<double>(
"localAngleXMax")),
255 localAngleYMin_(iConfig.getParameter<double>(
"localAngleYMin")),
256 localAngleYMax_(iConfig.getParameter<double>(
"localAngleYMax")),
258 n_prep_events_(iConfig.getParameter<unsigned int>(
"n_prep_events")),
259 n_exp_prot_max_(iConfig.getParameter<unsigned int>(
"n_exp_prot_max")),
260 n_sigmas_(iConfig.getParameter<std::
vector<double>>(
"n_sigmas")),
262 outputFile_(iConfig.getParameter<
string>(
"outputFile")),
264 verbosity_(iConfig.getUntrackedParameter<unsigned int>(
"verbosity")),
266 ff_(new TF1(
"ff",
"[0] * exp(- (x-[1])*(x-[1]) / 2 / [2]/[2]) + [4]")) {
286 desc.
add<
string>(
"lhcInfoLabel",
"")->setComment(
"label of LHCInfo data");
287 desc.
add<
string>(
"opticsLabel",
"")->setComment(
"label of optics data");
288 desc.
add<
string>(
"ppsAssociationCutsLabel",
"")->setComment(
"label of PPSAssociationCuts data");
290 desc.
add<
bool>(
"pixelDiscardBXShiftedTracks",
false)
291 ->setComment(
"whether to discard pixel tracks built from BX-shifted planes");
293 desc.
add<
double>(
"localAngleXMin", -0.03)->
setComment(
"minimal accepted value of local horizontal angle (rad)");
294 desc.
add<
double>(
"localAngleXMax", +0.03)->
setComment(
"maximal accepted value of local horizontal angle (rad)");
295 desc.
add<
double>(
"localAngleYMin", -0.04)->
setComment(
"minimal accepted value of local vertical angle (rad)");
296 desc.
add<
double>(
"localAngleYMax", +0.04)->
setComment(
"maximal accepted value of local vertical angle (rad)");
298 desc.
add<
unsigned int>(
"n_prep_events", 1000)
299 ->setComment(
"number of preparatory events (to determine de x and de y window)");
301 desc.
add<
unsigned int>(
"n_exp_prot_max", 5)->setComment(
"maximum number of expected protons per event and per arm");
303 desc.
add<std::vector<double>>(
"n_sigmas", {3., 5., 7.})->setComment(
"list of n_sigma values");
305 desc.
add<
unsigned int>(
"rpId_45_N", 0)->setComment(
"decimal RP id for 45 near");
306 desc.
add<
unsigned int>(
"rpId_45_F", 0)->setComment(
"decimal RP id for 45 far");
307 desc.
add<
unsigned int>(
"rpId_56_N", 0)->setComment(
"decimal RP id for 56 near");
308 desc.
add<
unsigned int>(
"rpId_56_F", 0)->setComment(
"decimal RP id for 56 far");
310 desc.
add<
std::string>(
"outputFile",
"output.root")->setComment(
"output file name");
312 desc.
addUntracked<
unsigned int>(
"verbosity", 0)->setComment(
"verbosity level");
314 descriptions.
add(
"ctppsProtonReconstructionEfficiencyEstimatorData", desc);
321 std::ostringstream os;
330 data_[0].UpdateOptics(opticalFunctions);
331 data_[1].UpdateOptics(opticalFunctions);
342 std::vector<unsigned int> sel_track_idc;
344 std::map<unsigned int, std::vector<unsigned int>> trackingSelection;
346 for (
unsigned int idx = 0; idx < hTracks->size(); ++idx) {
347 const auto &tr = hTracks->at(idx);
359 sel_track_idc.push_back(idx);
363 const bool trackerRP =
367 trackingSelection[rpId.arm()].push_back(idx);
372 os <<
"* tracks (pre-selected):" << std::endl;
374 for (
const auto idx : sel_track_idc) {
375 const auto &tr = hTracks->at(idx);
377 unsigned int decRPId = rpId.
arm() * 100 + rpId.station() * 10 + rpId.rp();
379 os <<
" [" << idx <<
"] RP=" << decRPId <<
", x=" << tr.x() <<
", y=" << tr.y() << std::endl;
382 os <<
"* protons:" << std::endl;
383 for (
unsigned int i = 0;
i < hRecoProtonsMultiRP->size(); ++
i) {
384 const auto &pr = (*hRecoProtonsMultiRP)[
i];
385 os <<
" [" <<
i <<
"] track indices: ";
386 for (
const auto &trr : pr.contributingLocalTracks())
387 os << trr.key() <<
", ";
393 map<unsigned int, bool> hasTracksInArm;
395 for (
const auto idx_i : sel_track_idc) {
396 const auto &tr_i = hTracks->at(idx_i);
398 unsigned int decRPId_i = rpId_i.
arm() * 100 + rpId_i.station() * 10 + rpId_i.rp();
400 for (
const auto idx_j : sel_track_idc) {
401 const auto &tr_j = hTracks->at(idx_j);
403 unsigned int decRPId_j = rpId_j.
arm() * 100 + rpId_j.station() * 10 + rpId_j.rp();
406 unsigned int arm = 123;
407 for (
const auto &ap :
data_) {
408 if (ap.second.rpId_N == decRPId_i && ap.second.rpId_F == decRPId_j)
416 hasTracksInArm[arm] =
true;
419 auto &ad = data_[arm];
420 const double de_x = tr_j.x() - tr_i.x();
421 const double de_y = tr_j.y() - tr_i.y();
424 ad.h_de_x->Fill(de_x);
425 ad.h_de_y->Fill(de_y);
428 ad.h2_de_y_vs_de_x->Fill(de_x, de_y);
433 for (
auto &ap :
data_) {
434 if (hasTracksInArm[ap.first])
435 ap.second.n_events_with_tracks++;
439 for (
auto &ap : data_) {
440 auto &ad = ap.second;
443 if (ad.de_x_sigma > 0. && ad.de_y_sigma > 0.)
446 std::vector<std::pair<unsigned int, TH1D *>>
m;
447 m.emplace_back(0, ad.h_de_x.get());
448 m.emplace_back(1, ad.h_de_y.get());
450 for (
const auto &
p : m) {
451 double max_pos = -1E100, max_val = -1.;
452 for (
int bi = 1; bi <
p.second->GetNbinsX(); ++bi) {
453 const double pos =
p.second->GetBinCenter(bi);
454 const double val =
p.second->GetBinContent(bi);
462 const double sig = 0.2;
464 ff_->SetParameters(max_val, max_pos, sig, 0.);
465 p.second->Fit(
ff_.get(),
"Q",
"", max_pos - 3. * sig, max_pos + 3. * sig);
466 p.second->Fit(
ff_.get(),
"Q",
"", max_pos - 3. * sig, max_pos + 3. * sig);
469 ad.de_x_mean =
ff_->GetParameter(1);
470 ad.de_x_sigma = fabs(
ff_->GetParameter(2));
473 ad.de_y_mean =
ff_->GetParameter(1);
474 ad.de_y_sigma = fabs(
ff_->GetParameter(2));
479 os <<
"* fitting arm " << ap.first << std::endl
480 <<
" de_x: mean = " << ad.de_x_mean <<
", sigma = " << ad.de_x_sigma << std::endl
481 <<
" de_y: mean = " << ad.de_y_mean <<
", sigma = " << ad.de_y_sigma;
494 struct ArmEventData {
496 std::map<unsigned int, std::set<unsigned int>> matched_track_idc;
499 std::set<unsigned int> reco_proton_idc;
502 std::map<unsigned int, std::set<unsigned int>> matched_track_with_prot_idc, matched_track_without_prot_idc;
505 struct EvaluatedPair {
506 unsigned idx_N, idx_F;
512 vector<EvaluatedPair> evaluatedPairs;
515 std::map<unsigned int, ArmEventData> armEventData;
518 for (
const auto idx_i : sel_track_idc) {
519 const auto &tr_i = hTracks->at(idx_i);
521 unsigned int decRPId_i = rpId_i.
arm() * 100 + rpId_i.station() * 10 + rpId_i.rp();
523 for (
const auto idx_j : sel_track_idc) {
524 const auto &tr_j = hTracks->at(idx_j);
526 unsigned int decRPId_j = rpId_j.
arm() * 100 + rpId_j.station() * 10 + rpId_j.rp();
529 unsigned int arm = 123;
530 for (
const auto &ap : data_) {
531 if (ap.second.rpId_N == decRPId_i && ap.second.rpId_F == decRPId_j)
539 auto &ad = data_[arm];
540 const double de_x = tr_j.x() - tr_i.x();
541 const double de_y = tr_j.y() - tr_i.y();
543 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
544 const double n_si = ad.n_sigmas[nsi];
545 const bool match_x = fabs(de_x - ad.de_x_mean) < n_si * ad.de_x_sigma;
546 const bool match_y = fabs(de_y - ad.de_y_mean) < n_si * ad.de_y_sigma;
547 if (match_x && match_y)
548 armEventData[arm].matched_track_idc[nsi].insert(idx_i);
554 for (
unsigned int i = 0;
i < hRecoProtonsMultiRP->size(); ++
i) {
555 const auto &proton = (*hRecoProtonsMultiRP)[
i];
557 CTPPSDetId rpId((*proton.contributingLocalTracks().begin())->rpId());
558 unsigned int arm = rpId.
arm();
560 if (proton.validFit())
561 armEventData[arm].reco_proton_idc.insert(
i);
566 os <<
"* cmp matched tracks vs. reco protons" << std::endl;
568 for (
auto &ap : armEventData) {
569 auto &ad = data_[ap.first];
572 os <<
" arm " << ap.first << std::endl;
574 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
576 os <<
" nsi = " << nsi << std::endl;
578 for (
const auto &tri : ap.second.matched_track_idc[nsi]) {
579 const auto &
track = hTracks->at(tri);
581 bool some_proton_matching =
false;
584 os <<
" tri = " << tri << std::endl;
586 for (
const auto &pri : ap.second.reco_proton_idc) {
587 const auto &proton = (*hRecoProtonsMultiRP)[pri];
589 bool proton_matching =
false;
591 for (
const auto &pr_tr : proton.contributingLocalTracks()) {
593 unsigned int decRPId = rpId.
arm() * 100 + rpId.station() * 10 + rpId.rp();
595 if (decRPId != ad.rpId_N)
598 const double x = pr_tr->x();
599 const double y = pr_tr->y();
600 const double th = 1E-3;
602 const bool match = (fabs(x -
track.x()) < th) && (fabs(y -
track.y()) < th);
605 os <<
" pri = " << pri <<
": x_tr = " <<
track.x() <<
", x_pr = " << x
606 <<
", match = " << match << std::endl;
609 proton_matching =
true;
614 if (proton_matching) {
615 some_proton_matching =
true;
621 os <<
" --> some_proton_matching " << some_proton_matching << std::endl;
623 if (some_proton_matching)
624 ap.second.matched_track_with_prot_idc[nsi].insert(tri);
626 ap.second.matched_track_without_prot_idc[nsi].insert(tri);
632 for (
auto &ap : armEventData) {
633 const auto &arm = ap.first;
635 auto &ad = data_[arm];
637 auto &aed = ap.second;
639 auto &ass_cut = ppsAssociationCuts.getAssociationCuts(arm);
641 const auto &
indices = trackingSelection[arm];
643 map<unsigned int, unsigned> matching_multiplicity;
646 for (
const auto &
j : indices) {
647 const auto &tr_i = hTracks->at(
i);
648 const auto &tr_j = hTracks->at(
j);
653 const unsigned rpDecId_i = id_i.
arm() * 100 + id_i.station() * 10 + id_i.rp();
654 const unsigned rpDecId_j = id_j.arm() * 100 + id_j.station() * 10 + id_j.rp();
656 if (rpDecId_i != ad.rpId_N || rpDecId_j != ad.rpId_F)
659 ArmEventData::EvaluatedPair evp;
663 evp.x_cut = ass_cut.isSatisfied(ass_cut.qX, tr_i.x(), tr_i.y(), lhcInfo.crossingAngle(), tr_i.x() - tr_j.x());
664 evp.y_cut = ass_cut.isSatisfied(ass_cut.qY, tr_i.x(), tr_i.y(), lhcInfo.crossingAngle(), tr_i.y() - tr_j.y());
666 evp.match = evp.x_cut && evp.y_cut;
668 aed.evaluatedPairs.push_back(evp);
671 matching_multiplicity[
i]++;
672 matching_multiplicity[
j]++;
677 for (
auto &evp : aed.evaluatedPairs)
678 evp.unique = (matching_multiplicity[evp.idx_N] == 1) && (matching_multiplicity[evp.idx_F] == 1);
683 for (
auto &ap : armEventData) {
684 auto &ad = data_[ap.first];
686 if (ad.de_x_sigma <= 0. && ad.de_y_sigma <= 0.)
689 os <<
"* results for arm " << ap.first << std::endl;
691 os <<
" reco_proton_idc: ";
692 for (
const auto &idx : ap.second.reco_proton_idc)
696 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
697 os <<
" n_si = " << ad.n_sigmas[nsi] << std::endl;
699 os <<
" matched_track_idc: ";
700 for (
const auto &idx : ap.second.matched_track_idc[nsi])
704 os <<
" matched_track_with_prot_idc: ";
705 for (
const auto &idx : ap.second.matched_track_with_prot_idc[nsi])
709 os <<
" matched_track_without_prot_idc: ";
710 for (
const auto &idx : ap.second.matched_track_without_prot_idc[nsi])
715 os <<
" evaluated pairs: ";
716 for (
const auto &
p : ap.second.evaluatedPairs)
717 os <<
"(" <<
p.idx_N <<
"-" <<
p.idx_F <<
",M" <<
p.match <<
",U" <<
p.unique <<
")"
724 for (
auto &ap : armEventData) {
725 const auto &arm = ap.first;
726 auto &ad = data_[arm];
729 if (ad.de_x_sigma <= 0. && ad.de_y_sigma <= 0.)
733 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
734 const unsigned int n_exp_prot = ap.second.matched_track_idc[nsi].size();
735 const unsigned int n_rec_prot = ap.second.reco_proton_idc.size();
738 if (n_exp_prot < 1 || n_exp_prot > ad.n_exp_prot_max)
742 const double eff = double(n_rec_prot) / n_exp_prot;
744 for (
unsigned int tri : ap.second.matched_track_idc[nsi]) {
745 const double x_N = hTracks->at(tri).x();
746 const double xi_N = ad.s_x_to_xi_N->Eval(x_N * 1E-1);
748 ad.effPlots[0][nsi].p_eff1_vs_x_N->Fill(x_N, eff);
749 ad.effPlots[0][nsi].p_eff1_vs_xi_N->Fill(xi_N, eff);
751 ad.effPlots[n_exp_prot][nsi].p_eff1_vs_x_N->Fill(x_N, eff);
752 ad.effPlots[n_exp_prot][nsi].p_eff1_vs_xi_N->Fill(xi_N, eff);
756 for (
const auto &tri : ap.second.matched_track_with_prot_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_eff2_vs_x_N->Fill(x_N, 1.);
761 ad.effPlots[0][nsi].p_eff2_vs_xi_N->Fill(xi_N, 1.);
763 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_x_N->Fill(x_N, 1.);
764 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_xi_N->Fill(xi_N, 1.);
767 for (
const auto &tri : ap.second.matched_track_without_prot_idc[nsi]) {
768 const double x_N = hTracks->at(tri).x();
769 const double xi_N = ad.s_x_to_xi_N->Eval(x_N * 1E-1);
771 ad.effPlots[0][nsi].p_eff2_vs_x_N->Fill(x_N, 0.);
772 ad.effPlots[0][nsi].p_eff2_vs_xi_N->Fill(xi_N, 0.);
774 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_x_N->Fill(x_N, 0.);
775 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_xi_N->Fill(xi_N, 0.);
779 for (
const auto &cand : ap.second.matched_track_idc[nsi])
781 const double x_N = hTracks->at(cand).x();
783 auto &
plots = ad.effPlots[n_exp_prot][nsi];
785 bool hasMatchingAndUniquePair =
false;
786 bool hasMatchingAndNonUniquePair =
false;
787 for (
const auto &pair : ap.second.evaluatedPairs)
790 if (cand != pair.idx_N)
793 if (pair.match && pair.unique)
794 hasMatchingAndUniquePair =
true;
796 if (pair.match && !pair.unique)
797 hasMatchingAndNonUniquePair =
true;
800 if (!pair.x_cut && !pair.y_cut)
802 if (pair.x_cut && !pair.y_cut)
804 if (!pair.x_cut && pair.y_cut)
806 if (pair.x_cut && pair.y_cut)
809 plots.p_fr_signature_0->Fill(x_N, (signature == 0) ? 1 : 0);
810 plots.p_fr_signature_1->Fill(x_N, (signature == 1) ? 1 : 0);
811 plots.p_fr_signature_2->Fill(x_N, (signature == 2) ? 1 : 0);
812 plots.p_fr_signature_12->Fill(x_N, (signature == 12) ? 1 : 0);
815 plots.p_fr_match_unique->Fill(x_N, (hasMatchingAndUniquePair) ? 1 : 0);
816 plots.p_fr_match_non_unique->Fill(x_N, (hasMatchingAndNonUniquePair) ? 1 : 0);
822 edm::LogInfo(
"CTPPSProtonReconstructionEfficiencyEstimatorData") << os.str();
828 auto f_out = std::make_unique<TFile>(
outputFile_.c_str(),
"recreate");
830 for (
const auto &ait :
data_) {
832 sprintf(buf,
"arm %u", ait.first);
833 TDirectory *d_arm = f_out->mkdir(buf);
void setComment(std::string const &value)
std::unique_ptr< TProfile > p_eff2_vs_xi_N
CTPPSProtonReconstructionEfficiencyEstimatorData(const edm::ParameterSet &)
std::vector< double > n_sigmas_
std::map< unsigned int, std::map< unsigned int, EffPlots > > effPlots
std::unique_ptr< TProfile > p_fr_signature_12
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
std::unique_ptr< TProfile > p_fr_signature_0
bool getByToken(EDGetToken token, Handle< PROD > &result) const
#define DEFINE_FWK_MODULE(type)
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
const std::vector< double > & getXiValues() const
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
edm::ESGetToken< LHCInfo, LHCInfoRcd > lhcInfoESToken_
void UpdateOptics(const LHCInterpolatedOpticalFunctionsSetCollection &ofc)
bool getData(T &iHolder) const
std::unique_ptr< TProfile > p_fr_match_non_unique
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::unique_ptr< TProfile > p_fr_match_unique
edm::EDGetTokenT< reco::ForwardProtonCollection > tokenRecoProtonsMultiRP_
std::unique_ptr< TF1 > ff_
ParameterDescriptionBase * add(U const &iLabel, T const &value)
std::unique_ptr< TH1D > h_de_x
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_
T getParameter(std::string const &) const
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
const std::vector< std::vector< double > > & getFcnValues() const
std::unique_ptr< TH2D > h2_de_y_vs_de_x
void analyze(const edm::Event &, const edm::EventSetup &) override
std::vector< double > n_sigmas