95 : p_eff1_vs_x_N(new TProfile(
"",
";x_{N} (mm);efficiency", 50, 0., 25.)),
96 p_eff1_vs_xi_N(new TProfile(
"",
";#xi_{si,N};efficiency", 50, 0., 0.25)),
98 p_eff2_vs_x_N(new TProfile(
"",
";x_{N} (mm);efficiency", 50, 0., 25.)),
99 p_eff2_vs_xi_N(new TProfile(
"",
";#xi_{si,N};efficiency", 50, 0., 0.25)) {}
102 p_eff1_vs_x_N->Write(
"p_eff1_vs_x_N");
103 p_eff1_vs_xi_N->Write(
"p_eff1_vs_xi_N");
105 p_eff2_vs_x_N->Write(
"p_eff2_vs_x_N");
106 p_eff2_vs_xi_N->Write(
"p_eff2_vs_xi_N");
112 std::map<unsigned int, std::map<unsigned int, EffPlots>>
effPlots;
115 : n_events_with_tracks(0),
117 h_de_x(new TH1D(
"",
";x_{F} - x_{N} (mm)", 200, -1., +1.)),
118 h_de_y(new TH1D(
"",
";y_{F} - y_{N} (mm)", 200, -1., +1.)),
119 h2_de_y_vs_de_x(new TH2D(
"",
";x_{F} - x_{N} (mm);y_{F} - y_{N} (mm)", 100, -1., +1., 100, -1., +1.)),
126 for (
unsigned int nsi = 0; nsi < n_sigmas.size(); ++nsi) {
133 h_de_x->Write(
"h_de_x");
134 h_de_y->Write(
"h_de_y");
135 h2_de_y_vs_de_x->Write(
"h2_de_y_vs_de_x");
139 for (
const auto &n_si : n_sigmas) {
140 sprintf(buf,
"g_de_y_vs_de_x_n_si=%.1f", n_si);
141 TGraph *
g =
new TGraph();
144 g->SetPoint(0, de_x_mean - n_si * de_x_sigma, de_y_mean - n_si * de_y_sigma);
145 g->SetPoint(1, de_x_mean + n_si * de_x_sigma, de_y_mean - n_si * de_y_sigma);
146 g->SetPoint(2, de_x_mean + n_si * de_x_sigma, de_y_mean + n_si * de_y_sigma);
147 g->SetPoint(3, de_x_mean - n_si * de_x_sigma, de_y_mean + n_si * de_y_sigma);
148 g->SetPoint(4, de_x_mean - n_si * de_x_sigma, de_y_mean - n_si * de_y_sigma);
153 TDirectory *d_top = gDirectory;
155 for (
const auto &nep_p : effPlots) {
156 if (nep_p.first == 0)
157 sprintf(buf,
"exp prot all");
159 sprintf(buf,
"exp prot %u", nep_p.first);
161 TDirectory *d_nep = d_top->mkdir(buf);
163 for (
const auto &nsi_p : nep_p.second) {
164 sprintf(buf,
"nsi = %.1f", n_sigmas[nsi_p.first]);
166 TDirectory *d_nsi = d_nep->mkdir(buf);
170 nsi_p.second.write();
180 for (
const auto &
p : ofc) {
184 if (decRPId == rpId_N) {
191 edm::LogError(
"ArmData::UpdateOptics") <<
"Cannot find optical functions for RP " <<
rpId_N;
195 std::vector<double> xiValues =
198 s_x_to_xi_N = std::make_shared<TSpline3>(
"", xDValues.data(), xiValues.data(), xiValues.size());
202 std::map<unsigned int, ArmData>
data_;
231 n_sigmas_(iConfig.getParameter<
std::vector<double>>(
"n_sigmas")),
235 verbosity_(iConfig.getUntrackedParameter<unsigned
int>(
"verbosity")),
237 ff_(new TF1(
"ff",
"[0] * exp(- (x-[1])*(x-[1]) / 2 / [2]/[2]) + [4]")) {
257 desc.
add<
bool>(
"pixelDiscardBXShiftedTracks",
false)
258 ->setComment(
"whether to discard pixel tracks built from BX-shifted planes");
260 desc.
add<
double>(
"localAngleXMin", -0.03)->
setComment(
"minimal accepted value of local horizontal angle (rad)");
261 desc.
add<
double>(
"localAngleXMax", +0.03)->
setComment(
"maximal accepted value of local horizontal angle (rad)");
262 desc.
add<
double>(
"localAngleYMin", -0.04)->
setComment(
"minimal accepted value of local vertical angle (rad)");
263 desc.
add<
double>(
"localAngleYMax", +0.04)->
setComment(
"maximal accepted value of local vertical angle (rad)");
265 desc.
add<
std::string>(
"opticsLabel",
"")->setComment(
"label of the optics records");
267 desc.
add<
unsigned int>(
"n_prep_events", 1000)
268 ->setComment(
"number of preparatory events (to determine de x and de y window)");
270 desc.
add<
unsigned int>(
"n_exp_prot_max", 5)->setComment(
"maximum number of expected protons per event and per arm");
272 desc.
add<std::vector<double>>(
"n_sigmas", {3., 5., 7.})->setComment(
"list of n_sigma values");
274 desc.
add<
unsigned int>(
"rpId_45_N", 0)->setComment(
"decimal RP id for 45 near");
275 desc.
add<
unsigned int>(
"rpId_45_F", 0)->setComment(
"decimal RP id for 45 far");
276 desc.
add<
unsigned int>(
"rpId_56_N", 0)->setComment(
"decimal RP id for 56 near");
277 desc.
add<
unsigned int>(
"rpId_56_F", 0)->setComment(
"decimal RP id for 56 far");
279 desc.
add<
std::string>(
"outputFile",
"output.root")->setComment(
"output file name");
281 desc.
addUntracked<
unsigned int>(
"verbosity", 0)->setComment(
"verbosity level");
283 descriptions.
add(
"ctppsProtonReconstructionEfficiencyEstimatorData", desc);
290 std::ostringstream os;
298 data_[0].UpdateOptics(*hOpticalFunctions);
299 data_[1].UpdateOptics(*hOpticalFunctions);
310 std::vector<unsigned int> sel_track_idc;
311 for (
unsigned int idx = 0;
idx < hTracks->size(); ++
idx) {
312 const auto &tr = hTracks->at(
idx);
324 sel_track_idc.push_back(
idx);
329 os <<
"* tracks (pre-selected):" << std::endl;
331 for (
const auto idx : sel_track_idc) {
332 const auto &tr = hTracks->at(
idx);
336 os <<
" [" <<
idx <<
"] RP=" << decRPId <<
", x=" << tr.getX() <<
", y=" << tr.getY() << std::endl;
339 os <<
"* protons:" << std::endl;
340 for (
unsigned int i = 0;
i < hRecoProtonsMultiRP->size(); ++
i) {
341 const auto &
pr = (*hRecoProtonsMultiRP)[
i];
342 os <<
" [" <<
i <<
"] track indices: ";
343 for (
const auto &trr :
pr.contributingLocalTracks())
344 os << trr.key() <<
", ";
350 map<unsigned int, bool> hasTracksInArm;
352 for (
const auto idx_i : sel_track_idc) {
353 const auto &tr_i = hTracks->at(idx_i);
355 unsigned int decRPId_i = rpId_i.
arm() * 100 + rpId_i.station() * 10 + rpId_i.rp();
357 for (
const auto idx_j : sel_track_idc) {
358 const auto &tr_j = hTracks->at(idx_j);
360 unsigned int decRPId_j = rpId_j.
arm() * 100 + rpId_j.station() * 10 + rpId_j.rp();
363 unsigned int arm = 123;
364 for (
const auto &ap :
data_) {
365 if (ap.second.rpId_N == decRPId_i && ap.second.rpId_F == decRPId_j)
373 hasTracksInArm[
arm] =
true;
376 auto &ad = data_[
arm];
377 const double de_x = tr_j.getX() - tr_i.getX();
378 const double de_y = tr_j.getY() - tr_i.getY();
381 ad.h_de_x->Fill(de_x);
382 ad.h_de_y->Fill(de_y);
385 ad.h2_de_y_vs_de_x->Fill(de_x, de_y);
390 for (
auto &ap :
data_) {
391 if (hasTracksInArm[ap.first])
392 ap.second.n_events_with_tracks++;
396 for (
auto &ap : data_) {
397 auto &ad = ap.second;
400 if (ad.de_x_sigma > 0. && ad.de_y_sigma > 0.)
403 std::vector<std::pair<unsigned int, TH1D *>>
m;
404 m.emplace_back(0, ad.h_de_x.get());
405 m.emplace_back(1, ad.h_de_y.get());
407 for (
const auto &
p : m) {
408 double max_pos = -1E100, max_val = -1.;
409 for (
int bi = 1; bi <
p.second->GetNbinsX(); ++bi) {
410 const double pos =
p.second->GetBinCenter(bi);
411 const double val =
p.second->GetBinContent(bi);
419 const double sig = 0.2;
421 ff_->SetParameters(max_val, max_pos, sig, 0.);
422 p.second->Fit(
ff_.get(),
"Q",
"", max_pos - 3. * sig, max_pos + 3. * sig);
423 p.second->Fit(
ff_.get(),
"Q",
"", max_pos - 3. * sig, max_pos + 3. * sig);
426 ad.de_x_mean =
ff_->GetParameter(1);
427 ad.de_x_sigma = fabs(
ff_->GetParameter(2));
430 ad.de_y_mean =
ff_->GetParameter(1);
431 ad.de_y_sigma = fabs(
ff_->GetParameter(2));
436 os <<
"* fitting arm " << ap.first << std::endl
437 <<
" de_x: mean = " << ad.de_x_mean <<
", sigma = " << ad.de_x_sigma << std::endl
438 <<
" de_y: mean = " << ad.de_y_mean <<
", sigma = " << ad.de_y_sigma;
444 struct ArmEventData {
445 std::map<unsigned int, std::set<unsigned int>> matched_track_idc;
447 std::set<unsigned int> reco_proton_idc;
449 std::map<unsigned int, std::set<unsigned int>> matched_track_with_prot_idc, matched_track_without_prot_idc;
452 std::map<unsigned int, ArmEventData> armEventData;
455 for (
const auto idx_i : sel_track_idc) {
456 const auto &tr_i = hTracks->at(idx_i);
458 unsigned int decRPId_i = rpId_i.
arm() * 100 + rpId_i.station() * 10 + rpId_i.rp();
460 for (
const auto idx_j : sel_track_idc) {
461 const auto &tr_j = hTracks->at(idx_j);
463 unsigned int decRPId_j = rpId_j.
arm() * 100 + rpId_j.station() * 10 + rpId_j.rp();
466 unsigned int arm = 123;
467 for (
const auto &ap : data_) {
468 if (ap.second.rpId_N == decRPId_i && ap.second.rpId_F == decRPId_j)
476 auto &ad = data_[
arm];
477 const double de_x = tr_j.getX() - tr_i.getX();
478 const double de_y = tr_j.getY() - tr_i.getY();
480 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
481 const double n_si = ad.n_sigmas[nsi];
482 const bool match_x = fabs(de_x - ad.de_x_mean) < n_si * ad.de_x_sigma;
483 const bool match_y = fabs(de_y - ad.de_y_mean) < n_si * ad.de_y_sigma;
484 if (match_x && match_y)
485 armEventData[
arm].matched_track_idc[nsi].insert(idx_i);
491 for (
unsigned int i = 0;
i < hRecoProtonsMultiRP->size(); ++
i) {
492 const auto &proton = (*hRecoProtonsMultiRP)[
i];
494 CTPPSDetId rpId((*proton.contributingLocalTracks().begin())->getRPId());
497 if (proton.validFit())
498 armEventData[arm].reco_proton_idc.insert(
i);
503 os <<
"* cmp matched tracks vs. reco protons" << std::endl;
505 for (
auto &ap : armEventData) {
506 auto &ad = data_[ap.first];
509 os <<
" arm " << ap.first << std::endl;
511 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
513 os <<
" nsi = " << nsi << std::endl;
515 for (
const auto &tri : ap.second.matched_track_idc[nsi]) {
516 const auto &
track = hTracks->at(tri);
518 bool some_proton_matching =
false;
521 os <<
" tri = " << tri << std::endl;
523 for (
const auto &pri : ap.second.reco_proton_idc) {
524 const auto &proton = (*hRecoProtonsMultiRP)[pri];
526 bool proton_matching =
false;
528 for (
const auto &pr_tr : proton.contributingLocalTracks()) {
532 if (decRPId != ad.rpId_N)
535 const double x = pr_tr->getX();
536 const double y = pr_tr->getY();
537 const double th = 1E-3;
539 const bool match = (fabs(x -
track.getX()) < th) && (fabs(y -
track.getY()) < th);
542 os <<
" pri = " << pri <<
": x_tr = " <<
track.getX() <<
", x_pr = " << x
543 <<
", match = " << match << std::endl;
546 proton_matching =
true;
551 if (proton_matching) {
552 some_proton_matching =
true;
558 os <<
" --> some_proton_matching " << some_proton_matching << std::endl;
560 if (some_proton_matching)
561 ap.second.matched_track_with_prot_idc[nsi].insert(tri);
563 ap.second.matched_track_without_prot_idc[nsi].insert(tri);
570 for (
auto &ap : armEventData) {
571 auto &ad = data_[ap.first];
573 if (ad.de_x_sigma <= 0. && ad.de_y_sigma <= 0.)
576 os <<
"* results for arm " << ap.first << std::endl;
578 os <<
" reco_proton_idc: ";
579 for (
const auto &
idx : ap.second.reco_proton_idc)
583 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
584 os <<
" n_si = " << ad.n_sigmas[nsi] << std::endl;
586 os <<
" matched_track_idc: ";
587 for (
const auto &idx : ap.second.matched_track_idc[nsi])
591 os <<
" matched_track_with_prot_idc: ";
592 for (
const auto &idx : ap.second.matched_track_with_prot_idc[nsi])
596 os <<
" matched_track_without_prot_idc: ";
597 for (
const auto &idx : ap.second.matched_track_without_prot_idc[nsi])
605 for (
auto &ap : armEventData) {
606 auto &ad = data_[ap.first];
609 if (ad.de_x_sigma <= 0. && ad.de_y_sigma <= 0.)
613 for (
unsigned int nsi = 0; nsi < ad.n_sigmas.size(); ++nsi) {
614 const unsigned int n_exp_prot = ap.second.matched_track_idc[nsi].size();
615 const unsigned int n_rec_prot = ap.second.reco_proton_idc.size();
618 if (n_exp_prot < 1 || n_exp_prot > ad.n_exp_prot_max)
622 const double eff = double(n_rec_prot) / n_exp_prot;
624 for (
unsigned int tri : ap.second.matched_track_idc[nsi]) {
625 const double x_N = hTracks->at(tri).getX();
626 const double xi_N = ad.s_x_to_xi_N->Eval(x_N * 1E-1);
628 ad.effPlots[0][nsi].p_eff1_vs_x_N->Fill(x_N, eff);
629 ad.effPlots[0][nsi].p_eff1_vs_xi_N->Fill(xi_N, eff);
631 ad.effPlots[n_exp_prot][nsi].p_eff1_vs_x_N->Fill(x_N, eff);
632 ad.effPlots[n_exp_prot][nsi].p_eff1_vs_xi_N->Fill(xi_N, eff);
636 for (
const auto &tri : ap.second.matched_track_with_prot_idc[nsi]) {
637 const double x_N = hTracks->at(tri).getX();
638 const double xi_N = ad.s_x_to_xi_N->Eval(x_N * 1E-1);
640 ad.effPlots[0][nsi].p_eff2_vs_x_N->Fill(x_N, 1.);
641 ad.effPlots[0][nsi].p_eff2_vs_xi_N->Fill(xi_N, 1.);
643 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_x_N->Fill(x_N, 1.);
644 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_xi_N->Fill(xi_N, 1.);
647 for (
const auto &tri : ap.second.matched_track_without_prot_idc[nsi]) {
648 const double x_N = hTracks->at(tri).getX();
649 const double xi_N = ad.s_x_to_xi_N->Eval(x_N * 1E-1);
651 ad.effPlots[0][nsi].p_eff2_vs_x_N->Fill(x_N, 0.);
652 ad.effPlots[0][nsi].p_eff2_vs_xi_N->Fill(xi_N, 0.);
654 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_x_N->Fill(x_N, 0.);
655 ad.effPlots[n_exp_prot][nsi].p_eff2_vs_xi_N->Fill(xi_N, 0.);
661 edm::LogInfo(
"CTPPSProtonReconstructionEfficiencyEstimatorData") << os.str();
667 auto f_out = std::make_unique<TFile>(
outputFile_.c_str(),
"recreate");
669 for (
const auto &ait :
data_) {
671 sprintf(buf,
"arm %u", ait.first);
672 TDirectory *d_arm = f_out->mkdir(buf);
T getParameter(std::string const &) const
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
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
bool getByToken(EDGetToken token, Handle< PROD > &result) const
std::unique_ptr< TH1D > h_de_y
std::map< unsigned int, ArmData > data_
std::shared_ptr< const TSpline3 > s_x_to_xi_N
unsigned int n_exp_prot_max
const std::vector< double > & getXiValues() const
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
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
void UpdateOptics(const LHCInterpolatedOpticalFunctionsSetCollection &ofc)
#define DEFINE_FWK_MODULE(type)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
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_
std::unique_ptr< TProfile > p_eff1_vs_xi_N
std::vector< CTPPSLocalTrackLite > CTPPSLocalTrackLiteCollection
Collection of CTPPSLocalTrackLite objects.
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.
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.
edm::ESWatcher< CTPPSInterpolatedOpticsRcd > opticsWatcher_
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