19 #include <fmt/format.h> 20 #include <fmt/printf.h> 43 #include "TFitResult.h" 80 throw cms::Exception(
"Inconsistent Data") <<
"Passed inexistent cut value";
153 dqmDir_(iConfig.getParameter<
std::
string>(
"dqmDir")),
154 doChebyshevFit_(iConfig.getParameter<
bool>(
"doChebyshevFit")),
155 order_(iConfig.getParameter<
int>(
"order")),
156 fitChi2Cut_(iConfig.getParameter<double>(
"fitChi2Cut")),
157 fitRange_(iConfig.getParameter<
std::
vector<double>>(
"fitRange")),
158 minHitsCut_(iConfig.getParameter<
int>(
"minHitsCut")),
159 recordName_(iConfig.getParameter<
std::
string>(
"record")) {
165 throw cms::Exception(
"SiPixelLorentzAnglePCLHarvester") <<
"Too many fit range parameters specified";
171 throw cms::Exception(
"SiPixelLorentzAnglePCLHarvester") <<
"PoolDBService required";
206 if (modulename.find(
"BPix_") != std::string::npos) {
208 const auto& detId = bn.
getDetId(tTopo);
213 }
else if (modulename.find(
"FPix_") != std::string::npos) {
215 const auto& detId = en.
getDetId(tTopo);
226 LogDebug(
"SiPixelLorentzAnglePCLHarvester") <<
id;
229 LogDebug(
"SiPixelLorentzAnglePCLHarvester") <<
"Stored a total of " <<
count <<
" new detIds.";
235 std::vector<uint32_t> treatedIndices;
237 for (
const auto& det :
geom->detsPXB()) {
250 if (
std::find(treatedIndices.begin(), treatedIndices.end(), i_index) != treatedIndices.end()) {
253 hists_.
detIdsList.insert(std::pair<uint32_t, std::vector<uint32_t>>(i_index, {rawId}));
254 treatedIndices.push_back(i_index);
259 for (
const auto&
i : treatedIndices) {
261 LogDebug(
"SiPixelLorentzAnglePCLHarvester") <<
id;
265 LogDebug(
"SiPixelLorentzAnglePCLHarvester") <<
"Stored a total of " <<
count <<
" detIds.";
282 for (
int i_layer = 1; i_layer <=
hists_.
nlay; i_layer++) {
283 const auto& prefix_ = fmt::sprintf(
"%s/BPix/BPixLayer%i",
dqmDir_, i_layer);
284 for (
int i_module = 1; i_module <=
hists_.
nModules_[i_layer - 1]; i_module++) {
285 int i_index = i_module + (i_layer - 1) *
hists_.
nModules_[i_layer - 1];
288 iGetter.
get(
fmt::format(
"{}/h_drift_depth_layer{}_module{}", prefix_, i_layer, i_module));
292 <<
"Failed to retrieve electron drift over depth for layer " << i_layer <<
", module " << i_module <<
".";
297 iGetter.
get(
fmt::format(
"{}/h_drift_depth_adc_layer{}_module{}", prefix_, i_layer, i_module));
300 iGetter.
get(
fmt::format(
"{}/h_drift_depth_adc2_layer{}_module{}", prefix_, i_layer, i_module));
303 iGetter.
get(
fmt::format(
"{}/h_drift_depth_noadc_layer{}_module{}", prefix_, i_layer, i_module));
342 edm::LogError(
"SiPixelLorentzAnglePCLHarvester") <<
"Failed to retrieve the hit on track occupancy.";
365 iBooker.
book1D(
"h_drift_depth_adc_slice",
"slice of adc histogram", hist_drift_, min_drift_, max_drift_);
369 "h_diffLA",
"difference in #mu_{H}; #Delta #mu_{H}/#mu_{H} (old-new)/old [%];n. modules", 100, -150, 150);
373 const double lo = -0.5;
374 const double hi = maxSect - 0.5;
378 std::string repText =
"%s tan#theta_{LA}/B by sector;pixel sector;%s tan(#theta_{LA})/B [1/T]";
380 iBooker.
book1D(
"h_LAbySector_Measured", fmt::sprintf(repText,
"measured",
"measured"), maxSect, lo,
hi);
382 iBooker.
book1D(
"h_LAbySector_Accepted", fmt::sprintf(repText,
"accepted",
"accepted"), maxSect, lo,
hi);
384 iBooker.
book1D(
"h_LAbySector_Rejected", fmt::sprintf(repText,
"rejected",
"rejected"), maxSect, lo,
hi);
387 iBooker.
book1D(
"h_deltaLAbySector", fmt::sprintf(repText,
"#Delta",
"#Delta"), maxSect, lo,
hi);
389 iBooker.
book1D(
"h_bySectorChi2",
"Fit #chi^{2}/ndf by sector;pixel sector; fit #chi^{2}/ndf", maxSect, lo,
hi);
392 iBooker.
book1D(
"h_bySectFitStatus",
"Fit Status by sector;pixel sector; fit status", maxSect, lo,
hi);
395 "h_bySectorCovMatrixStatus",
"Fit Covariance Matrix Status by sector;pixel sector; fit status", maxSect, lo,
hi);
397 iBooker.
book1D(
"h_bySectorDriftError",
398 "square error on the measured drift at half-width by sector;pixel sector;#Delta d^{2}(t/2)",
404 std::vector<std::string>
labels = {
"#chi^{2}!=0",
"#chi^{2} cut",
"covStat>=2",
"n. entries cut"};
406 "Fit quality by sector;pixel sector;quality cut",
415 for (
int bin = 1;
bin <= maxSect;
bin++) {
429 for (
unsigned int binY = 1; binY <=
labels.size(); binY++) {
437 std::string repText =
"BPix Layer %i tan#theta_{LA}/B;module number;ladder number;tan#theta_{LA}/B [1/T]";
440 fmt::sprintf(repText,
i + 1),
448 repName =
"h2_byLayerDiff_%i";
449 repText =
"BPix Layer %i #Delta#mu_{H}/#mu_{H};module number;ladder number;#Delta#mu_{H}/#mu_{H} [%%]";
451 fmt::sprintf(repText,
i + 1),
461 edm::LogPrint(
"LorentzAngle") <<
"module" <<
"\t" <<
"layer" <<
"\t" 462 <<
"offset" <<
"\t" <<
"e0" <<
"\t" 463 <<
"slope" <<
"\t" <<
"e1" <<
"\t" 464 <<
"rel.err" <<
"\t" <<
"pull" <<
"\t" 465 <<
"p2" <<
"\t" <<
"e2" <<
"\t" 466 <<
"p3" <<
"\t" <<
"e3" <<
"\t" 467 <<
"p4" <<
"\t" <<
"e4" <<
"\t" 468 <<
"p5" <<
"\t" <<
"e5" <<
"\t" 469 <<
"chi2" <<
"\t" <<
"prob" <<
"\t" 470 <<
"newDetId" <<
"\t" <<
"tan(LA)" <<
"\t" 475 std::shared_ptr<SiPixelLorentzAngle>
LorentzAngle = std::make_shared<SiPixelLorentzAngle>();
478 double p1_simul_newmodule = 0.294044;
480 for (
int i_layer = 1; i_layer <=
hists_.
nlay; i_layer++) {
481 for (
int i_module = 1; i_module <=
hists_.
nModules_[i_layer - 1]; i_module++) {
483 p1_simul[i_layer - 1][i_module - 1] = 0.436848;
484 else if (i_layer == 2)
485 p1_simul[i_layer - 1][i_module - 1] = 0.25802;
486 else if (i_layer == 3 && i_module <= 4)
487 p1_simul[i_layer - 1][i_module - 1] = 0.29374;
488 else if (i_layer == 3 && i_module >= 5)
489 p1_simul[i_layer - 1][i_module - 1] = 0.31084;
490 else if (i_layer == 4 && i_module <= 4)
491 p1_simul[i_layer - 1][i_module - 1] = 0.29944;
493 p1_simul[i_layer - 1][i_module - 1] = 0.31426;
498 p1_simul[
hists_.
nlay][i_module - 1] = p1_simul_newmodule;
507 for (
int i = 1;
i <= hist_depth_;
i++) {
508 findMean(h_drift_depth_adc_slice_,
i, new_index);
516 <<
res.p1 << std::setprecision(3) <<
"\t" <<
res.e1 <<
"\t" 517 <<
res.e1 /
res.p1 * 100. <<
"\t" 519 <<
res.e2 <<
"\t" <<
res.p3 <<
"\t" <<
res.e3 <<
"\t" <<
res.p4 <<
"\t" 520 <<
res.e4 <<
"\t" <<
res.p5 <<
"\t" <<
res.e5 <<
"\t" <<
res.chi2 <<
"\t" 526 for (
int i_layer = 1; i_layer <=
hists_.
nlay; i_layer++) {
527 for (
int i_module = 1; i_module <=
hists_.
nModules_[i_layer - 1]; i_module++) {
528 int i_index = i_module + (i_layer - 1) *
hists_.
nModules_[i_layer - 1];
532 for (
int i = 1;
i <= hist_depth_;
i++) {
533 findMean(h_drift_depth_adc_slice_,
i, i_index);
540 << std::setprecision(4) << i_module <<
"\t" << i_layer <<
"\t" <<
res.p0 <<
"\t" <<
res.e0 <<
"\t" <<
res.p1
541 << std::setprecision(3) <<
"\t" <<
res.e1 <<
"\t" <<
res.e1 /
res.p1 * 100. <<
"\t" 542 << (
res.p1 - p1_simul[i_layer - 1][i_module - 1]) /
res.e1 <<
"\t" <<
res.p2 <<
"\t" <<
res.e2 <<
"\t" 543 <<
res.p3 <<
"\t" <<
res.e3 <<
"\t" <<
res.p4 <<
"\t" <<
res.e4 <<
"\t" <<
res.p5 <<
"\t" <<
res.e5 <<
"\t" 544 <<
res.chi2 <<
"\t" <<
res.prob <<
"\t" 546 <<
"\t" <<
res.tan_LA <<
"\t" <<
res.error_LA;
552 const auto& newLAMap =
LorentzAngle->getLorentzAngles();
553 std::vector<unsigned int> currentLADets;
554 std::vector<unsigned int> newLADets;
558 std::back_inserter(currentLADets),
563 std::back_inserter(newLADets),
566 std::vector<unsigned int> notCommon;
567 std::set_symmetric_difference(
568 currentLADets.begin(), currentLADets.end(), newLADets.begin(), newLADets.end(), std::back_inserter(notCommon));
570 for (
const auto&
id : notCommon) {
572 if (!
LorentzAngle->putLorentzAngle(
id, fPixLorentzAnglePerTesla_)) {
574 <<
"[SiPixelLorentzAnglePCLHarvester::dqmEndJob] filling rest of payload: detid already exists";
578 for (
const auto&
id : newLADets) {
581 h_diffLA->
Fill(deltaMuHoverMuH * 100.
f);
584 bool isPayloadChanged{
false};
594 float deltaMuHoverMuH =
598 if (!isPayloadChanged && (deltaMuHoverMuH != 0.
f))
599 isPayloadChanged =
true;
603 if (isPayloadChanged) {
612 edm::LogError(
"SiPixelLorentzAngleDB") <<
"caught std::exception " << er.what();
615 edm::LogError(
"SiPixelLorentzAngleDB") <<
"Service is unavailable";
618 edm::LogPrint(
"SiPixelLorentzAngleDB") << __PRETTY_FUNCTION__ <<
" there is no new valid measurement to append! ";
625 h_drift_depth_adc_slice_->
Reset();
626 int hist_drift_ = h_drift_depth_adc_slice_->
getNbinsX();
630 for (
int j = 1;
j <= hist_drift_;
j++) {
650 double mean = h_drift_depth_adc_slice_->
getMean(1);
658 h_drift_depth_adc_slice_->
Reset();
663 std::shared_ptr<SiPixelLorentzAngle> theLAPayload,
int i_index,
int i_layer,
int i_module) {
670 const int npar =
order_ + 1;
674 f1_ = std::make_unique<TF1>(
"f1",
675 "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + [5]*x*x*x*x*x",
684 assert(strcmp(
f1_->GetName(),
"f1") == 0);
686 f1_->SetParName(0,
"offset");
687 f1_->SetParName(1,
"tan#theta_{LA}");
688 f1_->SetParName(2,
"quad term");
689 f1_->SetParName(3,
"cubic term");
690 f1_->SetParName(4,
"quartic term");
691 f1_->SetParName(5,
"quintic term");
693 f1_->SetParameter(0, 0);
694 f1_->SetParError(0, 0);
695 f1_->SetParameter(1, 0.4);
696 f1_->SetParError(1, 0);
697 f1_->SetParameter(2, 0.0);
698 f1_->SetParError(2, 0);
699 f1_->SetParameter(3, 0.0);
700 f1_->SetParError(3, 0);
701 f1_->SetParameter(4, 0.0);
702 f1_->SetParError(4, 0);
703 f1_->SetParameter(5, 0.0);
704 f1_->SetParError(5, 0);
705 f1_->SetChisquare(0);
710 edm::LogInfo(
"SiPixelLorentzAnglePCLHarvester") <<
"Fit status: " <<
res.fitStatus;
712 edm::LogError(
"SiPixelLorentzAnglePCLHarvester") <<
"Could not retrieve the fit status! Setting it to 0 by default";
716 if (
res.fitStatus >= 0) {
717 res.covMatrixStatus =
result->CovMatrixStatus();
732 cov00 =
result->CovMatrix(0, 0);
738 res.p0 =
f1_->GetParameter(0);
739 res.e0 =
f1_->GetParError(0);
740 res.p1 =
f1_->GetParameter(1);
741 res.e1 =
f1_->GetParError(1);
742 res.p2 =
f1_->GetParameter(2);
743 res.e2 =
f1_->GetParError(2);
744 res.p3 =
f1_->GetParameter(3);
745 res.e3 =
f1_->GetParError(3);
746 res.p4 =
f1_->GetParameter(4);
747 res.e4 =
f1_->GetParError(4);
748 res.p5 =
f1_->GetParameter(5);
749 res.e5 =
f1_->GetParError(5);
750 res.chi2 =
f1_->GetChisquare();
752 res.prob =
f1_->GetProb();
755 double f1_halfwidth =
res.p0 +
res.p1 * half_width +
res.p2 *
pow(half_width, 2) +
res.p3 *
pow(half_width, 3) +
756 res.p4 *
pow(half_width, 4) +
res.p5 *
pow(half_width, 5);
758 double f1_zerowidth =
res.p0;
761 res.tan_LA = (f1_halfwidth - f1_zerowidth) / half_width;
763 (
pow(
res.e1, 2) +
pow((half_width *
res.e2), 2) +
pow((half_width * half_width *
res.e3), 2) +
764 pow((half_width * half_width * half_width *
res.e4), 2) +
765 pow((half_width * half_width * half_width * half_width *
res.e5), 2));
786 LogDebug(
"SiPixelLorentzAnglePCLHarvester")
787 <<
" isNew: " << isNew <<
" i_index: " << i_index <<
" shift index: " << shiftIdx;
789 const auto& detIdsToFill =
792 LogDebug(
"SiPixelLorentzAnglePCLHarvester")
793 <<
"index: " << i_index <<
" i_module: " << i_module <<
" i_layer: " << i_layer;
794 for (
const auto&
id : detIdsToFill) {
795 LogDebug(
"SiPixelLorentzAnglePCLHarvester") <<
id <<
",";
804 float LorentzAnglePerTesla_;
809 for (
unsigned int i_bin = 0; i_bin <
res.quality.size(); i_bin++) {
810 if (
res.quality[i_bin]) {
825 const auto& deltaLA = (LorentzAnglePerTesla_ - currentLA);
828 for (
const auto&
id : detIdsToFill) {
829 if (!theLAPayload->putLorentzAngle(
id, LorentzAnglePerTesla_)) {
830 edm::LogError(
"SiPixelLorentzAnglePCLHarvester") <<
"[SiPixelLorentzAnglePCLHarvester::fitAndStore]: detid (" 831 << i_layer <<
"," << i_module <<
") already exists";
841 for (
const auto&
id : detIdsToFill) {
843 if (!theLAPayload->putLorentzAngle(
id, LorentzAnglePerTesla_)) {
844 edm::LogError(
"SiPixelLorentzAnglePCLHarvester") <<
"[SiPixelLorentzAnglePCLHarvester::fitAndStore]: detid (" 845 << i_layer <<
"," << i_module <<
") already exists";
856 const bool notZeroCut = (
res.redChi2 != 0.);
870 if (covMatrixStatusCut) {
878 return (
res.quality.all());
884 desc.setComment(
"Harvester module of the SiPixel Lorentz Angle PCL monitoring workflow");
885 desc.add<std::vector<std::string>>(
"newmodulelist", {})->setComment(
"the list of DetIds for new sensors");
886 desc.add<
std::string>(
"dqmDir",
"AlCaReco/SiPixelLorentzAngle")->setComment(
"the directory of PCL Worker output");
887 desc.add<
bool>(
"doChebyshevFit",
false)->setComment(
"use Chebyshev polynomials for the dript vs depth fit");
888 desc.add<
int>(
"order", 5)->setComment(
"order of the Chebyshev polynomial used for the fit");
889 desc.add<
double>(
"fitChi2Cut", 20.)->setComment(
"cut on fit chi2/ndof to accept measurement");
890 desc.add<std::vector<double>>(
"fitRange", {5., 280.})->setComment(
"range of depths to perform the LA fit");
891 desc.add<
int>(
"minHitsCut", 10000)->setComment(
"cut on minimum number of on-track hits to accept measurement");
892 desc.add<
std::string>(
"record",
"SiPixelLorentzAngleRcd")->setComment(
"target DB record");
std::vector< dqm::reco::MonitorElement * > h2_byLayerLA_
std::vector< int > BPixnewModule_
dqm::reco::MonitorElement * h_bySectSetLA_
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
dqm::reco::MonitorElement * h_bySectLA_
unsigned int pxbLayer(const DetId &id) const
dqm::reco::MonitorElement * h_bySectCovMatrixStatus_
Base exception class for the object to relational access.
virtual void setCurrentFolder(std::string const &fullpath)
const SiPixelLorentzAngle * currentLorentzAngle_
void beginRun(const edm::Run &, const edm::EventSetup &) override
std::vector< int > nLadders_
std::vector< std::string > FPixnewmodulename_
#define DEFINE_FWK_MODULE(type)
int bladeName() const
blade id
edm::ESGetToken< TrackerTopology, TrackerTopologyRcd > topoEsTokenBR_
int moduleName() const
module id (index in z)
void findMean(MonitorElement *h_drift_depth_adc_slice_, int i, int i_ring)
SiPixelLorentzAnglePCLHarvester(const edm::ParameterSet &)
SiPixelLAHarvest::fitResults fitAndStore(std::shared_ptr< SiPixelLorentzAngle > theLA, int i_idx, int i_lay, int i_mod)
edm::ESGetToken< TrackerTopology, TrackerTopologyRcd > topoEsTokenER_
const std::string dqmDir_
const std::map< unsigned int, float > & getLorentzAngles() const
std::vector< int > nModules_
Log< level::Error, false > LogError
MonitorMap h_drift_depth_
static void fillDescriptions(edm::ConfigurationDescriptions &)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
std::unique_ptr< TF1 > f1_
std::unique_ptr< TrackerTopology > theTrackerTopology_
std::vector< int > FPixnewDetIds_
std::vector< unsigned int > BPixnewDetIds_
constexpr std::array< uint8_t, layerIndexSize > layer
float inverseBzAtOriginInGeV() const
The inverse of field z component for this map in GeV.
dqm::reco::MonitorElement * h_bySectFitQuality_
MonitorMap h_drift_depth_noadc_
virtual float thickness() const =0
~SiPixelLorentzAnglePCLHarvester() override=default
virtual void Reset()
Remove all data from the ME, keept the empty histogram with all its settings.
dqm::reco::MonitorElement * h_bySectChi2_
edm::ESGetToken< SiPixelLorentzAngle, SiPixelLorentzAngleRcd > siPixelLAEsToken_
dqm::reco::MonitorElement * h_bySectDriftError_
dqm::reco::MonitorElement * h_bySectFitStatus_
virtual double getRMS(int axis=1) const
get RMS of histogram along x, y or z axis (axis=1, 2, 3 respectively)
static constexpr float teslaToInverseGeV_
Container::value_type value_type
cond::Time_t currentTime() const
int diskName() const
disk id
static constexpr float cmToum
std::unordered_map< uint32_t, std::vector< uint32_t > > detIdsList
const std::vector< double > fitRange_
edm::ESGetToken< TrackerGeometry, TrackerDigiGeometryRecord > geomEsToken_
Hash writeOneIOV(const T &payload, Time_t time, const std::string &recordName)
dqm::reco::MonitorElement * h_bySectOccupancy_
bool getData(T &iHolder) const
virtual void setBinLabel(int bin, const std::string &label, int axis=1)
set bin label for x, y or z axis (axis=1, 2, 3 respectively)
DetId geographicalId() const
The label of this GeomDet.
Log< level::Warning, true > LogPrint
SiPixelLorentzAngleCalibrationHistograms hists_
PXFDetId getDetId()
return DetId
Log< level::Info, false > LogInfo
const Plane & surface() const
The nominal surface of the GeomDet.
const bool doChebyshevFit_
const std::string recordName_
virtual void setBinContent(int binx, double content)
set content of bin (1-D)
constexpr uint32_t rawId() const
get the raw id
dqm::reco::MonitorElement * h_bySectMeasLA_
int layerName() const
layer id
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
MonitorMap h_drift_depth_adc_
virtual MonitorElement * get(std::string const &fullpath) const
std::vector< int > FPixnewBlade_
MonitorMap h_drift_depth_adc2_
virtual double getMean(int axis=1) const
get mean value of histogram along x, y or z axis (axis=1, 2, 3 respectively)
virtual int getNbinsX() const
get # of bins in X-axis
std::vector< std::string > BPixnewmodulename_
dqm::reco::MonitorElement * h_bySectRejectLA_
virtual void setBinError(int binx, double error)
set uncertainty on content of bin (1-D)
dqm::reco::MonitorElement * h_bySectDeltaLA_
std::vector< int > FPixnewDisk_
std::vector< int > BPixnewLayer_
unsigned int pxbModule(const DetId &id) const
std::pair< double, double > theFitRange_
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
char const * what() const noexcept override
float getLorentzAngle(const uint32_t &) const
edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > magneticFieldToken_
PXBDetId getDetId()
return the DetId
std::vector< dqm::reco::MonitorElement * > h2_byLayerDiff_
std::vector< std::string > newmodulelist_
bool isFitGood(SiPixelLAHarvest::fitResults &res)
Power< A, B >::type pow(const A &a, const B &b)
void endRun(const edm::Run &, const edm::EventSetup &) override
void dqmEndJob(DQMStore::IBooker &, DQMStore::IGetter &) override
void setQualityCutBit(const SiPixelLAHarvest::cuts &cut)
virtual double getBinContent(int binx) const
get content of bin (1-D)
const Bounds & bounds() const