/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Alignment/APEEstimation/plugins/ApeEstimatorSummary.cc
1 103 строки
47 KB
mteroerd
Bug fixes
11 авг 2021, 10:29
11 авг 2021, 10:29
eb9c7bd
Код
Авторство
О чём код?
// -*- C++ -*- // // Package: ApeEstimatorSummary // Class: ApeEstimatorSummary // /**\class ApeEstimatorSummary ApeEstimatorSummary.cc Alignment/APEEstimation/src/ApeEstimatorSummary.cc Description: [one line class summary] Implementation: [Notes on implementation] */ // // Original Author: Johannes Hauk,6 2-039,+41227673512, // Created: Mon Oct 11 13:44:03 CEST 2010 // Modified by: Christian Schomakers (RWTH Aachen) // $Id: ApeEstimatorSummary.cc,v 1.14 2012/01/26 00:06:33 hauk Exp $ // // // system include files #include <memory> #include <fstream> #include <sstream> // user include files #include "FWCore/Framework/interface/Frameworkfwd.h" #include "FWCore/Framework/interface/one/EDAnalyzer.h" #include "FWCore/Framework/interface/EventSetup.h" #include "FWCore/Framework/interface/Event.h" #include "FWCore/Framework/interface/MakerMacros.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "FWCore/Utilities/interface/EDMException.h" #include "FWCore/Utilities/interface/isFinite.h" #include "CLHEP/Matrix/SymMatrix.h" //#include "CondFormats/AlignmentRecord/interface/TrackerAlignmentRcd.h" #include "CondFormats/AlignmentRecord/interface/TrackerAlignmentErrorExtendedRcd.h" #include "CondFormats/Alignment/interface/AlignmentErrorsExtended.h" //............... #include "Alignment/APEEstimation/interface/TrackerSectorStruct.h" #include "TH1.h" #include "TString.h" #include "TFile.h" #include "TDirectory.h" #include "TTree.h" #include "TF1.h" #include "TMath.h" // // class declaration // class ApeEstimatorSummary : public edm::one::EDAnalyzer<> { public: explicit ApeEstimatorSummary(const edm::ParameterSet&); ~ApeEstimatorSummary() override; private: void beginJob() override; void analyze(const edm::Event&, const edm::EventSetup&) override; void endJob() override; void openInputFile(); void getTrackerSectorStructs(); void bookHists(); std::vector<double> residualErrorBinning(); void writeHists(); void calculateApe(); enum ApeWeight { wInvalid, wUnity, wEntries, wEntriesOverSigmaX2 }; // ----------member data --------------------------- const edm::ParameterSet parameterSet_; const edm::ESGetToken<AlignmentErrorsExtended, TrackerAlignmentErrorExtendedRcd> alignmentErrorToken_; bool firstEvent = true; TFile* inputFile_; std::map<unsigned int, TrackerSectorStruct> m_tkSector_; unsigned int noSectors_; }; // // constants, enums and typedefs // // // static data member definitions // // // constructors and destructor // ApeEstimatorSummary::ApeEstimatorSummary(const edm::ParameterSet& iConfig) : parameterSet_(iConfig), alignmentErrorToken_(esConsumes()), inputFile_(nullptr) {} ApeEstimatorSummary::~ApeEstimatorSummary() {} // // member functions // void ApeEstimatorSummary::openInputFile() { const std::string inputFileName(parameterSet_.getParameter<std::string>("InputFile")); std::ifstream inputFileStream; // Check if baseline file exists inputFileStream.open(inputFileName.c_str()); if (inputFileStream.is_open()) { inputFile_ = new TFile(inputFileName.c_str(), "READ"); } if (inputFile_) { edm::LogInfo("CalculateAPE") << "Input file from loop over tracks and corresponding hits sucessfully opened"; } else { edm::LogError("CalculateAPE") << "There is NO input file\n" << "...APE calculation stopped. Please check path of input file name in config:\n" << "\t" << inputFileName; throw edm::Exception(edm::errors::Configuration, "Bad input file name"); } } void ApeEstimatorSummary::getTrackerSectorStructs() { // At present first of the plugins registered in TFileService needs to be the one containing the normalized residual histos per sector per error bin TString pluginName(inputFile_->GetListOfKeys()->At(0)->GetName()); pluginName += "/"; TDirectory *sectorDir(nullptr), *intervalDir(nullptr); bool sectorBool(true); unsigned int iSector(1); for (; sectorBool; ++iSector) { std::stringstream sectorName, fullSectorName; sectorName << "Sector_" << iSector << "/"; fullSectorName << pluginName << sectorName.str(); TString fullName(fullSectorName.str().c_str()); inputFile_->cd(); sectorDir = (TDirectory*)inputFile_->TDirectory::GetDirectory(fullName); if (sectorDir) { TrackerSectorStruct tkSector; sectorDir->GetObject("z_name;1", tkSector.Name); tkSector.name = tkSector.Name->GetTitle(); bool intervalBool(true); for (unsigned int iInterval(1); intervalBool; ++iInterval) { std::stringstream intervalName, fullIntervalName; intervalName << "Interval_" << iInterval << "/"; fullIntervalName << fullSectorName.str() << intervalName.str(); fullName = fullIntervalName.str().c_str(); intervalDir = (TDirectory*)inputFile_->TDirectory::GetDirectory(fullName); if (intervalDir) { intervalDir->GetObject("h_sigmaX;1", tkSector.m_binnedHists[iInterval]["sigmaX"]); intervalDir->GetObject("h_norResX;1", tkSector.m_binnedHists[iInterval]["norResX"]); intervalDir->GetObject("h_sigmaY;1", tkSector.m_binnedHists[iInterval]["sigmaY"]); intervalDir->GetObject("h_norResY;1", tkSector.m_binnedHists[iInterval]["norResY"]); if (tkSector.m_binnedHists[iInterval]["sigmaY"] && tkSector.m_binnedHists[iInterval]["norResY"]) { tkSector.isPixel = true; } } else { intervalBool = false; if (iSector == 1) edm::LogInfo("CalculateAPE") << "There are " << iInterval - 1 << " intervals per sector defined in input file"; } } TDirectory* resultsDir(nullptr); std::stringstream fullResultName; fullResultName << fullSectorName.str() << "Results/"; fullName = fullResultName.str().c_str(); resultsDir = (TDirectory*)inputFile_->TDirectory::GetDirectory(fullName); if (resultsDir) { resultsDir->GetObject("h_entriesX;1", tkSector.EntriesX); if (tkSector.isPixel) resultsDir->GetObject("h_entriesY;1", tkSector.EntriesY); TTree* rawIdTree(nullptr); resultsDir->GetObject("rawIdTree", rawIdTree); unsigned int rawId(0); rawIdTree->SetBranchAddress("RawId", &rawId); for (int entry = 0; entry < rawIdTree->GetEntries(); ++entry) { rawIdTree->GetEntry(entry); // command "hadd" adds entries in TTree, so rawId are existing as often as number of files are added bool alreadyAdded(false); for (auto const& i_rawId : tkSector.v_rawId) { if (rawId == i_rawId) alreadyAdded = true; } if (alreadyAdded) break; tkSector.v_rawId.push_back(rawId); } } m_tkSector_[iSector] = tkSector; } else { sectorBool = false; edm::LogInfo("CalculateAPE") << "There are " << iSector - 1 << " sectors defined in input file"; } } noSectors_ = iSector + 1; } void ApeEstimatorSummary::bookHists() { const std::vector<double> v_binX(this->residualErrorBinning()); for (auto& i_sector : m_tkSector_) { i_sector.second.WeightX = new TH1F("h_weightX", "relative weight w_{x}/w_{tot,x};#sigma_{x} [#mum];w_{x}/w_{tot,x}", v_binX.size() - 1, &(v_binX[0])); i_sector.second.MeanX = new TH1F("h_meanX", "residual mean <r_{x}/#sigma_{r,x}>;#sigma_{x} [#mum];<r_{x}/#sigma_{r,x}>", v_binX.size() - 1, &(v_binX[0])); i_sector.second.RmsX = new TH1F("h_rmsX", "residual rms RMS(r_{x}/#sigma_{r,x});#sigma_{x} [#mum];RMS(r_{x}/#sigma_{r,x})", v_binX.size() - 1, &(v_binX[0])); i_sector.second.FitMeanX1 = new TH1F( "h_fitMeanX1", "fitted residual mean #mu_{x};#sigma_{x} [#mum];#mu_{x}", v_binX.size() - 1, &(v_binX[0])); i_sector.second.ResidualWidthX1 = new TH1F("h_residualWidthX1", "residual width #Delta_{x};#sigma_{x} [#mum];#Delta_{x}", v_binX.size() - 1, &(v_binX[0])); i_sector.second.CorrectionX1 = new TH1F("h_correctionX1", "correction to APE_{x};#sigma_{x} [#mum];#Delta#sigma_{align,x} [#mum]", v_binX.size() - 1, &(v_binX[0])); i_sector.second.FitMeanX2 = new TH1F( "h_fitMeanX2", "fitted residual mean #mu_{x};#sigma_{x} [#mum];#mu_{x}", v_binX.size() - 1, &(v_binX[0])); i_sector.second.ResidualWidthX2 = new TH1F("h_residualWidthX2", "residual width #Delta_{x};#sigma_{x} [#mum];#Delta_{x}", v_binX.size() - 1, &(v_binX[0])); i_sector.second.CorrectionX2 = new TH1F("h_correctionX2", "correction to APE_{x};#sigma_{x} [#mum];#Delta#sigma_{align,x} [#mum]", v_binX.size() - 1, &(v_binX[0])); if (i_sector.second.isPixel) { i_sector.second.WeightY = new TH1F("h_weightY", "relative weight w_{y}/w_{tot,y};#sigma_{y} [#mum];w_{y}/w_{tot,y}", v_binX.size() - 1, &(v_binX[0])); i_sector.second.MeanY = new TH1F("h_meanY", "residual mean <r_{y}/#sigma_{r,y}>;#sigma_{y} [#mum];<r_{y}/#sigma_{r,y}>", v_binX.size() - 1, &(v_binX[0])); i_sector.second.RmsY = new TH1F("h_rmsY", "residual rms RMS(r_{y}/#sigma_{r,y});#sigma_{y} [#mum];RMS(r_{y}/#sigma_{r,y})", v_binX.size() - 1, &(v_binX[0])); i_sector.second.FitMeanY1 = new TH1F( "h_fitMeanY1", "fitted residual mean #mu_{y};#sigma_{y} [#mum];#mu_{y}", v_binX.size() - 1, &(v_binX[0])); i_sector.second.ResidualWidthY1 = new TH1F("h_residualWidthY1", "residual width #Delta_{y};#sigma_{y} [#mum];#Delta_{y}", v_binX.size() - 1, &(v_binX[0])); i_sector.second.CorrectionY1 = new TH1F("h_correctionY1", "correction to APE_{y};#sigma_{y} [#mum];#Delta#sigma_{align,y} [#mum]", v_binX.size() - 1, &(v_binX[0])); i_sector.second.FitMeanY2 = new TH1F( "h_fitMeanY2", "fitted residual mean #mu_{y};#sigma_{y} [#mum];#mu_{y}", v_binX.size() - 1, &(v_binX[0])); i_sector.second.ResidualWidthY2 = new TH1F("h_residualWidthY2", "residual width #Delta_{y};#sigma_{y} [#mum];#Delta_{y}", v_binX.size() - 1, &(v_binX[0])); i_sector.second.CorrectionY2 = new TH1F("h_correctionY2", "correction to APE_{y};#sigma_{y} [#mum];#Delta#sigma_{align,y} [#mum]", v_binX.size() - 1, &(v_binX[0])); } } } std::vector<double> ApeEstimatorSummary::residualErrorBinning() { std::vector<double> v_binX; TH1* EntriesX(m_tkSector_[1].EntriesX); for (int iBin = 1; iBin <= EntriesX->GetNbinsX() + 1; ++iBin) { v_binX.push_back(EntriesX->GetBinLowEdge(iBin)); } return v_binX; } void ApeEstimatorSummary::writeHists() { TFile* resultsFile = new TFile(parameterSet_.getParameter<std::string>("ResultsFile").c_str(), "RECREATE"); TDirectory* baseDir = resultsFile->mkdir("ApeEstimatorSummary"); for (auto const& i_sector : m_tkSector_) { std::stringstream dirName; dirName << "Sector_" << i_sector.first; TDirectory* dir = baseDir->mkdir(dirName.str().c_str()); dir->cd(); i_sector.second.Name->Write(); i_sector.second.WeightX->Write(); i_sector.second.MeanX->Write(); i_sector.second.RmsX->Write(); i_sector.second.FitMeanX1->Write(); i_sector.second.ResidualWidthX1->Write(); i_sector.second.CorrectionX1->Write(); i_sector.second.FitMeanX2->Write(); i_sector.second.ResidualWidthX2->Write(); i_sector.second.CorrectionX2->Write(); if (i_sector.second.isPixel) { i_sector.second.WeightY->Write(); i_sector.second.MeanY->Write(); i_sector.second.RmsY->Write(); i_sector.second.FitMeanY1->Write(); i_sector.second.ResidualWidthY1->Write(); i_sector.second.CorrectionY1->Write(); i_sector.second.FitMeanY2->Write(); i_sector.second.ResidualWidthY2->Write(); i_sector.second.CorrectionY2->Write(); } } resultsFile->Close(); } void ApeEstimatorSummary::calculateApe() { // Set baseline or calculate APE value? const bool setBaseline(parameterSet_.getParameter<bool>("setBaseline")); // Read in baseline file for calculation of APE value (if not setting baseline) // Has same format as iterationFile const std::string baselineFileName(parameterSet_.getParameter<std::string>("BaselineFile")); TFile* baselineFile(nullptr); TTree* baselineTreeX(nullptr); TTree* baselineTreeY(nullptr); TTree* sectorNameBaselineTree(nullptr); if (!setBaseline) { std::ifstream baselineFileStream; // Check if baseline file exists baselineFileStream.open(baselineFileName.c_str()); if (baselineFileStream.is_open()) { baselineFileStream.close(); baselineFile = new TFile(baselineFileName.c_str(), "READ"); } if (baselineFile) { edm::LogInfo("CalculateAPE") << "Baseline file for APE values sucessfully opened"; baselineFile->GetObject("iterTreeX;1", baselineTreeX); baselineFile->GetObject("iterTreeY;1", baselineTreeY); baselineFile->GetObject("nameTree;1", sectorNameBaselineTree); } else { edm::LogWarning("CalculateAPE") << "There is NO baseline file for APE values, so normalized residual width =1 " "for ideal conditions is assumed"; } } // Set up root file for iterations on APE value (or for setting baseline in setBaseline mode) const std::string iterationFileName(setBaseline ? baselineFileName : parameterSet_.getParameter<std::string>("IterationFile")); // For iterations, updates are needed to not overwrite the iterations before TFile* iterationFile = new TFile(iterationFileName.c_str(), setBaseline ? "RECREATE" : "UPDATE"); // Set up TTree for iterative APE values on first pass (first iteration) or read from file (further iterations) TTree* iterationTreeX(nullptr); TTree* iterationTreeY(nullptr); iterationFile->GetObject("iterTreeX;1", iterationTreeX); iterationFile->GetObject("iterTreeY;1", iterationTreeY); // The same for TTree containing the names of the sectors (no additional check, since always handled exactly as iterationTree) TTree* sectorNameTree(nullptr); iterationFile->GetObject("nameTree;1", sectorNameTree); const bool firstIter(!iterationTreeX); if (firstIter) { // should be always true in setBaseline mode, since file is recreated if (!setBaseline) { iterationTreeX = new TTree("iterTreeX", "Tree for APE x values of all iterations"); iterationTreeY = new TTree("iterTreeY", "Tree for APE y values of all iterations"); edm::LogInfo("CalculateAPE") << "First APE iteration (number 0.), create iteration file with TTree"; sectorNameTree = new TTree("nameTree", "Tree with names of sectors"); } else { iterationTreeX = new TTree("iterTreeX", "Tree for baseline x values of normalized residual width"); iterationTreeY = new TTree("iterTreeY", "Tree for baseline y values of normalized residual width"); edm::LogInfo("CalculateAPE") << "Set baseline, create baseline file with TTree"; sectorNameTree = new TTree("nameTree", "Tree with names of sectors"); } } else { const unsigned int iteration(iterationTreeX->GetEntries()); edm::LogWarning("CalculateAPE") << "NOT the first APE iteration (number 0.) but the " << iteration << ". one, is this wanted or forgot to delete old iteration file with TTree?"; } // Assign the information stored in the trees to arrays double a_apeSectorX[noSectors_]; double a_apeSectorY[noSectors_]; double a_baselineSectorX[noSectors_]; double a_baselineSectorY[noSectors_]; std::string* a_sectorName[noSectors_]; std::string* a_sectorBaselineName[noSectors_]; for (auto const& i_sector : m_tkSector_) { const unsigned int iSector(i_sector.first); const bool pixelSector(i_sector.second.isPixel); a_apeSectorX[iSector] = 99.; a_apeSectorY[iSector] = 99.; a_baselineSectorX[iSector] = -99.; a_baselineSectorY[iSector] = -99.; a_sectorName[iSector] = nullptr; a_sectorBaselineName[iSector] = nullptr; std::stringstream ss_sector, ss_sectorSuffixed; ss_sector << "Ape_Sector_" << iSector; if (!setBaseline && baselineTreeX) { baselineTreeX->SetBranchAddress(ss_sector.str().c_str(), &a_baselineSectorX[iSector]); baselineTreeX->GetEntry(0); if (pixelSector) { baselineTreeY->SetBranchAddress(ss_sector.str().c_str(), &a_baselineSectorY[iSector]); baselineTreeY->GetEntry(0); } sectorNameBaselineTree->SetBranchAddress(ss_sector.str().c_str(), &a_sectorBaselineName[iSector]); sectorNameBaselineTree->GetEntry(0); } else { // Set default ideal normalized residual width to 1 a_baselineSectorX[iSector] = 1.; a_baselineSectorY[iSector] = 1.; } if (firstIter) { // should be always true in setBaseline mode, since file is recreated ss_sectorSuffixed << ss_sector.str() << "/D"; iterationTreeX->Branch(ss_sector.str().c_str(), &a_apeSectorX[iSector], ss_sectorSuffixed.str().c_str()); if (pixelSector) { iterationTreeY->Branch(ss_sector.str().c_str(), &a_apeSectorY[iSector], ss_sectorSuffixed.str().c_str()); } sectorNameTree->Branch(ss_sector.str().c_str(), &a_sectorName[iSector], 32000, 00); } else { iterationTreeX->SetBranchAddress(ss_sector.str().c_str(), &a_apeSectorX[iSector]); iterationTreeX->GetEntry(iterationTreeX->GetEntries() - 1); if (pixelSector) { iterationTreeY->SetBranchAddress(ss_sector.str().c_str(), &a_apeSectorY[iSector]); iterationTreeY->GetEntry(iterationTreeY->GetEntries() - 1); } sectorNameTree->SetBranchAddress(ss_sector.str().c_str(), &a_sectorName[iSector]); sectorNameTree->GetEntry(0); } } // Check whether sector definitions are identical with the ones of previous iterations and with the ones in baseline file bool failed(false); for (auto& i_sector : m_tkSector_) { const std::string& name(i_sector.second.name); if (firstIter) { a_sectorName[i_sector.first] = new std::string(name); } else { const std::string& nameLastIter(*a_sectorName[i_sector.first]); if (name != nameLastIter) { edm::LogError("CalculateAPE") << "Inconsistent sector definition in iterationFile for sector " << i_sector.first << ",\n" << "Recent iteration has name \"" << name << "\", while previous had \"" << nameLastIter << "\"\n" << "...APE calculation stopped. Please check sector definitions in config!\n"; failed = true; } } if (!setBaseline && baselineFile) { const std::string& nameBaseline(*a_sectorBaselineName[i_sector.first]); if (name != nameBaseline) { failed = true; edm::LogError("CalculateAPE") << "Inconsistent sector definition in baselineFile for sector " << i_sector.first << ",\n" << "Recent iteration has name \"" << name << "\", while baseline had \"" << nameBaseline << "\"\n" << "...APE calculation stopped. Please check sector definitions in config!\n"; } } } if (failed) { if (firstIter) { for (auto& i_sector : m_tkSector_) { delete a_sectorName[i_sector.first]; } } return; } // Set up text file for writing out APE values per module std::ofstream apeOutputFile; if (!setBaseline) { const std::string apeOutputFileName(parameterSet_.getParameter<std::string>("ApeOutputFile")); apeOutputFile.open(apeOutputFileName.c_str()); if (apeOutputFile.is_open()) { edm::LogInfo("CalculateAPE") << "Text file for writing APE values successfully opened"; } else { edm::LogError("CalculateAPE") << "Text file for writing APE values NOT opened,\n" << "...APE calculation stopped. Please check path of text file name in config:\n" << "\t" << apeOutputFileName; return; } } // Loop over sectors for calculating APE const std::string apeWeightName(parameterSet_.getParameter<std::string>("apeWeight")); ApeWeight apeWeight(wInvalid); if (apeWeightName == "unity") apeWeight = wUnity; else if (apeWeightName == "entries") apeWeight = wEntries; else if (apeWeightName == "entriesOverSigmaX2") apeWeight = wEntriesOverSigmaX2; if (apeWeight == wInvalid) { edm::LogError("CalculateAPE") << "Invalid parameter 'apeWeight' in cfg file: \"" << apeWeightName << "\"\nimplemented apeWeights are \"unity\", \"entries\", \"entriesOverSigmaX2\"" << "\n...APE calculation stopped."; return; } const double minHitsPerInterval(parameterSet_.getParameter<double>("minHitsPerInterval")); const double sigmaFactorFit(parameterSet_.getParameter<double>("sigmaFactorFit")); const double correctionScaling(parameterSet_.getParameter<double>("correctionScaling")); const bool smoothIteration(parameterSet_.getParameter<bool>("smoothIteration")); const double smoothFraction(parameterSet_.getParameter<double>("smoothFraction")); if (smoothFraction <= 0. || smoothFraction > 1.) { edm::LogError("CalculateAPE") << "Incorrect parameter in cfg file," << "\nsmoothFraction has to be in [0,1], but is " << smoothFraction << "\n...APE calculation stopped."; return; } for (auto& i_sector : m_tkSector_) { typedef std::pair<double, double> Error2AndResidualWidth2PerBin; typedef std::pair<double, Error2AndResidualWidth2PerBin> WeightAndResultsPerBin; std::vector<WeightAndResultsPerBin> v_weightAndResultsPerBinX; std::vector<WeightAndResultsPerBin> v_weightAndResultsPerBinY; double baselineWidthX2(a_baselineSectorX[i_sector.first]); double baselineWidthY2(a_baselineSectorY[i_sector.first]); // Loop over residual error bins to calculate APE for every bin for (auto const& i_errBins : i_sector.second.m_binnedHists) { std::map<std::string, TH1*> mHists = i_errBins.second; double entriesX = mHists["sigmaX"]->GetEntries(); double meanSigmaX = mHists["sigmaX"]->GetMean(); // Fitting Parameters double xMin = mHists["norResX"]->GetXaxis()->GetXmin(); double xMax = mHists["norResX"]->GetXaxis()->GetXmax(); double integralX = mHists["norResX"]->Integral(); double meanX = mHists["norResX"]->GetMean(); double rmsX = mHists["norResX"]->GetRMS(); double maximumX = mHists["norResX"]->GetBinContent(mHists["norResX"]->GetMaximumBin()); // First Gaus Fit TF1 funcX_1("mygausX", "gaus", xMin, xMax); funcX_1.SetParameters(maximumX, meanX, rmsX); TString fitOpt("ILERQ"); //TString fitOpt("IMR"); ("IRLL"); ("IRQ"); if (integralX > minHitsPerInterval) { if (mHists["norResX"]->Fit(&funcX_1, fitOpt)) { edm::LogWarning("CalculateAPE") << "Fit1 did not work: " << mHists["norResX"]->Fit(&funcX_1, fitOpt); continue; } LogDebug("CalculateAPE") << "FitResultX1\t" << mHists["norResX"]->Fit(&funcX_1, fitOpt) << "\n"; } double meanX_1 = funcX_1.GetParameter(1); double sigmaX_1 = funcX_1.GetParameter(2); // Second gaus fit TF1 funcX_2("mygausX2", "gaus", meanX_1 - sigmaFactorFit * TMath::Abs(sigmaX_1), meanX_1 + sigmaFactorFit * TMath::Abs(sigmaX_1)); funcX_2.SetParameters(funcX_1.GetParameter(0), meanX_1, sigmaX_1); if (integralX > minHitsPerInterval) { if (mHists["norResX"]->Fit(&funcX_2, fitOpt)) { edm::LogWarning("CalculateAPE") << "Fit2 did not work for x : " << mHists["norResX"]->Fit(&funcX_2, fitOpt); continue; } LogDebug("CalculateAPE") << "FitResultX2\t" << mHists["norResX"]->Fit(&funcX_2, fitOpt) << "\n"; } double meanX_2 = funcX_2.GetParameter(1); double sigmaX_2 = funcX_2.GetParameter(2); // Now the same for y coordinate double entriesY(0.); double meanSigmaY(0.); if (i_sector.second.isPixel) { entriesY = mHists["sigmaY"]->GetEntries(); meanSigmaY = mHists["sigmaY"]->GetMean(); } double meanY_1(0.); double sigmaY_1(0.); double meanY_2(0.); double sigmaY_2(0.); double meanY(0.); double rmsY(0.); if (i_sector.second.isPixel) { // Fitting Parameters double yMin = mHists["norResY"]->GetXaxis()->GetXmin(); double yMax = mHists["norResY"]->GetXaxis()->GetXmax(); double integralY = mHists["norResY"]->Integral(); meanY = mHists["norResY"]->GetMean(); rmsY = mHists["norResY"]->GetRMS(); double maximumY = mHists["norResY"]->GetBinContent(mHists["norResY"]->GetMaximumBin()); // First Gaus Fit TF1 funcY_1("mygausY", "gaus", yMin, yMax); funcY_1.SetParameters(maximumY, meanY, rmsY); if (integralY > minHitsPerInterval) { if (mHists["norResY"]->Fit(&funcY_1, fitOpt)) { edm::LogWarning("CalculateAPE") << "Fit1 did not work: " << mHists["norResY"]->Fit(&funcY_1, fitOpt); continue; } LogDebug("CalculateAPE") << "FitResultY1\t" << mHists["norResY"]->Fit(&funcY_1, fitOpt) << "\n"; } meanY_1 = funcY_1.GetParameter(1); sigmaY_1 = funcY_1.GetParameter(2); // Second gaus fit TF1 funcY_2("mygausY2", "gaus", meanY_1 - sigmaFactorFit * TMath::Abs(sigmaY_1), meanY_1 + sigmaFactorFit * TMath::Abs(sigmaY_1)); funcY_2.SetParameters(funcY_1.GetParameter(0), meanY_1, sigmaY_1); if (integralY > minHitsPerInterval) { if (mHists["norResY"]->Fit(&funcY_2, fitOpt)) { edm::LogWarning("CalculateAPE") << "Fit2 did not work for y : " << mHists["norResY"]->Fit(&funcY_2, fitOpt); continue; } LogDebug("CalculateAPE") << "FitResultY2\t" << mHists["norResY"]->Fit(&funcY_2, fitOpt) << "\n"; } meanY_2 = funcY_2.GetParameter(1); sigmaY_2 = funcY_2.GetParameter(2); } // Fill histograms double fitMeanX_1(meanX_1), fitMeanX_2(meanX_2); double residualWidthX_1(sigmaX_1), residualWidthX_2(sigmaX_2); double fitMeanY_1(meanY_1), fitMeanY_2(meanY_2); double residualWidthY_1(sigmaY_1), residualWidthY_2(sigmaY_2); double correctionX2_1(-0.0010), correctionX2_2(-0.0010); double correctionY2_1(-0.0010), correctionY2_2(-0.0010); correctionX2_1 = meanSigmaX * meanSigmaX * (residualWidthX_1 * residualWidthX_1 - baselineWidthX2); correctionX2_2 = meanSigmaX * meanSigmaX * (residualWidthX_2 * residualWidthX_2 - baselineWidthX2); if (i_sector.second.isPixel) { correctionY2_1 = meanSigmaY * meanSigmaY * (residualWidthY_1 * residualWidthY_1 - baselineWidthY2); correctionY2_2 = meanSigmaY * meanSigmaY * (residualWidthY_2 * residualWidthY_2 - baselineWidthY2); } double correctionX_1 = correctionX2_1 >= 0. ? std::sqrt(correctionX2_1) : -std::sqrt(-correctionX2_1); double correctionX_2 = correctionX2_2 >= 0. ? std::sqrt(correctionX2_2) : -std::sqrt(-correctionX2_2); double correctionY_1 = correctionY2_1 >= 0. ? std::sqrt(correctionY2_1) : -std::sqrt(-correctionY2_1); double correctionY_2 = correctionY2_2 >= 0. ? std::sqrt(correctionY2_2) : -std::sqrt(-correctionY2_2); // Meanwhile, this got very bad default values, or? (negative corrections allowed) if (edm::isNotFinite(correctionX_1)) correctionX_1 = -0.0010; if (edm::isNotFinite(correctionX_2)) correctionX_2 = -0.0010; if (edm::isNotFinite(correctionY_1)) correctionY_1 = -0.0010; if (edm::isNotFinite(correctionY_2)) correctionY_2 = -0.0010; if (entriesX < minHitsPerInterval) { meanX = 0.; rmsX = -0.0010; fitMeanX_1 = 0.; correctionX_1 = residualWidthX_1 = -0.0010; fitMeanX_2 = 0.; correctionX_2 = residualWidthX_2 = -0.0010; } if (entriesY < minHitsPerInterval) { meanY = 0.; rmsY = -0.0010; fitMeanY_1 = 0.; correctionY_1 = residualWidthY_1 = -0.0010; fitMeanY_2 = 0.; correctionY_2 = residualWidthY_2 = -0.0010; } i_sector.second.MeanX->SetBinContent(i_errBins.first, meanX); i_sector.second.RmsX->SetBinContent(i_errBins.first, rmsX); i_sector.second.FitMeanX1->SetBinContent(i_errBins.first, fitMeanX_1); i_sector.second.ResidualWidthX1->SetBinContent(i_errBins.first, residualWidthX_1); i_sector.second.CorrectionX1->SetBinContent(i_errBins.first, correctionX_1 * 10000.); i_sector.second.FitMeanX2->SetBinContent(i_errBins.first, fitMeanX_2); i_sector.second.ResidualWidthX2->SetBinContent(i_errBins.first, residualWidthX_2); i_sector.second.CorrectionX2->SetBinContent(i_errBins.first, correctionX_2 * 10000.); if (i_sector.second.isPixel) { i_sector.second.MeanY->SetBinContent(i_errBins.first, meanY); i_sector.second.RmsY->SetBinContent(i_errBins.first, rmsY); i_sector.second.FitMeanY1->SetBinContent(i_errBins.first, fitMeanY_1); i_sector.second.ResidualWidthY1->SetBinContent(i_errBins.first, residualWidthY_1); i_sector.second.CorrectionY1->SetBinContent(i_errBins.first, correctionY_1 * 10000.); i_sector.second.FitMeanY2->SetBinContent(i_errBins.first, fitMeanY_2); i_sector.second.ResidualWidthY2->SetBinContent(i_errBins.first, residualWidthY_2); i_sector.second.CorrectionY2->SetBinContent(i_errBins.first, correctionY_2 * 10000.); } // Use result for bin only when entries>=minHitsPerInterval if (entriesX < minHitsPerInterval && entriesY < minHitsPerInterval) continue; double weightX(0.); double weightY(0.); if (apeWeight == wUnity) { weightX = 1.; weightY = 1.; } else if (apeWeight == wEntries) { weightX = entriesX; weightY = entriesY; } else if (apeWeight == wEntriesOverSigmaX2) { weightX = entriesX / (meanSigmaX * meanSigmaX); weightY = entriesY / (meanSigmaY * meanSigmaY); } const Error2AndResidualWidth2PerBin error2AndResidualWidth2PerBinX(meanSigmaX * meanSigmaX, residualWidthX_1 * residualWidthX_1); const WeightAndResultsPerBin weightAndResultsPerBinX(weightX, error2AndResidualWidth2PerBinX); if (!(entriesX < minHitsPerInterval)) { //Fill absolute weights i_sector.second.WeightX->SetBinContent(i_errBins.first, weightX); v_weightAndResultsPerBinX.push_back(weightAndResultsPerBinX); } const Error2AndResidualWidth2PerBin error2AndResidualWidth2PerBinY(meanSigmaY * meanSigmaY, residualWidthY_1 * residualWidthY_1); const WeightAndResultsPerBin weightAndResultsPerBinY(weightY, error2AndResidualWidth2PerBinY); if (!(entriesY < minHitsPerInterval)) { //Fill absolute weights i_sector.second.WeightY->SetBinContent(i_errBins.first, weightY); v_weightAndResultsPerBinY.push_back(weightAndResultsPerBinY); } } // Do the final calculations if (v_weightAndResultsPerBinX.empty()) { edm::LogError("CalculateAPE") << "NO error interval of sector " << i_sector.first << " has a valid x APE calculated,\n...so cannot set APE"; continue; } if (i_sector.second.isPixel && v_weightAndResultsPerBinY.empty()) { edm::LogError("CalculateAPE") << "NO error interval of sector " << i_sector.first << " has a valid y APE calculated,\n...so cannot set APE"; continue; } double correctionX2(999.); double correctionY2(999.); // Get sum of all weights double weightSumX(0.); for (auto const& i_apeBin : v_weightAndResultsPerBinX) { weightSumX += i_apeBin.first; } i_sector.second.WeightX->Scale(1 / weightSumX); double weightSumY(0.); if (i_sector.second.isPixel) { for (auto const& i_apeBin : v_weightAndResultsPerBinY) { weightSumY += i_apeBin.first; } i_sector.second.WeightY->Scale(1 / weightSumY); } if (!setBaseline) { // Calculate weighted mean bool firstIntervalX(true); for (auto const& i_apeBin : v_weightAndResultsPerBinX) { if (firstIntervalX) { correctionX2 = i_apeBin.first * i_apeBin.second.first * (i_apeBin.second.second - baselineWidthX2); firstIntervalX = false; } else { correctionX2 += i_apeBin.first * i_apeBin.second.first * (i_apeBin.second.second - baselineWidthX2); } } correctionX2 = correctionX2 / weightSumX; } else { double numeratorX(0.), denominatorX(0.); for (auto const& i_apeBin : v_weightAndResultsPerBinX) { numeratorX += i_apeBin.first * i_apeBin.second.first * i_apeBin.second.second; denominatorX += i_apeBin.first * i_apeBin.second.first; } correctionX2 = numeratorX / denominatorX; } if (i_sector.second.isPixel) { if (!setBaseline) { // Calculate weighted mean bool firstIntervalY(true); for (auto const& i_apeBin : v_weightAndResultsPerBinY) { if (firstIntervalY) { correctionY2 = i_apeBin.first * i_apeBin.second.first * (i_apeBin.second.second - baselineWidthY2); firstIntervalY = false; } else { correctionY2 += i_apeBin.first * i_apeBin.second.first * (i_apeBin.second.second - baselineWidthY2); } } correctionY2 = correctionY2 / weightSumY; } else { double numeratorY(0.), denominatorY(0.); for (auto const& i_apeBin : v_weightAndResultsPerBinY) { numeratorY += i_apeBin.first * i_apeBin.second.first * i_apeBin.second.second; denominatorY += i_apeBin.first * i_apeBin.second.first; } correctionY2 = numeratorY / denominatorY; } } if (!setBaseline) { // Calculate updated squared APE of current iteration double apeX2(999.); double apeY2(999.); // old APE value from last iteration if (firstIter) { apeX2 = 0.; apeY2 = 0.; } else { apeX2 = a_apeSectorX[i_sector.first]; apeY2 = a_apeSectorY[i_sector.first]; } const double apeX2old = apeX2; const double apeY2old = apeY2; // scale APE Correction with value given in cfg (not if smoothed iteration is used) edm::LogInfo("CalculateAPE") << "Unscaled correction x for sector " << i_sector.first << " is " << (correctionX2 > 0. ? +1. : -1.) * std::sqrt(std::fabs(correctionX2)); if (!smoothIteration || firstIter) correctionX2 = correctionX2 * correctionScaling * correctionScaling; if (i_sector.second.isPixel) { edm::LogInfo("CalculateAPE") << "Unscaled correction y for sector " << i_sector.first << " is " << (correctionY2 > 0. ? +1. : -1.) * std::sqrt(std::fabs(correctionY2)); if (!smoothIteration || firstIter) correctionY2 = correctionY2 * correctionScaling * correctionScaling; } // new APE value // smooth iteration or not? if (apeX2 + correctionX2 < 0.) correctionX2 = -apeX2; if (apeY2 + correctionY2 < 0.) correctionY2 = -apeY2; const double apeX2new(apeX2old + correctionX2); const double apeY2new(apeY2old + correctionY2); if (!smoothIteration || firstIter) { apeX2 = apeX2new; apeY2 = apeY2new; } else { const double apeXtmp = smoothFraction * std::sqrt(apeX2new) + (1 - smoothFraction) * std::sqrt(apeX2old); const double apeYtmp = smoothFraction * std::sqrt(apeY2new) + (1 - smoothFraction) * std::sqrt(apeY2old); apeX2 = apeXtmp * apeXtmp; apeY2 = apeYtmp * apeYtmp; } if (apeX2 < 0. || apeY2 < 0.) edm::LogError("CalculateAPE") << "\n\n\tBad APE, but why???\n\n\n"; a_apeSectorX[i_sector.first] = apeX2; a_apeSectorY[i_sector.first] = apeY2; // Set the calculated APE spherical for all modules of strip sectors const double apeX(std::sqrt(apeX2)); const double apeY(std::sqrt(apeY2)); const double apeZ(std::sqrt(0.5 * (apeX2 + apeY2))); for (auto const& i_rawId : i_sector.second.v_rawId) { if (i_sector.second.isPixel) { apeOutputFile << i_rawId << " " << std::fixed << std::setprecision(5) << apeX << " " << apeY << " " << apeZ << "\n"; } else { apeOutputFile << i_rawId << " " << std::fixed << std::setprecision(5) << apeX << " " << apeX << " " << apeX << "\n"; } } } else { // In setBaseline mode, just fill estimated mean value of residual width a_apeSectorX[i_sector.first] = correctionX2; a_apeSectorY[i_sector.first] = correctionY2; } } if (!setBaseline) apeOutputFile.close(); iterationTreeX->Fill(); iterationTreeX->Write("iterTreeX", TObject::kOverwrite); // TObject::kOverwrite needed to not produce another iterTreeX;2 iterationTreeY->Fill(); iterationTreeY->Write("iterTreeY", TObject::kOverwrite); // TObject::kOverwrite needed to not produce another iterTreeY;2 if (firstIter) { sectorNameTree->Fill(); sectorNameTree->Write("nameTree"); for (auto& i_sector : m_tkSector_) { delete a_sectorName[i_sector.first]; } } iterationFile->Close(); delete iterationFile; if (baselineFile) { baselineFile->Close(); delete baselineFile; } } // ------------ method called to for each event ------------ void ApeEstimatorSummary::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) { // Load APEs from the GT and write them to root files similar to the ones from calculateAPE() if (firstEvent) { // Set baseline or calculate APE value? const bool setBaseline(parameterSet_.getParameter<bool>("setBaseline")); const AlignmentErrorsExtended* alignmentErrors = &iSetup.getData(alignmentErrorToken_); // Read in baseline file for calculation of APE value (if not setting baseline) // Has same format as iterationFile const std::string baselineFileName(parameterSet_.getParameter<std::string>("BaselineFile")); TFile* baselineFile(nullptr); TTree* sectorNameBaselineTree(nullptr); if (!setBaseline) { std::ifstream baselineFileStream; // Check if baseline file exists baselineFileStream.open(baselineFileName.c_str()); if (baselineFileStream.is_open()) { baselineFileStream.close(); baselineFile = new TFile(baselineFileName.c_str(), "READ"); } if (baselineFile) { edm::LogInfo("CalculateAPE") << "Baseline file for APE values sucessfully opened"; baselineFile->GetObject("nameTree;1", sectorNameBaselineTree); } else { edm::LogWarning("CalculateAPE") << "There is NO baseline file for APE values, so normalized residual width =1 " "for ideal conditions is assumed"; } } // Set up root file for default APE values const std::string defaultFileName(parameterSet_.getParameter<std::string>("DefaultFile")); TFile* defaultFile = new TFile(defaultFileName.c_str(), "RECREATE"); // Naming in the root files has to be iterTreeX to be consistent for the plotting tool TTree* defaultTreeX(nullptr); TTree* defaultTreeY(nullptr); defaultFile->GetObject("iterTreeX;1", defaultTreeX); defaultFile->GetObject("iterTreeY;1", defaultTreeY); // The same for TTree containing the names of the sectors (no additional check, since always handled exactly as defaultTree) TTree* sectorNameTree(nullptr); defaultFile->GetObject("nameTree;1", sectorNameTree); const bool firstIter(!defaultTreeX); if (firstIter) { // should be always true in setBaseline mode, since file is recreated defaultTreeX = new TTree("iterTreeX", "Tree for default APE x values from GT"); defaultTreeY = new TTree("iterTreeY", "Tree for default APE y values from GT"); edm::LogInfo("CalculateAPE") << "First APE iteration (number 0.), create default file with TTree"; sectorNameTree = new TTree("nameTree", "Tree with names of sectors"); } else { edm::LogWarning("CalculateAPE") << "NOT the first APE iteration (number 0.), is this wanted or forgot to delete " "old iteration file with TTree?"; } // Assign the information stored in the trees to arrays double a_defaultSectorX[noSectors_]; double a_defaultSectorY[noSectors_]; std::string* a_sectorName[noSectors_]; std::string* a_sectorBaselineName[noSectors_]; for (auto const& i_sector : m_tkSector_) { const unsigned int iSector(i_sector.first); const bool pixelSector(i_sector.second.isPixel); a_defaultSectorX[iSector] = -99.; a_defaultSectorY[iSector] = -99.; a_sectorName[iSector] = nullptr; a_sectorBaselineName[iSector] = nullptr; std::stringstream ss_sector, ss_sectorSuffixed; ss_sector << "Ape_Sector_" << iSector; if (!setBaseline && sectorNameBaselineTree) { sectorNameBaselineTree->SetBranchAddress(ss_sector.str().c_str(), &a_sectorBaselineName[iSector]); sectorNameBaselineTree->GetEntry(0); } if (firstIter) { // should be always true in setBaseline mode, since file is recreated ss_sectorSuffixed << ss_sector.str() << "/D"; defaultTreeX->Branch(ss_sector.str().c_str(), &a_defaultSectorX[iSector], ss_sectorSuffixed.str().c_str()); if (pixelSector) { defaultTreeY->Branch(ss_sector.str().c_str(), &a_defaultSectorY[iSector], ss_sectorSuffixed.str().c_str()); } sectorNameTree->Branch(ss_sector.str().c_str(), &a_sectorName[iSector], 32000, 00); } else { defaultTreeX->SetBranchAddress(ss_sector.str().c_str(), &a_defaultSectorX[iSector]); defaultTreeX->GetEntry(0); if (pixelSector) { defaultTreeY->SetBranchAddress(ss_sector.str().c_str(), &a_defaultSectorY[iSector]); defaultTreeY->GetEntry(0); } sectorNameTree->SetBranchAddress(ss_sector.str().c_str(), &a_sectorName[iSector]); sectorNameTree->GetEntry(0); } } // Check whether sector definitions are identical with the ones of previous iterations and with the ones in baseline file bool failed(false); for (auto& i_sector : m_tkSector_) { const std::string& name(i_sector.second.name); if (firstIter) { a_sectorName[i_sector.first] = new std::string(name); } else { const std::string& nameLastIter(*a_sectorName[i_sector.first]); if (name != nameLastIter) { edm::LogError("CalculateAPE") << "Inconsistent sector definition in iterationFile for sector " << i_sector.first << ",\n" << "Recent iteration has name \"" << name << "\", while previous had \"" << nameLastIter << "\"\n" << "...APE calculation stopped. Please check sector definitions in config!\n"; failed = true; } } if (!setBaseline && baselineFile) { const std::string& nameBaseline(*a_sectorBaselineName[i_sector.first]); if (name != nameBaseline) { edm::LogError("CalculateAPE") << "Inconsistent sector definition in baselineFile for sector " << i_sector.first << ",\n" << "Recent iteration has name \"" << name << "\", while baseline had \"" << nameBaseline << "\"\n" << "...APE calculation stopped. Please check sector definitions in config!\n"; failed = true; } } } if (failed) { if (firstIter) { delete defaultTreeX; delete defaultTreeY; delete sectorNameTree; for (auto& i_sector : m_tkSector_) { delete a_sectorName[i_sector.first]; } } return; } // Loop over sectors for calculating getting default APE for (auto& i_sector : m_tkSector_) { double defaultApeX(0.); double defaultApeY(0.); unsigned int nModules(0); for (auto const& i_rawId : i_sector.second.v_rawId) { std::vector<AlignTransformErrorExtended> alignErrors = alignmentErrors->m_alignError; for (std::vector<AlignTransformErrorExtended>::const_iterator i_alignError = alignErrors.begin(); i_alignError != alignErrors.end(); ++i_alignError) { if (i_rawId == i_alignError->rawId()) { CLHEP::HepSymMatrix errMatrix = i_alignError->matrix(); defaultApeX += errMatrix[0][0]; defaultApeY += errMatrix[1][1]; nModules++; } } } a_defaultSectorX[i_sector.first] = defaultApeX / nModules; a_defaultSectorY[i_sector.first] = defaultApeY / nModules; } sectorNameTree->Fill(); sectorNameTree->Write("nameTree"); defaultTreeX->Fill(); defaultTreeX->Write("iterTreeX"); defaultTreeY->Fill(); defaultTreeY->Write("iterTreeY"); defaultFile->Close(); if (baselineFile) { baselineFile->Close(); delete baselineFile; } delete defaultFile; if (firstIter) { for (auto& i_sector : m_tkSector_) { delete a_sectorName[i_sector.first]; } } firstEvent = false; } } // ------------ method called once each job just before starting event loop ------------ void ApeEstimatorSummary::beginJob() { this->openInputFile(); this->getTrackerSectorStructs(); this->bookHists(); } // ------------ method called once each job just after ending the event loop ------------ void ApeEstimatorSummary::endJob() { this->calculateApe(); this->writeHists(); } //define this as a plug-in DEFINE_FWK_MODULE(ApeEstimatorSummary);