diff --git a/.github/workflows/fix-eof-newline-coderabbit-docstrings.yml b/.github/workflows/fix-eof-newline-coderabbit-docstrings.yml new file mode 100644 index 0000000000..75d43e65e5 --- /dev/null +++ b/.github/workflows/fix-eof-newline-coderabbit-docstrings.yml @@ -0,0 +1,106 @@ +name: Fix missing final newline (CodeRabbit docstring PRs) + +on: + pull_request_target: + types: [opened, synchronize, reopened] + +permissions: + contents: write + pull-requests: read + +jobs: + fix_eof_newline: + runs-on: ubuntu-latest + steps: + - name: Guard - only CodeRabbit docstring PRs from same repo + id: guard + shell: bash + run: | + set -euo pipefail + + AUTHOR='${{ github.event.pull_request.user.login }}' + BASE_REPO='${{ github.event.pull_request.base.repo.full_name }}' + HEAD_REPO='${{ github.event.pull_request.head.repo.full_name }}' + TITLE='${{ github.event.pull_request.title }}' + + if [[ "$AUTHOR" != "coderabbitai[bot]" ]]; then + echo "run=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + # Safety: only push to branches within the same repo + if [[ "$BASE_REPO" != "$HEAD_REPO" ]]; then + echo "run=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + # only run for docstring PRs + if ! echo "$TITLE" | grep -qi "docstring"; then + echo "run=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "run=true" >> "$GITHUB_OUTPUT" + + - name: Checkout PR head + if: steps.guard.outputs.run == 'true' + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + repository: ${{ github.event.pull_request.head.repo.full_name }} + fetch-depth: 0 + + - name: Append final newline when missing (changed files only) + if: steps.guard.outputs.run == 'true' + shell: bash + run: | + set -euo pipefail + + BASE_SHA="${{ github.event.pull_request.base.sha }}" + HEAD_SHA="${{ github.event.pull_request.head.sha }}" + + files=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- \ + '*.C' '*.c' '*.cc' '*.cpp' '*.cxx' '*.h' '*.hh' '*.hpp' '*.hxx' || true) + + if [[ -z "${files}" ]]; then + echo "No relevant files changed." + exit 0 + fi + + changed=0 + for f in $files; do + [[ -f "$f" ]] || continue + + # For non-empty files: ensure last byte is '\n' + if [[ -s "$f" ]]; then + last_byte="$(tail -c 1 "$f" || true)" + if [[ "$last_byte" != $'\n' ]]; then + printf '\n' >> "$f" + echo "Fixed EOF newline: $f" + changed=1 + fi + fi + done + + if [[ "$changed" -eq 0 ]]; then + echo "All files already end with a newline." + exit 0 + fi + + git status --porcelain + git add -A + + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + git commit -m "Fix missing final newline in docstring PR" + + - name: Push fix commit back to PR branch + if: steps.guard.outputs.run == 'true' + shell: bash + run: | + set -euo pipefail + # If no commit was created, pushing will fail; so only push if HEAD is ahead. + if git rev-parse HEAD~1 >/dev/null 2>&1; then + git push origin "HEAD:${{ github.event.pull_request.head.ref }}" + fi diff --git a/calibrations/calorimeter/calo_cdb/CaloCDB-FilterDatasets.cc b/calibrations/calorimeter/calo_cdb/CaloCDB-FilterDatasets.cc index 8528cd26ae..56df96e205 100644 --- a/calibrations/calorimeter/calo_cdb/CaloCDB-FilterDatasets.cc +++ b/calibrations/calorimeter/calo_cdb/CaloCDB-FilterDatasets.cc @@ -1,6 +1,10 @@ -#include "filter-datasets.h" +#include "FilterDatasets.h" + +#include #include +#include +#include int main(int argc, const char* const argv[]) { @@ -17,7 +21,7 @@ int main(int argc, const char* const argv[]) const std::string& input_csv = args[1]; std::string output_dir_path = "."; - Bool_t debug = false; + bool debug = false; if (args.size() >= 3) { @@ -28,6 +32,9 @@ int main(int argc, const char* const argv[]) debug = std::stoi(args[3]); } + recoConsts* rc = recoConsts::instance(); + rc->set_StringFlag("CDB_GLOBALTAG", "newcdbtag"); + FilterDatasets filter(debug); filter.process(input_csv, output_dir_path); diff --git a/calibrations/calorimeter/calo_cdb/CaloCDB-GenStatus.cc b/calibrations/calorimeter/calo_cdb/CaloCDB-GenStatus.cc index 335563c295..49bf3e3c4f 100644 --- a/calibrations/calorimeter/calo_cdb/CaloCDB-GenStatus.cc +++ b/calibrations/calorimeter/calo_cdb/CaloCDB-GenStatus.cc @@ -1,6 +1,7 @@ -#include "genStatus.h" +#include "GenStatus.h" #include +#include #include int main(int argc, const char* const argv[]) diff --git a/calibrations/calorimeter/calo_cdb/filter-datasets.cc b/calibrations/calorimeter/calo_cdb/FilterDatasets.cc similarity index 90% rename from calibrations/calorimeter/calo_cdb/filter-datasets.cc rename to calibrations/calorimeter/calo_cdb/FilterDatasets.cc index 38ce957c4e..5ac745f0e8 100644 --- a/calibrations/calorimeter/calo_cdb/filter-datasets.cc +++ b/calibrations/calorimeter/calo_cdb/FilterDatasets.cc @@ -1,14 +1,18 @@ -#include "filter-datasets.h" +#include "FilterDatasets.h" // -- My Utils -- #include "myUtils.h" -// c++ includes -- +// sPHENIX includes -- +#include +#include + +#include #include #include -#include #include +#include FilterDatasets::FilterDatasets(Bool_t debug) : m_debug(debug) @@ -30,21 +34,12 @@ void FilterDatasets::readRunInfo(const std::string &line) std::string FilterDatasets::getCalibration(const std::string &pl_type, uint64_t iov) { - if (!uti) - { - uti = std::make_unique(); - } - return uti->getUrl(pl_type, iov); -} + recoConsts *rc = recoConsts::instance(); + // Update the global timestamp flag for the current run in the loop + rc->set_uint64Flag("TIMESTAMP", iov); -int FilterDatasets::setGlobalTag(const std::string &tagname) -{ - if (!uti) - { - uti = std::make_unique(); - } - int iret = uti->setGlobalTag(tagname); - return iret; + // Fetch the calibration URL via CDBInterface + return CDBInterface::instance()->getUrl(pl_type); } void FilterDatasets::analyze(const std::string &input, const std::string &outputDir) @@ -142,8 +137,6 @@ void FilterDatasets::process(const std::string &input, const std::string &output std::cout << "Debug: " << ((m_debug) ? "True" : "False") << std::endl; std::cout << "#############################" << std::endl; - setGlobalTag("newcdbtag"); - std::filesystem::path input_filepath_obj(input); if (!myUtils::readCSV(input_filepath_obj, [this](const std::string &line) { this->readRunInfo(line); })) diff --git a/calibrations/calorimeter/calo_cdb/filter-datasets.h b/calibrations/calorimeter/calo_cdb/FilterDatasets.h similarity index 75% rename from calibrations/calorimeter/calo_cdb/filter-datasets.h rename to calibrations/calorimeter/calo_cdb/FilterDatasets.h index c3af89f1de..c92485e75e 100644 --- a/calibrations/calorimeter/calo_cdb/filter-datasets.h +++ b/calibrations/calorimeter/calo_cdb/FilterDatasets.h @@ -1,23 +1,16 @@ #ifndef CALOCDB_FILTERDATASETS_H #define CALOCDB_FILTERDATASETS_H -// -- sPHENIX includes -- -#include - -// -- ROOT includes -- -#include - // -- c++ includes -- #include -#include +#include #include -#include #include class FilterDatasets { public: - explicit FilterDatasets(Bool_t debug = false); + explicit FilterDatasets(bool debug = false); void process(const std::string &input, const std::string &output = "."); @@ -26,7 +19,6 @@ class FilterDatasets void readRunInfo(const std::string &line); std::string getCalibration(const std::string &pl_type, uint64_t iov); - int setGlobalTag(const std::string &tagname); std::vector> m_runInfo; std::map m_ctr; @@ -36,9 +28,7 @@ class FilterDatasets , "CEMC_hotTowers_fracBadChi2", "HCALIN_hotTowers_fracBadChi2", "HCALOUT_hotTowers_fracBadChi2" , "CEMC_ZSCrossCalib", "HCALIN_ZSCrossCalib", "HCALOUT_ZSCrossCalib"}; - Bool_t m_debug; - - std::unique_ptr uti{nullptr}; + bool m_debug; }; #endif diff --git a/calibrations/calorimeter/calo_cdb/genStatus.cc b/calibrations/calorimeter/calo_cdb/GenStatus.cc similarity index 99% rename from calibrations/calorimeter/calo_cdb/genStatus.cc rename to calibrations/calorimeter/calo_cdb/GenStatus.cc index a49703127a..a5cdf538f6 100644 --- a/calibrations/calorimeter/calo_cdb/genStatus.cc +++ b/calibrations/calorimeter/calo_cdb/GenStatus.cc @@ -1,4 +1,4 @@ -#include "genStatus.h" +#include "GenStatus.h" #include "geometry_constants.h" @@ -15,7 +15,6 @@ // c++ includes -- #include #include -#include #include #include diff --git a/calibrations/calorimeter/calo_cdb/genStatus.h b/calibrations/calorimeter/calo_cdb/GenStatus.h similarity index 100% rename from calibrations/calorimeter/calo_cdb/genStatus.h rename to calibrations/calorimeter/calo_cdb/GenStatus.h diff --git a/calibrations/calorimeter/calo_cdb/Makefile.am b/calibrations/calorimeter/calo_cdb/Makefile.am index 9fbea67179..0107211521 100644 --- a/calibrations/calorimeter/calo_cdb/Makefile.am +++ b/calibrations/calorimeter/calo_cdb/Makefile.am @@ -15,18 +15,22 @@ AM_LDFLAGS = \ -L$(OFFLINE_MAIN)/lib64 \ `root-config --libs` +# Headers installed for use in macros and by other packages pkginclude_HEADERS = \ - genStatus.h \ - filter-datasets.h \ - geometry_constants.h \ + GenStatus.h \ + geometry_constants.h + +# Headers used only for building this library and its binaries +noinst_HEADERS = \ + FilterDatasets.h \ myUtils.h lib_LTLIBRARIES = \ libcalo_cdb.la libcalo_cdb_la_SOURCES = \ - genStatus.cc \ - filter-datasets.cc \ + GenStatus.cc \ + FilterDatasets.cc \ myUtils.cc libcalo_cdb_la_LIBADD = \ @@ -35,6 +39,7 @@ libcalo_cdb_la_LIBADD = \ -lcalo_io \ -lcdbobjects \ -lsphenixnpc \ + -lffamodules \ -lemcNoisyTowerFinder CaloCDB_GenStatus_SOURCES = CaloCDB-GenStatus.cc diff --git a/calibrations/calorimeter/calo_cdb/myUtils.cc b/calibrations/calorimeter/calo_cdb/myUtils.cc index 21a37ed595..3f495a4e7d 100644 --- a/calibrations/calorimeter/calo_cdb/myUtils.cc +++ b/calibrations/calorimeter/calo_cdb/myUtils.cc @@ -4,9 +4,12 @@ // root includes -- #include #include +#include +#include // c++ includes -- #include +#include TFitResultPtr myUtils::doGausFit(TH1 *hist, Double_t start, Double_t end, const std::string &name) { diff --git a/calibrations/calorimeter/calo_cdb/myUtils.h b/calibrations/calorimeter/calo_cdb/myUtils.h index 2799ab808f..a44d61984e 100644 --- a/calibrations/calorimeter/calo_cdb/myUtils.h +++ b/calibrations/calorimeter/calo_cdb/myUtils.h @@ -2,18 +2,19 @@ #define CALOCDB_MYUTILS_H // ROOT includes -- +#include #include -#include // -- c++ includes -- #include #include #include -#include #include #include #include +class TH1; + template concept InvocableWithString = std::invocable; @@ -39,7 +40,7 @@ class myUtils * @return true if the file was successfully opened and read, false otherwise. */ template // Using the more general concept for wider applicability - static Bool_t readCSV(const std::filesystem::path& filePath, Callable lineHandler, Bool_t skipHeader = true) + static bool readCSV(const std::filesystem::path& filePath, Callable lineHandler, bool skipHeader = true) { std::ifstream file(filePath); diff --git a/calibrations/framework/oncal/OnCal.cc b/calibrations/framework/fun4cal/CalReco.cc similarity index 75% rename from calibrations/framework/oncal/OnCal.cc rename to calibrations/framework/fun4cal/CalReco.cc index ae652adbc8..46ad141654 100644 --- a/calibrations/framework/oncal/OnCal.cc +++ b/calibrations/framework/fun4cal/CalReco.cc @@ -1,4 +1,4 @@ -#include "OnCal.h" +#include "CalReco.h" #include // for SubsysReco @@ -6,18 +6,18 @@ #include -OnCal::OnCal(const std::string &Name) +CalReco::CalReco(const std::string &Name) : SubsysReco(Name) { } -int OnCal::process_event(PHCompositeNode * /*topNode*/) +int CalReco::process_event(PHCompositeNode * /*topNode*/) { std::cout << "process_event(PHCompositeNode *topNode) not implemented by daughter class: " << Name() << std::endl; return -1; } -int OnCal::End(PHCompositeNode * /*topNode*/) +int CalReco::End(PHCompositeNode * /*topNode*/) { std::cout << "EndOfAnalysis not implemented by subsystem!" << std::endl; std::cout << "Use this signal for computing your calibrations and commit." << std::endl; @@ -26,7 +26,7 @@ int OnCal::End(PHCompositeNode * /*topNode*/) return 0; } -void OnCal::AddComment(const std::string &adcom) +void CalReco::AddComment(const std::string &adcom) { if (m_Comment.empty()) { @@ -40,7 +40,7 @@ void OnCal::AddComment(const std::string &adcom) return; } -int OnCal::CopyTables(const int /*FromRun*/, const int /*ToRun*/, const int /*commit*/) const +int CalReco::CopyTables(const int /*FromRun*/, const int /*ToRun*/, const int /*commit*/) const { std::cout << PHWHERE << " CopyTables not implemented" << std::endl << "this calibrator cannot copy its own tables" << std::endl; diff --git a/calibrations/framework/oncal/OnCal.h b/calibrations/framework/fun4cal/CalReco.h similarity index 90% rename from calibrations/framework/oncal/OnCal.h rename to calibrations/framework/fun4cal/CalReco.h index 454e240aaa..e2ba725884 100644 --- a/calibrations/framework/oncal/OnCal.h +++ b/calibrations/framework/fun4cal/CalReco.h @@ -1,5 +1,5 @@ -#ifndef ONCAL_ONCAL_H -#define ONCAL_ONCAL_H +#ifndef FUN4CAL_CALRECO_H +#define FUN4CAL_CALRECO_H #include #include @@ -7,10 +7,10 @@ #include // for pair #include -class OnCal : public SubsysReco +class CalReco : public SubsysReco { public: - ~OnCal() override = default; + ~CalReco() override = default; // These might be overwritten by everyone... int process_event(PHCompositeNode *topNode) override; @@ -47,7 +47,7 @@ class OnCal : public SubsysReco virtual std::vector GetLocalFileList() const { return localfilelist; } protected: - OnCal(const std::string &Name); // so noone can call it from outside + CalReco(const std::string &Name); // so noone can call it from outside unsigned int alldone{0}; std::string m_Comment; std::vector pdbcaltables; @@ -56,4 +56,4 @@ class OnCal : public SubsysReco std::vector localfilelist; }; -#endif /* ONCAL_ONCAL_H */ +#endif /* CALRECO_CALRECO_H */ diff --git a/calibrations/framework/oncal/OnCalDBCodes.h b/calibrations/framework/fun4cal/Fun4CalDBCodes.h similarity index 65% rename from calibrations/framework/oncal/OnCalDBCodes.h rename to calibrations/framework/fun4cal/Fun4CalDBCodes.h index 707c72f859..7964f6679c 100644 --- a/calibrations/framework/oncal/OnCalDBCodes.h +++ b/calibrations/framework/fun4cal/Fun4CalDBCodes.h @@ -1,7 +1,7 @@ -#ifndef ONCALDBCODES_H__ -#define ONCALDBCODES_H__ +#ifndef FUN4CAL_FUN4CALDBCODES_H +#define FUN4CAL_FUN4CALDBCODES_H -namespace OnCalDBCodes +namespace Fun4CalDBCodes { enum { diff --git a/calibrations/framework/fun4cal/Fun4CalHistoBinDefs.h b/calibrations/framework/fun4cal/Fun4CalHistoBinDefs.h new file mode 100644 index 0000000000..36c62bd3ec --- /dev/null +++ b/calibrations/framework/fun4cal/Fun4CalHistoBinDefs.h @@ -0,0 +1,16 @@ +#ifndef FUN4CAL_FUN4CALHISTOBINDEFS_H +#define FUN4CAL_FUN4CALHISTOBINDEFS_H + +namespace Fun4CalHistoBinDefs +{ + enum + { + FIRSTRUNBIN = 1, + LASTRUNBIN, + BORTIMEBIN, + EORTIMEBIN, + LASTBINPLUSONE + }; +}; + +#endif /* FUN4CAL_FUN4CALHISTOBINDEFS_H */ diff --git a/calibrations/framework/oncal/OnCalServer.cc b/calibrations/framework/fun4cal/Fun4CalServer.cc similarity index 90% rename from calibrations/framework/oncal/OnCalServer.cc rename to calibrations/framework/fun4cal/Fun4CalServer.cc index 5593b84188..5f9ec55b05 100644 --- a/calibrations/framework/oncal/OnCalServer.cc +++ b/calibrations/framework/fun4cal/Fun4CalServer.cc @@ -1,7 +1,7 @@ -#include "OnCalServer.h" -#include "OnCal.h" -#include "OnCalDBCodes.h" -#include "OnCalHistoBinDefs.h" +#include "Fun4CalServer.h" +#include "CalReco.h" +#include "Fun4CalDBCodes.h" +#include "Fun4CalHistoBinDefs.h" #include #include @@ -53,33 +53,33 @@ namespace odbc::Connection *DBconnection{nullptr}; } // namespace -OnCalServer *OnCalServer::instance() +Fun4CalServer *Fun4CalServer::instance() { if (__instance) { - OnCalServer *oncal = dynamic_cast(__instance); + Fun4CalServer *oncal = dynamic_cast(__instance); return oncal; } - __instance = new OnCalServer(); - OnCalServer *oncal = dynamic_cast(__instance); + __instance = new Fun4CalServer(); + Fun4CalServer *oncal = dynamic_cast(__instance); return oncal; } //--------------------------------------------------------------------- -OnCalServer::OnCalServer(const std::string &name) +Fun4CalServer::Fun4CalServer(const std::string &name) : Fun4AllServer(name) - , OnCalServerVars(new TH1D("OnCalServerVars", "OnCalServerVars", OnCalHistoBinDefs::LASTBINPLUSONE, -0.5, (int) (OnCalHistoBinDefs::LASTBINPLUSONE) -0.5)) + , Fun4CalServerVars(new TH1D("Fun4CalServerVars", "Fun4CalServerVars", Fun4CalHistoBinDefs::LASTBINPLUSONE, -0.5, (int) (Fun4CalHistoBinDefs::LASTBINPLUSONE) -0.5)) { beginTimeStamp.setTics(0); endTimeStamp.setTics(0); - Fun4AllServer::registerHisto(OnCalServerVars); + Fun4AllServer::registerHisto(Fun4CalServerVars); return; } //--------------------------------------------------------------------- -OnCalServer::~OnCalServer() +Fun4CalServer::~Fun4CalServer() { delete DBconnection; return; @@ -87,7 +87,7 @@ OnCalServer::~OnCalServer() //--------------------------------------------------------------------- PHTimeStamp * -OnCalServer::GetEndValidityTS() +Fun4CalServer::GetEndValidityTS() { if (endTimeStamp.getTics()) { @@ -100,7 +100,7 @@ OnCalServer::GetEndValidityTS() } //--------------------------------------------------------------------- -PHTimeStamp *OnCalServer::GetBeginValidityTS() +PHTimeStamp *Fun4CalServer::GetBeginValidityTS() { if (beginTimeStamp.getTics()) { @@ -113,7 +113,7 @@ PHTimeStamp *OnCalServer::GetBeginValidityTS() } //--------------------------------------------------------------------- -void OnCalServer::dumpHistos() +void Fun4CalServer::dumpHistos() { std::ostringstream filename; std::string fileprefix = "./"; @@ -137,7 +137,7 @@ void OnCalServer::dumpHistos() << "_" << iter->first << ".root"; TFile *hfile = new TFile(filename.str().c_str(), "RECREATE", "Created by Online Calibrator", compress); - std::cout << "OnCalServer::dumpHistos() Output root file: " << filename.str() << std::endl; + std::cout << "Fun4CalServer::dumpHistos() Output root file: " << filename.str() << std::endl; for (siter = (iter->second).begin(); siter != (iter->second).end(); ++siter) { histo = dynamic_cast(getHisto(*siter)); @@ -159,7 +159,7 @@ void OnCalServer::dumpHistos() return; } -void OnCalServer::registerHisto(TH1 *h1d, OnCal *Calibrator, const int replace) +void Fun4CalServer::registerHisto(TH1 *h1d, CalReco *Calibrator, const int replace) { if (Calibrator) { @@ -174,7 +174,7 @@ void OnCalServer::registerHisto(TH1 *h1d, OnCal *Calibrator, const int replace) { std::set newset; newset.insert(h1d->GetName()); - newset.insert("OnCalServerVars"); + newset.insert("Fun4CalServerVars"); calibratorhistomap[calibratorname] = newset; } } @@ -182,13 +182,13 @@ void OnCalServer::registerHisto(TH1 *h1d, OnCal *Calibrator, const int replace) return; } -void OnCalServer::unregisterHisto(const std::string &calibratorname) +void Fun4CalServer::unregisterHisto(const std::string &calibratorname) { calibratorhistomap.erase(calibratorname); return; } -int OnCalServer::process_event() +int Fun4CalServer::process_event() { Fun4AllServer::process_event(); int i = 0; @@ -201,7 +201,7 @@ int OnCalServer::process_event() std::vector >::const_iterator iter; for (iter = Subsystems.begin(); iter != Subsystems.end(); ++iter) { - OnCal *oncal = dynamic_cast(iter->first); + CalReco *oncal = dynamic_cast(iter->first); if (oncal) { ical++; @@ -220,7 +220,7 @@ int OnCalServer::process_event() return i; } -int OnCalServer::BeginRun(const int runno) +int Fun4CalServer::BeginRun(const int runno) { if (runno <= 0) { @@ -291,10 +291,10 @@ int OnCalServer::BeginRun(const int runno) << " - send e-mail to off-l with your macro" << std::endl; exit(1); } - OnCal *oncal = dynamic_cast((*iter).first); + CalReco *oncal = dynamic_cast((*iter).first); if (oncal) { - std::string table = "OnCal"; + std::string table = "CalReco"; table += (*iter).first->Name(); check_create_subsystable(table); insertRunNumInDB(table, runNum); @@ -312,7 +312,7 @@ int OnCalServer::BeginRun(const int runno) else { std::ostringstream stringarg; - stringarg << OnCalDBCodes::STARTED; + stringarg << Fun4CalDBCodes::STARTED; for (runiter = runlist.begin(); runiter != runlist.end(); ++runiter) { updateDB(successTable, calibname, stringarg.str(), *runiter); @@ -328,7 +328,7 @@ int OnCalServer::BeginRun(const int runno) else { rc->set_IntFlag("RUNNUMBER", oncalrun); - // rc->set_TimeStamp(OnCalBORTimeStamp); + // rc->set_TimeStamp(CalRecoBORTimeStamp); } if (!droplist.contains((*iter).first->Name())) { @@ -344,17 +344,17 @@ int OnCalServer::BeginRun(const int runno) gROOT->cd(currdir.c_str()); rc->set_IntFlag("RUNNUMBER", oncalrun); - // rc->set_TimeStamp(OnCalBORTimeStamp); - if (OnCalServerVars->GetBinContent(OnCalHistoBinDefs::FIRSTRUNBIN) == 0) + // rc->set_TimeStamp(CalRecoBORTimeStamp); + if (Fun4CalServerVars->GetBinContent(Fun4CalHistoBinDefs::FIRSTRUNBIN) == 0) { - OnCalServerVars->SetBinContent(OnCalHistoBinDefs::FIRSTRUNBIN, runno); - OnCalServerVars->SetBinContent(OnCalHistoBinDefs::BORTIMEBIN, (Stat_t) OnCalBORTimeStamp.getTics()); + Fun4CalServerVars->SetBinContent(Fun4CalHistoBinDefs::FIRSTRUNBIN, runno); + Fun4CalServerVars->SetBinContent(Fun4CalHistoBinDefs::BORTIMEBIN, (Stat_t) OnCalBORTimeStamp.getTics()); } - OnCalServerVars->SetBinContent(OnCalHistoBinDefs::LASTRUNBIN, (Stat_t) runno); + Fun4CalServerVars->SetBinContent(Fun4CalHistoBinDefs::LASTRUNBIN, (Stat_t) runno); ts = runTime->getEndTime(runno); if (ts) { - OnCalServerVars->SetBinContent(OnCalHistoBinDefs::EORTIMEBIN, (Stat_t) ts->getTics()); + Fun4CalServerVars->SetBinContent(Fun4CalHistoBinDefs::EORTIMEBIN, (Stat_t) ts->getTics()); delete ts; } @@ -367,7 +367,7 @@ int OnCalServer::BeginRun(const int runno) return i; } -int OnCalServer::End() +int Fun4CalServer::End() { if (nEvents == 0) { @@ -404,7 +404,7 @@ int OnCalServer::End() currdir = gDirectory->GetPath(); for (iter = Subsystems.begin(); iter != Subsystems.end(); ++iter) { - OnCal *oncal = dynamic_cast((*iter).first); + CalReco *oncal = dynamic_cast((*iter).first); if (!oncal) { continue; @@ -427,17 +427,17 @@ int OnCalServer::End() // report success database the status of the calibration if (recordDB) { - std::string table = "OnCal"; + std::string table = "CalReco"; table += CalibratorName; std::ostringstream stringarg; - if (databasecommitstatus == OnCalDBCodes::SUCCESS) + if (databasecommitstatus == Fun4CalDBCodes::SUCCESS) { - stringarg << OnCalDBCodes::COVERED; + stringarg << Fun4CalDBCodes::COVERED; } else { - stringarg << OnCalDBCodes::FAILED; + stringarg << Fun4CalDBCodes::FAILED; } std::set::const_iterator runiter; for (runiter = runlist.begin(); runiter != runlist.end(); ++runiter) @@ -503,7 +503,7 @@ int OnCalServer::End() } //--------------------------------------------------------------------- -void OnCalServer::Print(const std::string &what) const +void Fun4CalServer::Print(const std::string &what) const { Fun4AllServer::Print(what); if (what == "ALL" || what == "CALIBRATOR") @@ -513,13 +513,13 @@ void OnCalServer::Print(const std::string &what) const std::cout << "--------------------------------------" << std::endl << std::endl; - std::cout << "List of Calibrators in OnCalServer:" << std::endl; + std::cout << "List of Calibrators in Fun4CalServer:" << std::endl; std::vector >::const_iterator miter; for (miter = Subsystems.begin(); miter != Subsystems.end(); ++miter) { - OnCal *oncal = dynamic_cast((*miter).first); + CalReco *oncal = dynamic_cast((*miter).first); if (oncal) { std::cout << oncal->Name() << std::endl; @@ -534,7 +534,7 @@ void OnCalServer::Print(const std::string &what) const std::cout << "--------------------------------------" << std::endl << std::endl; - std::cout << "List of required Calibrations in OnCalServer:" << std::endl; + std::cout << "List of required Calibrations in Fun4CalServer:" << std::endl; std::map >::const_iterator iter; std::set::const_iterator siter; @@ -553,7 +553,7 @@ void OnCalServer::Print(const std::string &what) const { std::cout << "--------------------------------------" << std::endl << std::endl; - std::cout << "List of PRDF Files in OnCalServer:" << std::endl; + std::cout << "List of PRDF Files in Fun4CalServer:" << std::endl; for (Fun4AllSyncManager *sync : SyncManagers) { for (Fun4AllInputManager *inmgr : sync->GetInputManagers()) @@ -569,7 +569,7 @@ void OnCalServer::Print(const std::string &what) const { std::cout << "--------------------------------------" << std::endl << std::endl; - std::cout << "List of Run Numbers in OnCalServer:" << std::endl; + std::cout << "List of Run Numbers in Fun4CalServer:" << std::endl; std::set::const_iterator liter; for (liter = runlist.begin(); liter != runlist.end(); ++liter) { @@ -580,7 +580,7 @@ void OnCalServer::Print(const std::string &what) const return; } -void OnCalServer::printStamps() +void Fun4CalServer::printStamps() { std::cout << std::endl << std::endl; @@ -605,7 +605,7 @@ void OnCalServer::printStamps() //--------------------------------------------------------------------- -void OnCalServer::RunNumber(const int runnum) +void Fun4CalServer::RunNumber(const int runnum) { runNum = runnum; SetBorTime(runnum); @@ -641,7 +641,7 @@ void OnCalServer::RunNumber(const int runnum) //--------------------------------------------------------------------- -bool OnCalServer::connectDB() +bool Fun4CalServer::connectDB() { if (DBconnection) { @@ -678,7 +678,7 @@ bool OnCalServer::connectDB() } //--------------------------------------------------------------------- -int OnCalServer::DisconnectDB() +int Fun4CalServer::DisconnectDB() { delete DBconnection; DBconnection = nullptr; @@ -686,7 +686,7 @@ int OnCalServer::DisconnectDB() } //--------------------------------------------------------------------- -bool OnCalServer::insertRunNumInDB(const std::string &DBtable, const int runno) +bool Fun4CalServer::insertRunNumInDB(const std::string &DBtable, const int runno) { if (findRunNumInDB(DBtable, runno)) { @@ -705,7 +705,7 @@ bool OnCalServer::insertRunNumInDB(const std::string &DBtable, const int runno) if (Verbosity() == 1) { - std::cout << "in function OnCalServer::insertRunNumInDB() ... "; + std::cout << "in function Fun4CalServer::insertRunNumInDB() ... "; std::cout << "executing SQL statements ..." << std::endl; std::cout << cmd.str() << std::endl; } @@ -725,7 +725,7 @@ bool OnCalServer::insertRunNumInDB(const std::string &DBtable, const int runno) //--------------------------------------------------------------------- -bool OnCalServer::findRunNumInDB(const std::string &DBtable, const int runno) +bool Fun4CalServer::findRunNumInDB(const std::string &DBtable, const int runno) { if (!DBconnection) { @@ -743,7 +743,7 @@ bool OnCalServer::findRunNumInDB(const std::string &DBtable, const int runno) if (Verbosity() == 1) { - std::cout << "in function OnCalServer::findRunNumInDB() "; + std::cout << "in function Fun4CalServer::findRunNumInDB() "; std::cout << "executing SQL statement ..." << std::endl << cmd.str() << std::endl; } @@ -779,7 +779,7 @@ bool OnCalServer::findRunNumInDB(const std::string &DBtable, const int runno) return true; } -bool OnCalServer::updateDBRunRange(const std::string &table, const std::string &column, const int entry, const int firstrun, const int lastrun) +bool Fun4CalServer::updateDBRunRange(const std::string &table, const std::string &column, const int entry, const int firstrun, const int lastrun) { if (!DBconnection) { @@ -801,7 +801,7 @@ bool OnCalServer::updateDBRunRange(const std::string &table, const std::string & if (Verbosity() == 1) { - std::cout << "in function OnCalServer::updateDB() ... "; + std::cout << "in function Fun4CalServer::updateDB() ... "; std::cout << "executin SQL statement ... " << std::endl; std::cout << command << std::endl; } @@ -822,7 +822,7 @@ bool OnCalServer::updateDBRunRange(const std::string &table, const std::string & //--------------------------------------------------------------------- -bool OnCalServer::updateDB(const std::string &table, const std::string &column, int entry) +bool Fun4CalServer::updateDB(const std::string &table, const std::string &column, int entry) { if (!DBconnection) { @@ -842,7 +842,7 @@ bool OnCalServer::updateDB(const std::string &table, const std::string &column, if (Verbosity() == 1) { - std::cout << "in function OnCalServer::updateDB() ... "; + std::cout << "in function Fun4CalServer::updateDB() ... "; std::cout << "executin SQL statement ... " << std::endl; std::cout << command.Data() << std::endl; } @@ -862,7 +862,7 @@ bool OnCalServer::updateDB(const std::string &table, const std::string &column, } //--------------------------------------------------------------------- -bool OnCalServer::updateDB(const std::string &table, const std::string &column, bool entry) +bool Fun4CalServer::updateDB(const std::string &table, const std::string &column, bool entry) { if (!DBconnection) { @@ -881,7 +881,7 @@ bool OnCalServer::updateDB(const std::string &table, const std::string &column, if (Verbosity() == 1) { - std::cout << "in function OnCalServer::updateDB() ... "; + std::cout << "in function Fun4CalServer::updateDB() ... "; std::cout << "executin SQL statement ... " << std::endl; std::cout << command.Data() << std::endl; } @@ -902,7 +902,7 @@ bool OnCalServer::updateDB(const std::string &table, const std::string &column, //--------------------------------------------------------------------- -int OnCalServer::updateDB(const std::string &table, const std::string &column, +int Fun4CalServer::updateDB(const std::string &table, const std::string &column, const time_t ticks) { if (!DBconnection) @@ -924,7 +924,7 @@ int OnCalServer::updateDB(const std::string &table, const std::string &column, if (Verbosity() == 1) { - std::cout << "in function OnCalServer::updateDB() ... "; + std::cout << "in function Fun4CalServer::updateDB() ... "; std::cout << "executin SQL statement ... " << std::endl; std::cout << cmd.str() << std::endl; } @@ -942,7 +942,7 @@ int OnCalServer::updateDB(const std::string &table, const std::string &column, } //--------------------------------------------------------------------- -bool OnCalServer::updateDB(const std::string &table, const std::string &column, +bool Fun4CalServer::updateDB(const std::string &table, const std::string &column, const std::string &entry, const int runno, const bool append) { if (!DBconnection) @@ -971,7 +971,7 @@ bool OnCalServer::updateDB(const std::string &table, const std::string &column, } catch (odbc::SQLException &e) { - std::cout << "in function OnCalServer::updateDB() ... "; + std::cout << "in function Fun4CalServer::updateDB() ... "; std::cout << "run number " << runno << "not found in DB" << std::endl; std::cout << e.getMessage() << std::endl; } @@ -984,7 +984,7 @@ bool OnCalServer::updateDB(const std::string &table, const std::string &column, } catch (odbc::SQLException &e) { - std::cout << "in function OnCalServer::updateDB() ... " << std::endl; + std::cout << "in function Fun4CalServer::updateDB() ... " << std::endl; std::cout << "nothing to append." << std::endl; std::cout << e.getMessage() << std::endl; } @@ -1003,7 +1003,7 @@ bool OnCalServer::updateDB(const std::string &table, const std::string &column, if (Verbosity() == 1) { - std::cout << "in function OnCalServer::updateDB() ... "; + std::cout << "in function Fun4CalServer::updateDB() ... "; std::cout << "executin SQL statement ... " << std::endl; std::cout << cmd.str() << std::endl; } @@ -1023,7 +1023,7 @@ bool OnCalServer::updateDB(const std::string &table, const std::string &column, //--------------------------------------------------------------------- -int OnCalServer::check_create_subsystable(const std::string &tablename) +int Fun4CalServer::check_create_subsystable(const std::string &tablename) { if (!connectDB()) { @@ -1110,7 +1110,7 @@ int OnCalServer::check_create_subsystable(const std::string &tablename) return 0; } -int OnCalServer::add_calibrator_to_statustable(const std::string &calibratorname) +int Fun4CalServer::add_calibrator_to_statustable(const std::string &calibratorname) { if (!connectDB()) { @@ -1139,7 +1139,7 @@ int OnCalServer::add_calibrator_to_statustable(const std::string &calibratorname } cmd.str(""); cmd << "ALTER TABLE " << successTable << " ALTER COLUMN " - << calibname << " SET DEFAULT " << OnCalDBCodes::INIT; + << calibname << " SET DEFAULT " << Fun4CalDBCodes::INIT; try { stmt->executeUpdate(cmd.str()); @@ -1152,7 +1152,7 @@ int OnCalServer::add_calibrator_to_statustable(const std::string &calibratorname } cmd.str(""); cmd << "UPDATE " << successTable << " SET " - << calibname << " = " << OnCalDBCodes::INIT; + << calibname << " = " << Fun4CalDBCodes::INIT; try { stmt->executeUpdate(cmd.str()); @@ -1167,7 +1167,7 @@ int OnCalServer::add_calibrator_to_statustable(const std::string &calibratorname return 0; } -int OnCalServer::check_calibrator_in_statustable(const std::string &calibratorname) +int Fun4CalServer::check_calibrator_in_statustable(const std::string &calibratorname) { // replace this contraption by this sql command which returns 1 row if column exists // select * from information_schema.columns where table_name = 'oncal_status' and column_name = 'svxstripdeadmapcal'; @@ -1213,7 +1213,7 @@ int OnCalServer::check_calibrator_in_statustable(const std::string &calibratorna return -1; } -int OnCalServer::check_create_successtable(const std::string &tablename) +int Fun4CalServer::check_create_successtable(const std::string &tablename) { if (!connectDB()) { @@ -1257,7 +1257,7 @@ int OnCalServer::check_create_successtable(const std::string &tablename) return 0; } -void OnCalServer::recordDataBase(const bool bookkeep) +void Fun4CalServer::recordDataBase(const bool bookkeep) { recordDB = bookkeep; if (recordDB) @@ -1267,20 +1267,20 @@ void OnCalServer::recordDataBase(const bool bookkeep) return; } -void OnCalServer::BeginTimeStamp(const PHTimeStamp &TimeStp) +void Fun4CalServer::BeginTimeStamp(const PHTimeStamp &TimeStp) { beginTimeStamp = TimeStp; - std::cout << "OnCalServer::BeginTimeStamp: Setting BOR TimeStamp to " << beginTimeStamp << std::endl; + std::cout << "Fun4CalServer::BeginTimeStamp: Setting BOR TimeStamp to " << beginTimeStamp << std::endl; } -void OnCalServer::EndTimeStamp(const PHTimeStamp &TimeStp) +void Fun4CalServer::EndTimeStamp(const PHTimeStamp &TimeStp) { endTimeStamp = TimeStp; - std::cout << "OnCalServer::EndTimeStamp: Setting EOR TimeStamp to " << endTimeStamp << std::endl; + std::cout << "Fun4CalServer::EndTimeStamp: Setting EOR TimeStamp to " << endTimeStamp << std::endl; } PHTimeStamp * -OnCalServer::GetLastGoodRunTS(OnCal *calibrator, const int irun) +Fun4CalServer::GetLastGoodRunTS(CalReco *calibrator, const int irun) { PHTimeStamp *ts = nullptr; if (!connectDB()) @@ -1324,7 +1324,7 @@ OnCalServer::GetLastGoodRunTS(OnCal *calibrator, const int irun) return ts; } -int OnCalServer::SyncCalibTimeStampsToOnCal(const OnCal *calibrator, const int commit) +int Fun4CalServer::SyncCalibTimeStampsToOnCal(const CalReco *calibrator, const int commit) { std::vector caltab; calibrator->GetPdbCalTables(caltab); @@ -1337,7 +1337,7 @@ int OnCalServer::SyncCalibTimeStampsToOnCal(const OnCal *calibrator, const int c return 0; } -int OnCalServer::SyncCalibTimeStampsToOnCal(const OnCal *calibrator, const std::string &table, const int commit) +int Fun4CalServer::SyncCalibTimeStampsToOnCal(const CalReco *calibrator, const std::string &table, const int commit) { std::string name = calibrator->Name(); odbc::Connection *con = nullptr; @@ -1500,7 +1500,7 @@ int OnCalServer::SyncCalibTimeStampsToOnCal(const OnCal *calibrator, const std:: return 0; } -int OnCalServer::SyncOncalTimeStampsToRunDB(const int commit) +int Fun4CalServer::SyncOncalTimeStampsToRunDB(const int commit) { odbc::Connection *con = nullptr; RunToTime *rt = RunToTime::instance(); @@ -1636,13 +1636,13 @@ int OnCalServer::SyncOncalTimeStampsToRunDB(const int commit) return 0; } -int OnCalServer::CopyTables(const OnCal *calibrator, const int FromRun, const int ToRun, const int commit) +int Fun4CalServer::CopyTables(const CalReco *calibrator, const int FromRun, const int ToRun, const int commit) { int iret = calibrator->CopyTables(FromRun, ToRun, commit); return iret; } -int OnCalServer::CreateCalibration(OnCal *calibrator, const int myrunnumber, const std::string &what, const int commit) +int Fun4CalServer::CreateCalibration(CalReco *calibrator, const int myrunnumber, const std::string &what, const int commit) { int iret = -1; runNum = myrunnumber; @@ -1703,7 +1703,7 @@ int OnCalServer::CreateCalibration(OnCal *calibrator, const int myrunnumber, con std::cout << "updating oncal status tables for " << runnumber << std::endl; if (commit) { - CreateCalibrationUpdateStatus(calibrator, table, tablecomment, OnCalDBCodes::SUBSYSTEM); + CreateCalibrationUpdateStatus(calibrator, table, tablecomment, Fun4CalDBCodes::SUBSYSTEM); } } else @@ -1711,7 +1711,7 @@ int OnCalServer::CreateCalibration(OnCal *calibrator, const int myrunnumber, con std::cout << "Calibratior " << calibrator->Name() << " for run " << runnumber << " failed" << std::endl; if (commit) { - CreateCalibrationUpdateStatus(calibrator, table, tablecomment, OnCalDBCodes::FAILED); + CreateCalibrationUpdateStatus(calibrator, table, tablecomment, Fun4CalDBCodes::FAILED); } } } @@ -1723,7 +1723,7 @@ int OnCalServer::CreateCalibration(OnCal *calibrator, const int myrunnumber, con return iret; } -void OnCalServer::CreateCalibrationUpdateStatus(OnCal *calibrator, const std::string &table, const std::string &tablecomment, const int dbcode) +void Fun4CalServer::CreateCalibrationUpdateStatus(CalReco *calibrator, const std::string &table, const std::string &tablecomment, const int dbcode) { updateDB(successTable, calibrator->Name(), dbcode); insertRunNumInDB(table, RunNumber()); @@ -1766,7 +1766,7 @@ void OnCalServer::CreateCalibrationUpdateStatus(OnCal *calibrator, const std::st return; } -int OnCalServer::ClosestGoodRun(OnCal *calibrator, const int irun, const int previous) +int Fun4CalServer::ClosestGoodRun(CalReco *calibrator, const int irun, const int previous) { RunToTime *rt = RunToTime::instance(); PHTimeStamp *ts = rt->getBeginTime(irun); @@ -1906,7 +1906,7 @@ int OnCalServer::ClosestGoodRun(OnCal *calibrator, const int irun, const int pre return closestrun; } -int OnCalServer::OverwriteCalibration(OnCal *calibrator, const int runno, const int commit, const int FromRun) +int Fun4CalServer::OverwriteCalibration(CalReco *calibrator, const int runno, const int commit, const int FromRun) { if (FromRun < 0) { @@ -1916,7 +1916,7 @@ int OnCalServer::OverwriteCalibration(OnCal *calibrator, const int runno, const return iret; } -int OnCalServer::FixMissingCalibration(OnCal *calibrator, const int runno, const int commit, const int fromrun) +int Fun4CalServer::FixMissingCalibration(CalReco *calibrator, const int runno, const int commit, const int fromrun) { int iret = -1; // find this run in oncal_status @@ -1987,11 +1987,11 @@ int OnCalServer::FixMissingCalibration(OnCal *calibrator, const int runno, const int newstatus = 0; if (FromRun < runno) { - newstatus = OnCalDBCodes::COPIEDPREVIOUS; + newstatus = Fun4CalDBCodes::COPIEDPREVIOUS; } else { - newstatus = OnCalDBCodes::COPIEDLATER; + newstatus = Fun4CalDBCodes::COPIEDLATER; } std::string table = "OnCal"; table += calibrator->Name(); @@ -2016,7 +2016,7 @@ int OnCalServer::FixMissingCalibration(OnCal *calibrator, const int runno, const return iret; } -int OnCalServer::SetBorTime(const int runno) +int Fun4CalServer::SetBorTime(const int runno) { // recoConsts *rc = recoConsts::instance(); RunToTime *runTime = RunToTime::instance(); @@ -2033,7 +2033,7 @@ int OnCalServer::SetBorTime(const int runno) // enter begin run timestamp into rc flags PHTimeStamp BeginRunTimeStamp(*BorTimeStp); // rc->set_TimeStamp(BeginRunTimeStamp); - std::cout << "OnCalServer::SetBorTime from RunToTime was found for run : " << runno << " to "; + std::cout << "Fun4CalServer::SetBorTime from RunToTime was found for run : " << runno << " to "; BeginRunTimeStamp.print(); std::cout << std::endl; @@ -2041,7 +2041,7 @@ int OnCalServer::SetBorTime(const int runno) return 0; } -int OnCalServer::SetEorTime(const int runno) +int Fun4CalServer::SetEorTime(const int runno) { // recoConsts *rc = recoConsts::instance(); RunToTime *runTime = RunToTime::instance(); @@ -2065,14 +2065,14 @@ int OnCalServer::SetEorTime(const int runno) EorTimeStp->setTics(eorticks); } EndTimeStamp(*EorTimeStp); - std::cout << "OnCalServer::SetEorTime: setting eor time to "; + std::cout << "Fun4CalServer::SetEorTime: setting eor time to "; EorTimeStp->print(); std::cout << std::endl; delete EorTimeStp; return 0; } -int OnCalServer::GetRunTimeTicks(const int runno, time_t &borticks, time_t &eorticks) +int Fun4CalServer::GetRunTimeTicks(const int runno, time_t &borticks, time_t &eorticks) { RunToTime *runTime = RunToTime::instance(); PHTimeStamp *TimeStp(runTime->getBeginTime(runno)); @@ -2102,7 +2102,7 @@ int OnCalServer::GetRunTimeTicks(const int runno, time_t &borticks, time_t &eort return 0; } -int OnCalServer::requiredCalibration(SubsysReco *reco, const std::string &calibratorname) +int Fun4CalServer::requiredCalibration(SubsysReco *reco, const std::string &calibratorname) { std::map >::iterator iter; if (check_calibrator_in_statustable(calibratorname)) @@ -2124,7 +2124,7 @@ int OnCalServer::requiredCalibration(SubsysReco *reco, const std::string &calibr return 0; } -int OnCalServer::FindClosestCalibratedRun(const int irun) +int Fun4CalServer::FindClosestCalibratedRun(const int irun) { RunToTime *rt = RunToTime::instance(); PHTimeStamp *ts = rt->getBeginTime(irun); @@ -2261,7 +2261,7 @@ int OnCalServer::FindClosestCalibratedRun(const int irun) return closestrun; } -int OnCalServer::FillRunListFromFileList() +int Fun4CalServer::FillRunListFromFileList() { for (Fun4AllSyncManager *sync : SyncManagers) { @@ -2277,7 +2277,7 @@ int OnCalServer::FillRunListFromFileList() return 0; } -int OnCalServer::AdjustRichTimeStampForMultipleRuns() +int Fun4CalServer::AdjustRichTimeStampForMultipleRuns() { int firstrun = *runlist.begin(); int lastrun = *runlist.rbegin(); @@ -2289,7 +2289,7 @@ int OnCalServer::AdjustRichTimeStampForMultipleRuns() GetRunTimeTicks(firstrun, beginticks, dummy); GetRunTimeTicks(lastrun, dummy, endticks); std::ostringstream stringarg; - stringarg << OnCalDBCodes::COVERED; + stringarg << Fun4CalDBCodes::COVERED; // std::set::const_iterator runiter; /* for (runiter = runlist.begin(); runiter != runlist.end(); runiter++) @@ -2297,7 +2297,7 @@ int OnCalServer::AdjustRichTimeStampForMultipleRuns() updateDB(successTable, "RichCal", stringarg.str(), *runiter); } stringarg.str(""); - stringarg << OnCalDBCodes::SUCCESS; + stringarg << Fun4CalDBCodes::SUCCESS; updateDB(successTable, "RichCal", stringarg.str(), firstrun); */ @@ -2378,7 +2378,7 @@ int OnCalServer::AdjustRichTimeStampForMultipleRuns() return 0; } -int OnCalServer::GetCalibStatus(const std::string &calibname, const int runno) +int Fun4CalServer::GetCalibStatus(const std::string &calibname, const int runno) { int iret = -3; if (!connectDB()) @@ -2417,7 +2417,7 @@ int OnCalServer::GetCalibStatus(const std::string &calibname, const int runno) return iret; } -void OnCalServer::TestMode(const int i) +void Fun4CalServer::TestMode(const int i) { const char *logname = getenv("LOGNAME"); if (logname) diff --git a/calibrations/framework/oncal/OnCalServer.h b/calibrations/framework/fun4cal/Fun4CalServer.h similarity index 77% rename from calibrations/framework/oncal/OnCalServer.h rename to calibrations/framework/fun4cal/Fun4CalServer.h index 890901207c..47e0777ab8 100644 --- a/calibrations/framework/oncal/OnCalServer.h +++ b/calibrations/framework/fun4cal/Fun4CalServer.h @@ -1,5 +1,5 @@ -#ifndef ONCAL_ONCALSERVER_H -#define ONCAL_ONCALSERVER_H +#ifndef FUN4CAL_FUN4CALSERVER_H +#define FUN4CAL_FUN4CALSERVER_H #include #include @@ -10,7 +10,7 @@ #include #include -class OnCal; +class CalReco; class SubsysReco; class TH1; @@ -23,13 +23,13 @@ namespace fetchrun }; }; -class OnCalServer : public Fun4AllServer +class Fun4CalServer : public Fun4AllServer { public: - static OnCalServer *instance(); - ~OnCalServer() override; + static Fun4CalServer *instance(); + ~Fun4CalServer() override; using Fun4AllServer::registerHisto; - void registerHisto(TH1 *h1d, OnCal *Calibrator, const int replace = 0); + void registerHisto(TH1 *h1d, CalReco *Calibrator, const int replace = 0); void unregisterHisto(const std::string &calibratorname); void Print(const std::string &what = "ALL") const override; @@ -43,7 +43,7 @@ class OnCalServer : public Fun4AllServer PHTimeStamp *GetBeginValidityTS(); void printStamps(); - PHTimeStamp *GetLastGoodRunTS(OnCal *calibrator, const int irun); + PHTimeStamp *GetLastGoodRunTS(CalReco *calibrator, const int irun); void recordDataBase(const bool bookkeep = false); @@ -60,13 +60,13 @@ class OnCalServer : public Fun4AllServer void BeginTimeStamp(const PHTimeStamp &TimeStp); void EndTimeStamp(const PHTimeStamp &TimeStp); - int SyncCalibTimeStampsToOnCal(const OnCal *calibrator, const std::string &table, const int commit = 0); - int SyncCalibTimeStampsToOnCal(const OnCal *calibrator, const int commit = 0); + int SyncCalibTimeStampsToOnCal(const CalReco *calibrator, const std::string &table, const int commit = 0); + int SyncCalibTimeStampsToOnCal(const CalReco *calibrator, const int commit = 0); int SyncOncalTimeStampsToRunDB(const int commit = 0); - int ClosestGoodRun(OnCal *calibrator, const int irun, const int previous = fetchrun::CLOSEST); - static int CopyTables(const OnCal *calibrator, const int FromRun, const int ToRun, const int commit = 0); - static int OverwriteCalibration(OnCal *calibrator, const int runno, const int commit = 0, const int fromrun = -1); - int FixMissingCalibration(OnCal *calibrator, const int runno, const int commit = 0, const int fromrun = -1); + int ClosestGoodRun(CalReco *calibrator, const int irun, const int previous = fetchrun::CLOSEST); + static int CopyTables(const CalReco *calibrator, const int FromRun, const int ToRun, const int commit = 0); + static int OverwriteCalibration(CalReco *calibrator, const int runno, const int commit = 0, const int fromrun = -1); + int FixMissingCalibration(CalReco *calibrator, const int runno, const int commit = 0, const int fromrun = -1); int SetBorTime(const int runno); int SetEorTime(const int runno); @@ -74,7 +74,7 @@ class OnCalServer : public Fun4AllServer int FindClosestCalibratedRun(const int irun); int FillRunListFromFileList(); int AdjustRichTimeStampForMultipleRuns(); - int CreateCalibration(OnCal *calibrator, const int myrunnumber, const std::string &what, const int commit = 0); + int CreateCalibration(CalReco *calibrator, const int myrunnumber, const std::string &what, const int commit = 0); int GetCalibStatus(const std::string &calibname, const int runno); static int DisconnectDB(); void TestMode(const int i = 1); @@ -113,13 +113,13 @@ class OnCalServer : public Fun4AllServer int add_calibrator_to_statustable(const std::string &calibratorname); int check_calibrator_in_statustable(const std::string &calibratorname); static int GetRunTimeTicks(const int runno, time_t &borticks, time_t &eorticks); - void CreateCalibrationUpdateStatus(OnCal *calibrator, const std::string &table, const std::string &tablecomment, const int dbcode); - OnCalServer(const std::string &name = "OnCalServer"); + void CreateCalibrationUpdateStatus(CalReco *calibrator, const std::string &table, const std::string &tablecomment, const int dbcode); + Fun4CalServer(const std::string &name = "Fun4CalServer"); PHTimeStamp beginTimeStamp; // begin run timestamp of run analysing PHTimeStamp endTimeStamp; // end run timestamp of run analysing int testmode{0}; bool recordDB{false}; - TH1 *OnCalServerVars{nullptr}; + TH1 *Fun4CalServerVars{nullptr}; std::map Histo; std::map > calibratorhistomap; bool SetEndTimeStampByHand{false}; @@ -137,4 +137,4 @@ class OnCalServer : public Fun4AllServer std::set runlist; }; -#endif /* __ONCALSERVER_H */ +#endif /* __FUN4CALSERVER_H */ diff --git a/calibrations/framework/oncal/Makefile.am b/calibrations/framework/fun4cal/Makefile.am similarity index 76% rename from calibrations/framework/oncal/Makefile.am rename to calibrations/framework/fun4cal/Makefile.am index bb0b3674c1..02ad88ff18 100644 --- a/calibrations/framework/oncal/Makefile.am +++ b/calibrations/framework/fun4cal/Makefile.am @@ -7,9 +7,9 @@ AM_CPPFLAGS = \ -isystem$(ROOTSYS)/include lib_LTLIBRARIES = \ - liboncal.la + libfun4cal.la -liboncal_la_LIBADD = \ +libfun4cal_la_LIBADD = \ -L$(libdir) \ -L$(OFFLINE_MAIN)/lib \ -L$(OPT_SPHENIX)/lib \ @@ -19,14 +19,14 @@ liboncal_la_LIBADD = \ -lphool pkginclude_HEADERS = \ - OnCalDBCodes.h \ - OnCalHistoBinDefs.h \ - OnCal.h \ - OnCalServer.h + Fun4CalDBCodes.h \ + Fun4CalHistoBinDefs.h \ + CalReco.h \ + Fun4CalServer.h -liboncal_la_SOURCES = \ - OnCal.cc \ - OnCalServer.cc +libfun4cal_la_SOURCES = \ + CalReco.cc \ + Fun4CalServer.cc BUILT_SOURCES = \ testexternals.cc @@ -38,7 +38,7 @@ testexternals_SOURCES = \ testexternals.cc testexternals_LDADD = \ - liboncal.la + libfun4cal.la testexternals.cc: echo "//*** this is a generated file. Do not commit, do not edit" > $@ diff --git a/calibrations/framework/oncal/autogen.sh b/calibrations/framework/fun4cal/autogen.sh similarity index 100% rename from calibrations/framework/oncal/autogen.sh rename to calibrations/framework/fun4cal/autogen.sh diff --git a/calibrations/framework/oncal/configure.ac b/calibrations/framework/fun4cal/configure.ac similarity index 93% rename from calibrations/framework/oncal/configure.ac rename to calibrations/framework/fun4cal/configure.ac index e5467a38b0..a665c5357c 100644 --- a/calibrations/framework/oncal/configure.ac +++ b/calibrations/framework/fun4cal/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(oncal,[2.00]) +AC_INIT(fun4cal,[1.00]) AC_CONFIG_SRCDIR([configure.ac]) AM_INIT_AUTOMAKE diff --git a/calibrations/framework/oncal/OnCalHistoBinDefs.h b/calibrations/framework/oncal/OnCalHistoBinDefs.h deleted file mode 100644 index d030b6dce2..0000000000 --- a/calibrations/framework/oncal/OnCalHistoBinDefs.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __ONCALHISTOBINDEFS_H__ -#define __ONCALHISTOBINDEFS_H__ - -namespace OnCalHistoBinDefs -{ - enum - { - FIRSTRUNBIN = 1, - LASTRUNBIN, - BORTIMEBIN, - EORTIMEBIN, - LASTBINPLUSONE - }; -}; - -#endif /* __ONCALHISTOBINDEFS_H__ */ diff --git a/calibrations/sepd/sepd_eventplanecalib/EventPlaneData.cc b/calibrations/sepd/sepd_eventplanecalib/EventPlaneData.cc new file mode 100644 index 0000000000..57c3fcfc58 --- /dev/null +++ b/calibrations/sepd/sepd_eventplanecalib/EventPlaneData.cc @@ -0,0 +1,44 @@ +#include "EventPlaneData.h" + +#include + +EventPlaneData::EventPlaneData() +{ + sepd_charge.fill(0); +} + +void EventPlaneData::Reset() +{ + event_id = 0; + event_zvertex = std::numeric_limits::quiet_NaN(); + event_centrality = std::numeric_limits::quiet_NaN(); + sepd_totalcharge = std::numeric_limits::quiet_NaN(); + sepd_charge.fill(0); +} + +void EventPlaneData::identify(std::ostream& os) const +{ + os << "--- EventPlaneData Identify ---" << std::endl; + os << "Event ID: " << event_id << std::endl; + os << "Z-Vertex: " << event_zvertex << std::endl; + os << "Centrality: " << event_centrality << std::endl; + os << "sEPD Total Charge: " << sepd_totalcharge << std::endl; + os << "-------------------------------" << std::endl; +} + +int EventPlaneData::isValid() const +{ + // An object is considered invalid if the Z-vertex is still NaN + // or if the event ID hasn't been set (remains 0). + if (std::isnan(event_zvertex)) + { + return 0; + } + + if (event_id == 0) + { + return 0; + } + + return 1; +} diff --git a/calibrations/sepd/sepd_eventplanecalib/EventPlaneData.h b/calibrations/sepd/sepd_eventplanecalib/EventPlaneData.h new file mode 100644 index 0000000000..d9ffea19c9 --- /dev/null +++ b/calibrations/sepd/sepd_eventplanecalib/EventPlaneData.h @@ -0,0 +1,51 @@ +#ifndef SEPD_EVENTPLANECALIB_EVENTPLANEDATA_H +#define SEPD_EVENTPLANECALIB_EVENTPLANEDATA_H + +#include "QVecDefs.h" + +#include + +#include +#include + +class EventPlaneData : public PHObject +{ + public: + EventPlaneData(); + ~EventPlaneData() override = default; + + EventPlaneData(const EventPlaneData&) = default; + EventPlaneData& operator=(const EventPlaneData&) = default; + EventPlaneData(EventPlaneData&&) = default; + EventPlaneData& operator=(EventPlaneData&&) = default; + + void Reset() override; + void set_event_id(int id) {event_id = id;} + int get_event_id() const {return event_id;} + + void set_event_zvertex(double vtx) {event_zvertex = vtx;} + double get_event_zvertex() const {return event_zvertex;} + + void set_sepd_totalcharge(double chg) {sepd_totalcharge = chg;} + double get_sepd_totalcharge() const {return sepd_totalcharge;} + + void set_sepd_charge(int channel, double chg) {sepd_charge[channel] = chg;} + double get_sepd_charge(int channel) const {return sepd_charge[channel];} + + void set_event_centrality(double cent) { event_centrality = cent; } + double get_event_centrality() const { return event_centrality; } + + void identify(std::ostream& os = std::cout) const override; + int isValid() const override; + + private: + int event_id {0}; + double event_zvertex {std::numeric_limits::quiet_NaN()}; + double event_centrality{std::numeric_limits::quiet_NaN()}; + double sepd_totalcharge{std::numeric_limits::quiet_NaN()}; + + std::array sepd_charge {}; + ClassDefOverride(EventPlaneData, 1); +}; + +#endif diff --git a/calibrations/sepd/sepd_eventplanecalib/EventPlaneDataLinkDef.h b/calibrations/sepd/sepd_eventplanecalib/EventPlaneDataLinkDef.h new file mode 100644 index 0000000000..9c56106475 --- /dev/null +++ b/calibrations/sepd/sepd_eventplanecalib/EventPlaneDataLinkDef.h @@ -0,0 +1,5 @@ +#ifdef __CINT__ + +#pragma link C++ class EventPlaneData + ; + +#endif /* __CINT__ */ diff --git a/calibrations/sepd/sepd_eventplanecalib/Makefile.am b/calibrations/sepd/sepd_eventplanecalib/Makefile.am new file mode 100644 index 0000000000..d17c56b4a0 --- /dev/null +++ b/calibrations/sepd/sepd_eventplanecalib/Makefile.am @@ -0,0 +1,71 @@ +AUTOMAKE_OPTIONS = foreign + +AM_CPPFLAGS = \ + -I$(includedir) \ + -isystem$(OFFLINE_MAIN)/include \ + -isystem$(ROOTSYS)/include + +AM_LDFLAGS = \ + -L$(libdir) \ + -L$(OFFLINE_MAIN)/lib \ + -L$(OFFLINE_MAIN)/lib64 \ + `root-config --libs` + +pkginclude_HEADERS = \ + sEPD_TreeGen.h \ + QVecCalib.h \ + QVecDefs.h + +lib_LTLIBRARIES = \ + libsepd_eventplanecalib.la + +ROOTDICTS = \ + EventPlaneData_Dict.cc + +pcmdir = $(libdir) +# more elegant way to create pcm files (without listing them) +nobase_dist_pcm_DATA = $(ROOTDICTS:.cc=_rdict.pcm) + +# EventPlaneData is a locally used root i/o object - no need to create an io library +libsepd_eventplanecalib_la_SOURCES = \ + $(ROOTDICTS) \ + EventPlaneData.cc \ + sEPD_TreeGen.cc \ + QVecCalib.cc + +libsepd_eventplanecalib_la_LIBADD = \ + -lphool \ + -lSubsysReco \ + -lcentrality_io \ + -lfun4all \ + -lffamodules \ + -lglobalvertex_io \ + -lcalotrigger_io \ + -lcalotrigger \ + -lcdbobjects \ + -lepd_io + +# Rule for generating table CINT dictionaries. +%_Dict.cc: %.h %LinkDef.h + rootcint -f $@ @CINTDEFS@ $(DEFAULT_INCLUDES) $(AM_CPPFLAGS) $^ + +#just to get the dependency +%_Dict_rdict.pcm: %_Dict.cc ; + +BUILT_SOURCES = testexternals.cc + +noinst_PROGRAMS = \ + testexternals + +testexternals_SOURCES = testexternals.cc +testexternals_LDADD = libsepd_eventplanecalib.la + +testexternals.cc: + echo "//*** this is a generated file. Do not commit, do not edit" > $@ + echo "int main()" >> $@ + echo "{" >> $@ + echo " return 0;" >> $@ + echo "}" >> $@ + +clean-local: + rm -f $(BUILT_SOURCES) diff --git a/calibrations/sepd/sepd_eventplanecalib/QVecCalib.cc b/calibrations/sepd/sepd_eventplanecalib/QVecCalib.cc new file mode 100644 index 0000000000..46c99354e1 --- /dev/null +++ b/calibrations/sepd/sepd_eventplanecalib/QVecCalib.cc @@ -0,0 +1,1427 @@ +#include "QVecCalib.h" +#include "EventPlaneData.h" + +// ==================================================================== +// sPHENIX Includes +// ==================================================================== +#include + +// -- Fun4All +#include +#include + +// -- Nodes +#include +#include + +// -- sEPD +#include + +// -- Run +#include + +// -- CDBTTree +#include + +#include +#include +#include +#include + + +// ==================================================================== +// Standard C++ Includes +// ==================================================================== +#include +#include +#include + +//____________________________________________________________________________.. +QVecCalib::QVecCalib(const std::string &name): + SubsysReco(name) +{ + // std::cout << "QVecCalib::QVecCalib(const std::string &name) Calling ctor" << std::endl; +} + +//____________________________________________________________________________.. +int QVecCalib::Init([[maybe_unused]] PHCompositeNode *topNode) +{ + if (Verbosity() > 1) + { + std::cout << "QVecCalib::Init(PHCompositeNode *topNode) Initializing" << std::endl; + + Fun4AllServer *se = Fun4AllServer::instance(); + se->Print("NODETREE"); + } + + int ret = process_QA_hist(); + if (ret) + { + return ret; + } + + init_hists(); + + if (m_pass == Pass::ApplyRecentering || m_pass == Pass::ApplyFlattening) + { + ret = load_correction_data(); + if (ret) + { + return ret; + } + } + + prepare_hists(); + + return Fun4AllReturnCodes::EVENT_OK; +} + +void QVecCalib::prepare_hists() +{ + if (m_pass == Pass::ComputeRecentering) + { + prepare_average_hists(); + } + else if (m_pass == Pass::ApplyRecentering) + { + prepare_recenter_hists(); + } + else if (m_pass == Pass::ApplyFlattening) + { + prepare_flattening_hists(); + } +} + +int QVecCalib::process_QA_hist() +{ + TH1::AddDirectory(kFALSE); + auto* file = TFile::Open(m_input_hist.c_str()); + + // Check if the file was opened successfully. + if (!file || file->IsZombie()) + { + std::cout << PHWHERE << "Error! Cannot not open file: " << m_input_hist << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + // Get sEPD Total Charge Bounds as function of centrality + int ret = process_sEPD_event_thresholds(file); + if (ret) + { + return ret; + } + + // Get List of Bad Channels + ret = process_bad_channels(file); + if (ret) + { + return ret; + } + + // cleanup + file->Close(); + delete file; + + return Fun4AllReturnCodes::EVENT_OK; +} + +int QVecCalib::process_sEPD_event_thresholds(TFile* file) +{ + Fun4AllServer *se = Fun4AllServer::instance(); + + std::string sepd_totalcharge_centrality = "h2SEPD_totalcharge_centrality"; + + TH2 *hist {nullptr}; + file->GetObject(sepd_totalcharge_centrality.c_str(),hist); + + // Check if the hist is stored in the file + if (hist == nullptr) + { + std::cout << PHWHERE << "Error! Cannot find hist: " << sepd_totalcharge_centrality << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + h2SEPD_Charge = static_cast(hist->Clone("h2SEPD_Charge")); + h2SEPD_Chargev2 = static_cast(hist->Clone("h2SEPD_Chargev2")); + + se->registerHisto(h2SEPD_Charge); + se->registerHisto(h2SEPD_Chargev2); + + auto* h2SEPD_Charge_py = h2SEPD_Charge->ProfileY("h2SEPD_Charge_py", 1, -1, "s"); + + int binsx = h2SEPD_Charge->GetNbinsX(); + int binsy = h2SEPD_Charge->GetNbinsY(); + double ymin = h2SEPD_Charge->GetYaxis()->GetXmin(); + double ymax = h2SEPD_Charge->GetYaxis()->GetXmax(); + + hSEPD_Charge_Min = new TProfile("hSEPD_Charge_Min", "; Centrality [%]; sEPD Total Charge", binsy, ymin, ymax); + hSEPD_Charge_Max = new TProfile("hSEPD_Charge_Max", "; Centrality [%]; sEPD Total Charge", binsy, ymin, ymax); + + se->registerHisto(hSEPD_Charge_Min); + se->registerHisto(hSEPD_Charge_Max); + + for (int y = 1; y <= binsy; ++y) + { + double cent = h2SEPD_Charge_py->GetBinCenter(y); + double mean = h2SEPD_Charge_py->GetBinContent(y); + double sigma = h2SEPD_Charge_py->GetBinError(y); + + if (sigma == 0) + { + continue; + } + + double charge_low = mean - m_sEPD_sigma_threshold * sigma; + double charge_high = mean + m_sEPD_sigma_threshold * sigma; + + hSEPD_Charge_Min->Fill(cent, charge_low); + hSEPD_Charge_Max->Fill(cent, charge_high); + + for (int x = 1; x <= binsx; ++x) + { + double charge = h2SEPD_Charge->GetXaxis()->GetBinCenter(x); + double zscore = (charge - mean) / sigma; + + if (std::abs(zscore) > m_sEPD_sigma_threshold) + { + h2SEPD_Chargev2->SetBinContent(x, y, 0); + h2SEPD_Chargev2->SetBinError(x, y, 0); + } + } + } + + return Fun4AllReturnCodes::EVENT_OK; +} + +int QVecCalib::process_bad_channels(TFile* file) +{ + Fun4AllServer *se = Fun4AllServer::instance(); + + std::string sepd_charge_hist = "hSEPD_Charge"; + + TProfile *hSEPD_Charge{nullptr}; + file->GetObject(sepd_charge_hist.c_str(), hSEPD_Charge); + + // Check if the hist is stored in the file + if (hSEPD_Charge == nullptr) + { + std::cout << PHWHERE << "Error! Cannot find hist: " << sepd_charge_hist << ", in file: " << file->GetName() << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + int rbins = 16; + int bins_charge = 40; + + h2SEPD_South_Charge_rbin = new TH2F("h2SEPD_South_Charge_rbin", + "sEPD South; r_{bin}; Avg Charge", + rbins, -0.5, rbins - 0.5, + bins_charge, 0, bins_charge); + + h2SEPD_North_Charge_rbin = new TH2F("h2SEPD_North_Charge_rbin", + "sEPD North; r_{bin}; Avg Charge", + rbins, -0.5, rbins - 0.5, + bins_charge, 0, bins_charge); + + h2SEPD_South_Charge_rbinv2 = new TH2F("h2SEPD_South_Charge_rbinv2", + "sEPD South; r_{bin}; Avg Charge", + rbins, -0.5, rbins - 0.5, + bins_charge, 0, bins_charge); + + h2SEPD_North_Charge_rbinv2 = new TH2F("h2SEPD_North_Charge_rbinv2", + "sEPD North; r_{bin}; Avg Charge", + rbins, -0.5, rbins - 0.5, + bins_charge, 0, bins_charge); + + hSEPD_Bad_Channels = new TProfile("h_sEPD_Bad_Channels", "sEPD Bad Channels; Channel; Status", QVecShared::SEPD_CHANNELS, -0.5, QVecShared::SEPD_CHANNELS-0.5); + + se->registerHisto(h2SEPD_South_Charge_rbin); + se->registerHisto(h2SEPD_North_Charge_rbin); + se->registerHisto(h2SEPD_South_Charge_rbinv2); + se->registerHisto(h2SEPD_North_Charge_rbinv2); + se->registerHisto(hSEPD_Bad_Channels); + + for (int channel = 0; channel < QVecShared::SEPD_CHANNELS; ++channel) + { + unsigned int key = TowerInfoDefs::encode_epd(channel); + int rbin = TowerInfoDefs::get_epd_rbin(key); + unsigned int arm = TowerInfoDefs::get_epd_arm(key); + + double avg_charge = hSEPD_Charge->GetBinContent(channel + 1); + + auto* h2 = (arm == 0) ? h2SEPD_South_Charge_rbin : h2SEPD_North_Charge_rbin; + + h2->Fill(rbin, avg_charge); + } + + auto* hSpx = h2SEPD_South_Charge_rbin->ProfileX("hSpx", 2, -1, "s"); + auto* hNpx = h2SEPD_North_Charge_rbin->ProfileX("hNpx", 2, -1, "s"); + + int ctr_dead = 0; + int ctr_hot = 0; + int ctr_cold = 0; + + for (int channel = 0; channel < QVecShared::SEPD_CHANNELS; ++channel) + { + unsigned int key = TowerInfoDefs::encode_epd(channel); + int rbin = TowerInfoDefs::get_epd_rbin(key); + unsigned int arm = TowerInfoDefs::get_epd_arm(key); + + auto* h2 = (arm == 0) ? h2SEPD_South_Charge_rbinv2 : h2SEPD_North_Charge_rbinv2; + auto* hprof = (arm == 0) ? hSpx : hNpx; + + double charge = hSEPD_Charge->GetBinContent(channel + 1); + double mean_charge = hprof->GetBinContent(rbin + 1); + double sigma = hprof->GetBinError(rbin + 1); + double zscore = 0.0; + + if (sigma > 0) + { + zscore = (charge - mean_charge) / sigma; + } + + if (charge < m_sEPD_min_avg_charge_threshold || std::abs(zscore) > m_sEPD_sigma_threshold) + { + m_bad_channels.insert(channel); + + std::string type; + QVecShared::ChannelStatus status_fill; + + // dead channel + if (charge == 0) + { + type = "Dead"; + status_fill = QVecShared::ChannelStatus::Dead; + ++ctr_dead; + } + // hot channel + else if (zscore > m_sEPD_sigma_threshold) + { + type = "Hot"; + status_fill = QVecShared::ChannelStatus::Hot; + ++ctr_hot; + } + // cold channel + else + { + type = "Cold"; + status_fill = QVecShared::ChannelStatus::Cold; + ++ctr_cold; + } + + hSEPD_Bad_Channels->Fill(channel, static_cast(status_fill)); + std::cout << std::format("{:4} Channel: {:3d}, arm: {}, rbin: {:2d}, Mean: {:5.2f}, Charge: {:5.2f}, Z-Score: {:5.2f}", + type, channel, arm, rbin, mean_charge, charge, zscore) << std::endl; + } + else + { + h2->Fill(rbin, charge); + } + } + + std::cout << "Total Bad Channels: " << m_bad_channels.size() << ", Dead: " + << ctr_dead << ", Hot: " << ctr_hot << ", Cold: " << ctr_cold << std::endl; + + std::cout << "Finished processing Hot sEPD channels" << std::endl; + return Fun4AllReturnCodes::EVENT_OK; +} + +void QVecCalib::init_hists() +{ + unsigned int bins_psi = 126; + double psi_low = -std::numbers::pi; + double psi_high = std::numbers::pi; + + Fun4AllServer *se = Fun4AllServer::instance(); + + hCentrality = new TH1F("hCentrality", "|z| < 10 cm and MB; Centrality [%]; Events", m_cent_bins, m_cent_low, m_cent_high); + se->registerHisto(hCentrality); + + std::string pass_suffix; + if (m_pass == Pass::ApplyRecentering) + { + pass_suffix = "_corr"; + } + else if (m_pass == Pass::ApplyFlattening) + { + pass_suffix = "_corr2"; + } + + // n = 2, 3, 4, etc. + for (int n : m_harmonics) + { + std::string name_S = std::format("h2_sEPD_Psi_S_{}{}", n, pass_suffix); + std::string name_N = std::format("h2_sEPD_Psi_N_{}{}", n, pass_suffix); + std::string name_NS = std::format("h2_sEPD_Psi_NS_{}{}", n, pass_suffix); + + std::string title_S = std::format("sEPD South #Psi (Order {0}); Centrality [%]; {0}#Psi^{{S}}_{{{0}}}", n); + std::string title_N = std::format("sEPD North #Psi (Order {0}); Centrality [%]; {0}#Psi^{{N}}_{{{0}}}", n); + std::string title_NS = std::format("sEPD North South #Psi (Order {0}); Centrality [%]; {0}#Psi^{{NS}}_{{{0}}}", n); + + m_hists2D[name_S] = new TH2F(name_S.c_str(), title_S.c_str(), m_cent_bins, m_cent_low, m_cent_high, bins_psi, psi_low, psi_high); + m_hists2D[name_N] = new TH2F(name_N.c_str(), title_N.c_str(), m_cent_bins, m_cent_low, m_cent_high, bins_psi, psi_low, psi_high); + m_hists2D[name_NS] = new TH2F(name_NS.c_str(), title_NS.c_str(), m_cent_bins, m_cent_low, m_cent_high, bins_psi, psi_low, psi_high); + + // South, North + for (auto det : m_subdetectors) + { + std::string det_str = (det == QVecShared::Subdetector::S) ? "S" : "N"; + std::string det_name = (det == QVecShared::Subdetector::S) ? "South" : "North"; + + std::string q_avg_sq_cross_name; + std::string q_avg_sq_cross_title = std::format("sEPD {0}; Centrality [%]; ", det_name, n); + + if (m_pass == Pass::ApplyRecentering) + { + q_avg_sq_cross_name = QVecShared::get_hist_name(det_str, "xy", n); + } + + if (m_pass == Pass::ApplyFlattening) + { + q_avg_sq_cross_name = QVecShared::get_hist_name(det_str, "xy", n, "_corr"); + } + + if (!q_avg_sq_cross_name.empty()) + { + m_profiles[q_avg_sq_cross_name] = new TProfile(q_avg_sq_cross_name.c_str(), q_avg_sq_cross_title.c_str(), + m_cent_bins, m_cent_low, m_cent_high); + } + + for (auto comp : m_components) + { + std::string comp_str = (comp == QVecShared::QComponent::X) ? "x" : "y"; + std::string name = QVecShared::get_hist_name(det_str, comp_str, n, pass_suffix); + + auto add_profile = [&](const std::string& prof_name, std::string_view label_suffix = "") + { + std::string title = std::format("sEPD {}; Centrality [%]; ", det_name, n, comp_str, label_suffix); + m_profiles[prof_name] = new TProfile(prof_name.c_str(), title.c_str(), m_cent_bins, m_cent_low, m_cent_high); + }; + + add_profile(name); + + // 2. Only generate strings and profiles for the current pass + switch (m_pass) + { + case Pass::ComputeRecentering: + { + break; + } + + case Pass::ApplyRecentering: + { + std::string name_sq = QVecShared::get_hist_name(det_str, comp_str+comp_str, n); + add_profile(name_sq, "^{2}"); + break; + } + + case Pass::ApplyFlattening: + { + std::string name_sq_corr = QVecShared::get_hist_name(det_str, comp_str+comp_str, n, "_corr"); + add_profile(name_sq_corr, "^{2}"); + break; + } + } + } + } + + // Init for Combined NS Histograms + if (m_pass == Pass::ApplyRecentering || m_pass == Pass::ApplyFlattening) + { + std::string det_str = "NS"; + + // Initialize 2nd Moment Profiles for NS (needed to compute flattening) + for (const auto* comp : {"xx", "yy", "xy"}) + { + std::string name = QVecShared::get_hist_name(det_str, comp, n); + std::string title = std::format("sEPD NS; Centrality [%]; ", n, comp); + m_profiles[name] = new TProfile(name.c_str(), title.c_str(), m_cent_bins, m_cent_low, m_cent_high); + } + + // Initialize Validation Profiles (Flattened NS) + if (m_pass == Pass::ApplyFlattening) + { + for (const auto* comp : {"xx", "yy", "xy"}) + { + std::string name = QVecShared::get_hist_name(det_str, comp, n, "_corr"); + std::string title = std::format("sEPD NS Corrected; Centrality [%]; ", n, comp); + m_profiles[name] = new TProfile(name.c_str(), title.c_str(), m_cent_bins, m_cent_low, m_cent_high); + } + } + } + } +} + +std::array, 2> QVecCalib::calculate_flattening_matrix(double xx, double yy, double xy, int n, int cent_bin, const std::string& det_label) +{ + double D_arg = (xx * yy) - (xy * xy); + if (D_arg < 1e-12) + { + std::cout << "Warning: Near-zero determinant in bin " << cent_bin << ". Skipping matrix calc." << std::endl; + return std::array, 2>{{{1, 0}, {0, 1}}}; // Return Identity + } + double D = std::sqrt(D_arg); + + double N_term = D * (xx + yy + (2 * D)); + if (N_term <= 0) + { + std::cout << "Invalid N-term (" << N_term << ") for n=" << n << ", cent=" << cent_bin + << ", det=" << det_label << std::endl; + exit(1); + } + double inv_sqrt_N = 1.0 / std::sqrt(N_term); + + std::array, 2> mat{}; + mat[0][0] = inv_sqrt_N * (yy + D); + mat[0][1] = -inv_sqrt_N * xy; + mat[1][0] = mat[0][1]; + mat[1][1] = inv_sqrt_N * (xx + D); + return mat; +} + +template +T* QVecCalib::load_and_clone(TFile* file, const std::string& name) { + T *obj {nullptr}; + file->GetObject(name.c_str(),obj); + if (!obj) + { + std::cout << "Could not find histogram " << name << " in file " << file->GetName() << std::endl; + exit(1); + } + return static_cast(obj->Clone()); +} + +int QVecCalib::load_correction_data() +{ + Fun4AllServer *se = Fun4AllServer::instance(); + auto* file = TFile::Open(m_input_Q_calib.c_str()); + + if (!file || file->IsZombie()) + { + std::cout << PHWHERE << "Error! Cannot open: " << m_input_Q_calib << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + int n = m_harmonics[h_idx]; + + // Helper to load and register histograms automatically + auto load_reg = [&](const std::string& det, const std::string& var, const std::string& suffix = "") + { + std::string name = QVecShared::get_hist_name(det, var, n, suffix); + m_profiles[name] = load_and_clone(file, name); + se->registerHisto(m_profiles[name]); + return name; + }; + + // Load standard Recentering averages for S and N + std::string s_names[2][2]; // [det][comp] + for (int d = 0; d < 2; ++d) + { + std::string det_str = (d == 0) ? "S" : "N"; + s_names[d][0] = load_reg(det_str, "x"); + s_names[d][1] = load_reg(det_str, "y"); + } + + // Load Flattening (2nd moment) data if needed + if (m_pass == Pass::ApplyFlattening) + { + for (const auto& det_str : {"S", "N", "NS"}) + { + for (const auto& var : {"xx", "yy", "xy"}) + { + load_reg(det_str, var); + } + } + } + + // Populate the CorrectionData matrix + for (size_t cent_bin = 0; cent_bin < m_cent_bins; ++cent_bin) + { + int bin = static_cast(cent_bin) + 1; + + // Populate Recentering (S, N) + for (int d = 0; d < 2; ++d) + { + m_correction_data[cent_bin][h_idx][d].avg_Q = {m_profiles[s_names[d][0]]->GetBinContent(bin), m_profiles[s_names[d][1]]->GetBinContent(bin)}; + } + + if (m_pass == Pass::ApplyFlattening) + { + // Populate Flattening for S, N, and NS + for (int d = 0; d < (int) QVecShared::Subdetector::Count; ++d) + { + std::string det_str; + switch (d) + { + case 0: + det_str = "S"; + break; + case 1: + det_str = "N"; + break; + default: + det_str = "NS"; + break; + } + + double xx = m_profiles[QVecShared::get_hist_name(det_str, "xx", n)]->GetBinContent(bin); + double yy = m_profiles[QVecShared::get_hist_name(det_str, "yy", n)]->GetBinContent(bin); + double xy = m_profiles[QVecShared::get_hist_name(det_str, "xy", n)]->GetBinContent(bin); + + auto& data = m_correction_data[cent_bin][h_idx][d]; + data.X_matrix = calculate_flattening_matrix(xx, yy, xy, n, cent_bin, det_str); + data.avg_Q_xx = xx; + data.avg_Q_yy = yy; + data.avg_Q_xy = xy; + } + } + } + } + + file->Close(); + delete file; + return Fun4AllReturnCodes::EVENT_OK; +} + +void QVecCalib::prepare_average_hists() +{ + Fun4AllServer *se = Fun4AllServer::instance(); + + for (int n : m_harmonics) + { + std::string S_x_avg_name = QVecShared::get_hist_name("S", "x", n); + std::string S_y_avg_name = QVecShared::get_hist_name("S", "y", n); + std::string N_x_avg_name = QVecShared::get_hist_name("N", "x", n); + std::string N_y_avg_name = QVecShared::get_hist_name("N", "y", n); + + std::string psi_S_name = std::format("h2_sEPD_Psi_S_{}", n); + std::string psi_N_name = std::format("h2_sEPD_Psi_N_{}", n); + std::string psi_NS_name = std::format("h2_sEPD_Psi_NS_{}", n); + + AverageHists h; + + h.S_x_avg = m_profiles.at(S_x_avg_name); + h.S_y_avg = m_profiles.at(S_y_avg_name); + h.N_x_avg = m_profiles.at(N_x_avg_name); + h.N_y_avg = m_profiles.at(N_y_avg_name); + + h.Psi_S = m_hists2D.at(psi_S_name); + h.Psi_N = m_hists2D.at(psi_N_name); + h.Psi_NS = m_hists2D.at(psi_NS_name); + + se->registerHisto(h.S_x_avg); + se->registerHisto(h.S_y_avg); + se->registerHisto(h.N_x_avg); + se->registerHisto(h.N_y_avg); + + se->registerHisto(h.Psi_S); + se->registerHisto(h.Psi_N); + se->registerHisto(h.Psi_NS); + + m_average_hists.push_back(h); + } +} + +void QVecCalib::prepare_recenter_hists() +{ + Fun4AllServer *se = Fun4AllServer::instance(); + + for (int n : m_harmonics) + { + std::string S_x_corr_avg_name = QVecShared::get_hist_name("S", "x", n, "_corr"); + std::string S_y_corr_avg_name = QVecShared::get_hist_name("S", "y", n, "_corr"); + std::string N_x_corr_avg_name = QVecShared::get_hist_name("N", "x", n, "_corr"); + std::string N_y_corr_avg_name = QVecShared::get_hist_name("N", "y", n, "_corr"); + + std::string S_xx_avg_name = QVecShared::get_hist_name("S", "xx", n); + std::string S_yy_avg_name = QVecShared::get_hist_name("S", "yy", n); + std::string S_xy_avg_name = QVecShared::get_hist_name("S", "xy", n); + std::string N_xx_avg_name = QVecShared::get_hist_name("N", "xx", n); + std::string N_yy_avg_name = QVecShared::get_hist_name("N", "yy", n); + std::string N_xy_avg_name = QVecShared::get_hist_name("N", "xy", n); + + std::string NS_xx_avg_name = QVecShared::get_hist_name("NS", "xx", n); + std::string NS_yy_avg_name = QVecShared::get_hist_name("NS", "yy", n); + std::string NS_xy_avg_name = QVecShared::get_hist_name("NS", "xy", n); + + std::string psi_S_name = std::format("h2_sEPD_Psi_S_{}_corr", n); + std::string psi_N_name = std::format("h2_sEPD_Psi_N_{}_corr", n); + std::string psi_NS_name = std::format("h2_sEPD_Psi_NS_{}_corr", n); + + RecenterHists h; + + h.S_x_corr_avg = m_profiles.at(S_x_corr_avg_name); + h.S_y_corr_avg = m_profiles.at(S_y_corr_avg_name); + h.N_x_corr_avg = m_profiles.at(N_x_corr_avg_name); + h.N_y_corr_avg = m_profiles.at(N_y_corr_avg_name); + + h.S_xx_avg = m_profiles.at(S_xx_avg_name); + h.S_yy_avg = m_profiles.at(S_yy_avg_name); + h.S_xy_avg = m_profiles.at(S_xy_avg_name); + + h.N_xx_avg = m_profiles.at(N_xx_avg_name); + h.N_yy_avg = m_profiles.at(N_yy_avg_name); + h.N_xy_avg = m_profiles.at(N_xy_avg_name); + + h.NS_xx_avg = m_profiles.at(NS_xx_avg_name); + h.NS_yy_avg = m_profiles.at(NS_yy_avg_name); + h.NS_xy_avg = m_profiles.at(NS_xy_avg_name); + + h.Psi_S_corr = m_hists2D.at(psi_S_name); + h.Psi_N_corr = m_hists2D.at(psi_N_name); + h.Psi_NS_corr = m_hists2D.at(psi_NS_name); + + se->registerHisto(h.S_x_corr_avg); + se->registerHisto(h.S_y_corr_avg); + se->registerHisto(h.N_x_corr_avg); + se->registerHisto(h.N_y_corr_avg); + + se->registerHisto(h.S_xx_avg); + se->registerHisto(h.S_yy_avg); + se->registerHisto(h.S_xy_avg); + + se->registerHisto(h.N_xx_avg); + se->registerHisto(h.N_yy_avg); + se->registerHisto(h.N_xy_avg); + + se->registerHisto(h.NS_xx_avg); + se->registerHisto(h.NS_yy_avg); + se->registerHisto(h.NS_xy_avg); + + se->registerHisto(h.Psi_S_corr); + se->registerHisto(h.Psi_N_corr); + se->registerHisto(h.Psi_NS_corr); + + m_recenter_hists.push_back(h); + } +} + +void QVecCalib::prepare_flattening_hists() +{ + Fun4AllServer *se = Fun4AllServer::instance(); + + for (int n : m_harmonics) + { + std::string S_x_corr2_avg_name = QVecShared::get_hist_name("S", "x", n, "_corr2"); + std::string S_y_corr2_avg_name = QVecShared::get_hist_name("S", "y", n, "_corr2"); + std::string N_x_corr2_avg_name = QVecShared::get_hist_name("N", "x", n, "_corr2"); + std::string N_y_corr2_avg_name = QVecShared::get_hist_name("N", "y", n, "_corr2"); + + std::string S_xx_corr_avg_name = QVecShared::get_hist_name("S", "xx", n, "_corr"); + std::string S_yy_corr_avg_name = QVecShared::get_hist_name("S", "yy", n, "_corr"); + std::string S_xy_corr_avg_name = QVecShared::get_hist_name("S", "xy", n, "_corr"); + std::string N_xx_corr_avg_name = QVecShared::get_hist_name("N", "xx", n, "_corr"); + std::string N_yy_corr_avg_name = QVecShared::get_hist_name("N", "yy", n, "_corr"); + std::string N_xy_corr_avg_name = QVecShared::get_hist_name("N", "xy", n, "_corr"); + + std::string NS_xx_corr_avg_name = QVecShared::get_hist_name("NS", "xx", n, "_corr"); + std::string NS_yy_corr_avg_name = QVecShared::get_hist_name("NS", "yy", n, "_corr"); + std::string NS_xy_corr_avg_name = QVecShared::get_hist_name("NS", "xy", n, "_corr"); + + std::string psi_S_name = std::format("h2_sEPD_Psi_S_{}_corr2", n); + std::string psi_N_name = std::format("h2_sEPD_Psi_N_{}_corr2", n); + std::string psi_NS_name = std::format("h2_sEPD_Psi_NS_{}_corr2", n); + + FlatteningHists h; + + h.S_x_corr2_avg = m_profiles.at(S_x_corr2_avg_name); + h.S_y_corr2_avg = m_profiles.at(S_y_corr2_avg_name); + h.N_x_corr2_avg = m_profiles.at(N_x_corr2_avg_name); + h.N_y_corr2_avg = m_profiles.at(N_y_corr2_avg_name); + + h.S_xx_corr_avg = m_profiles.at(S_xx_corr_avg_name); + h.S_yy_corr_avg = m_profiles.at(S_yy_corr_avg_name); + h.S_xy_corr_avg = m_profiles.at(S_xy_corr_avg_name); + + h.N_xx_corr_avg = m_profiles.at(N_xx_corr_avg_name); + h.N_yy_corr_avg = m_profiles.at(N_yy_corr_avg_name); + h.N_xy_corr_avg = m_profiles.at(N_xy_corr_avg_name); + + h.NS_xx_corr_avg = m_profiles.at(NS_xx_corr_avg_name); + h.NS_yy_corr_avg = m_profiles.at(NS_yy_corr_avg_name); + h.NS_xy_corr_avg = m_profiles.at(NS_xy_corr_avg_name); + + h.Psi_S_corr2 = m_hists2D.at(psi_S_name); + h.Psi_N_corr2 = m_hists2D.at(psi_N_name); + h.Psi_NS_corr2 = m_hists2D.at(psi_NS_name); + + se->registerHisto(h.S_x_corr2_avg); + se->registerHisto(h.S_y_corr2_avg); + se->registerHisto(h.N_x_corr2_avg); + se->registerHisto(h.N_y_corr2_avg); + + se->registerHisto(h.S_xx_corr_avg); + se->registerHisto(h.S_yy_corr_avg); + se->registerHisto(h.S_xy_corr_avg); + + se->registerHisto(h.N_xx_corr_avg); + se->registerHisto(h.N_yy_corr_avg); + se->registerHisto(h.N_xy_corr_avg); + + se->registerHisto(h.NS_xx_corr_avg); + se->registerHisto(h.NS_yy_corr_avg); + se->registerHisto(h.NS_xy_corr_avg); + + se->registerHisto(h.Psi_S_corr2); + se->registerHisto(h.Psi_N_corr2); + se->registerHisto(h.Psi_NS_corr2); + + m_flattening_hists.push_back(h); + } +} + +int QVecCalib::InitRun(PHCompositeNode *topNode) +{ + RunHeader* run_header = findNode::getClass(topNode, "RunHeader"); + if (!run_header) + { + std::cout << PHWHERE << "RunHeader Node missing." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + m_runnumber = run_header->get_RunNumber(); + + EpdGeom* epdgeom = findNode::getClass(topNode, "TOWERGEOM_EPD"); + if (!epdgeom) + { + std::cout << PHWHERE << "TOWERGEOM_EPD Node missing." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + m_trig_cache.assign(m_harmonics.size(), std::vector>(QVecShared::SEPD_CHANNELS)); + + for (int channel = 0; channel < QVecShared::SEPD_CHANNELS; ++channel) + { + unsigned int key = TowerInfoDefs::encode_epd(channel); + double phi = epdgeom->get_phi(key); + + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + int n = m_harmonics[h_idx]; + m_trig_cache[h_idx][channel] = {std::cos(n * phi), std::sin(n * phi)}; + } + } + + std::cout << "QVecCalib::InitRun - Trigonometry cache initialized for " + << QVecShared::SEPD_CHANNELS << " channels." << std::endl; + + return Fun4AllReturnCodes::EVENT_OK; +} + +void QVecCalib::process_averages(double cent, const QVecShared::QVec& q_S, const QVecShared::QVec& q_N, const AverageHists& h) +{ + double psi_S = std::atan2(q_S.y, q_S.x); + double psi_N = std::atan2(q_N.y, q_N.x); + double psi_NS = std::atan2(q_S.y + q_N.y, q_S.x + q_N.x); + + h.S_x_avg->Fill(cent, q_S.x); + h.S_y_avg->Fill(cent, q_S.y); + h.N_x_avg->Fill(cent, q_N.x); + h.N_y_avg->Fill(cent, q_N.y); + + h.Psi_S->Fill(cent, psi_S); + h.Psi_N->Fill(cent, psi_N); + h.Psi_NS->Fill(cent, psi_NS); +} + +void QVecCalib::process_recentering(double cent, size_t h_idx, const QVecShared::QVec& q_S, const QVecShared::QVec& q_N, const RecenterHists& h) +{ + int cent_bin = hCentrality->FindBin(cent) - 1; + + const auto& S = m_correction_data[cent_bin][h_idx][(size_t) QVecShared::Subdetector::S]; + const auto& N = m_correction_data[cent_bin][h_idx][(size_t) QVecShared::Subdetector::N]; + + double Q_S_x_avg = S.avg_Q.x; + double Q_S_y_avg = S.avg_Q.y; + double Q_N_x_avg = N.avg_Q.x; + double Q_N_y_avg = N.avg_Q.y; + + QVecShared::QVec q_S_corr = {q_S.x - Q_S_x_avg, q_S.y - Q_S_y_avg}; + QVecShared::QVec q_N_corr = {q_N.x - Q_N_x_avg, q_N.y - Q_N_y_avg}; + + // Construct Combined Recentered Vector + // We use the sum of the individually recentered vectors + QVecShared::QVec q_NS_corr = {q_S_corr.x + q_N_corr.x, q_S_corr.y + q_N_corr.y}; + + double psi_S_corr = std::atan2(q_S_corr.y, q_S_corr.x); + double psi_N_corr = std::atan2(q_N_corr.y, q_N_corr.x); + double psi_NS_corr = std::atan2(q_NS_corr.y, q_NS_corr.x); + + h.S_x_corr_avg->Fill(cent, q_S_corr.x); + h.S_y_corr_avg->Fill(cent, q_S_corr.y); + h.N_x_corr_avg->Fill(cent, q_N_corr.x); + h.N_y_corr_avg->Fill(cent, q_N_corr.y); + + h.S_xx_avg->Fill(cent, q_S_corr.x * q_S_corr.x); + h.S_yy_avg->Fill(cent, q_S_corr.y * q_S_corr.y); + h.S_xy_avg->Fill(cent, q_S_corr.x * q_S_corr.y); + h.N_xx_avg->Fill(cent, q_N_corr.x * q_N_corr.x); + h.N_yy_avg->Fill(cent, q_N_corr.y * q_N_corr.y); + h.N_xy_avg->Fill(cent, q_N_corr.x * q_N_corr.y); + + h.NS_xx_avg->Fill(cent, q_NS_corr.x * q_NS_corr.x); + h.NS_yy_avg->Fill(cent, q_NS_corr.y * q_NS_corr.y); + h.NS_xy_avg->Fill(cent, q_NS_corr.x * q_NS_corr.y); + + h.Psi_S_corr->Fill(cent, psi_S_corr); + h.Psi_N_corr->Fill(cent, psi_N_corr); + h.Psi_NS_corr->Fill(cent, psi_NS_corr); +} + +void QVecCalib::process_flattening(double cent, size_t h_idx, const QVecShared::QVec& q_S, const QVecShared::QVec& q_N, const FlatteningHists& h) +{ + int cent_bin = hCentrality->FindBin(cent) - 1; + + const auto& S = m_correction_data[cent_bin][h_idx][(size_t) QVecShared::Subdetector::S]; + const auto& N = m_correction_data[cent_bin][h_idx][(size_t) QVecShared::Subdetector::N]; + const auto& NS = m_correction_data[cent_bin][h_idx][(size_t) QVecShared::Subdetector::NS]; + + double Q_S_x_avg = S.avg_Q.x; + double Q_S_y_avg = S.avg_Q.y; + double Q_N_x_avg = N.avg_Q.x; + double Q_N_y_avg = N.avg_Q.y; + + QVecShared::QVec q_S_corr = {q_S.x - Q_S_x_avg, q_S.y - Q_S_y_avg}; + QVecShared::QVec q_N_corr = {q_N.x - Q_N_x_avg, q_N.y - Q_N_y_avg}; + + // Construct Combined Recentered Vector + QVecShared::QVec q_NS_corr = {q_S_corr.x + q_N_corr.x, q_S_corr.y + q_N_corr.y}; + + const auto& X_S = S.X_matrix; + const auto& X_N = N.X_matrix; + const auto& X_NS = NS.X_matrix; + + double Q_S_x_corr2 = X_S[0][0] * q_S_corr.x + X_S[0][1] * q_S_corr.y; + double Q_S_y_corr2 = X_S[1][0] * q_S_corr.x + X_S[1][1] * q_S_corr.y; + double Q_N_x_corr2 = X_N[0][0] * q_N_corr.x + X_N[0][1] * q_N_corr.y; + double Q_N_y_corr2 = X_N[1][0] * q_N_corr.x + X_N[1][1] * q_N_corr.y; + + double Q_NS_x_corr2 = X_NS[0][0] * q_NS_corr.x + X_NS[0][1] * q_NS_corr.y; + double Q_NS_y_corr2 = X_NS[1][0] * q_NS_corr.x + X_NS[1][1] * q_NS_corr.y; + + QVecShared::QVec q_S_corr2 = {Q_S_x_corr2, Q_S_y_corr2}; + QVecShared::QVec q_N_corr2 = {Q_N_x_corr2, Q_N_y_corr2}; + QVecShared::QVec q_NS_corr2 = {Q_NS_x_corr2, Q_NS_y_corr2}; + + double psi_S = std::atan2(q_S_corr2.y, q_S_corr2.x); + double psi_N = std::atan2(q_N_corr2.y, q_N_corr2.x); + double psi_NS = std::atan2(q_NS_corr2.y, q_NS_corr2.x); + + h.S_x_corr2_avg->Fill(cent, q_S_corr2.x); + h.S_y_corr2_avg->Fill(cent, q_S_corr2.y); + h.N_x_corr2_avg->Fill(cent, q_N_corr2.x); + h.N_y_corr2_avg->Fill(cent, q_N_corr2.y); + + h.S_xx_corr_avg->Fill(cent, q_S_corr2.x * q_S_corr2.x); + h.S_yy_corr_avg->Fill(cent, q_S_corr2.y * q_S_corr2.y); + h.S_xy_corr_avg->Fill(cent, q_S_corr2.x * q_S_corr2.y); + h.N_xx_corr_avg->Fill(cent, q_N_corr2.x * q_N_corr2.x); + h.N_yy_corr_avg->Fill(cent, q_N_corr2.y * q_N_corr2.y); + h.N_xy_corr_avg->Fill(cent, q_N_corr2.x * q_N_corr2.y); + + h.NS_xx_corr_avg->Fill(cent, q_NS_corr2.x * q_NS_corr2.x); + h.NS_yy_corr_avg->Fill(cent, q_NS_corr2.y * q_NS_corr2.y); + h.NS_xy_corr_avg->Fill(cent, q_NS_corr2.x * q_NS_corr2.y); + + h.Psi_S_corr2->Fill(cent, psi_S); + h.Psi_N_corr2->Fill(cent, psi_N); + h.Psi_NS_corr2->Fill(cent, psi_NS); +} + +bool QVecCalib::process_sEPD() +{ + double sepd_total_charge_south = 0; + double sepd_total_charge_north = 0; + + // Loop over all sEPD Channels + for (int channel = 0; channel < QVecShared::SEPD_CHANNELS; ++channel) + { + double charge = m_evtdata->get_sepd_charge(channel); + + // Skip Bad Channels + if (m_bad_channels.contains(channel) || charge <= 0) + { + continue; + } + + unsigned int key = TowerInfoDefs::encode_epd(channel); + unsigned int arm = TowerInfoDefs::get_epd_arm(key); + + // arm = 0: South + // arm = 1: North + if (arm == 0) + { + sepd_total_charge_south += charge; + } + else + { + sepd_total_charge_north += charge; + } + + // Compute Raw Q vectors for each harmonic and respective arm + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + // Optimized lookup instead of std::cos/std::sin calls + const auto& [cached_cos, cached_sin] = m_trig_cache[h_idx][channel]; + + m_q_vectors[h_idx][arm].x += charge * cached_cos; + m_q_vectors[h_idx][arm].y += charge * cached_sin; + } + } + + // Skip Events with Zero sEPD Total Charge in either arm + if (sepd_total_charge_south == 0 || sepd_total_charge_north == 0) + { + return false; + } + + // Normalize the Q-vectors by total charge + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + for (auto det : m_subdetectors) + { + size_t det_idx = (det == QVecShared::Subdetector::S) ? 0 : 1; + double sepd_total_charge = (det_idx == 0) ? sepd_total_charge_south : sepd_total_charge_north; + m_q_vectors[h_idx][det_idx].x /= sepd_total_charge; + m_q_vectors[h_idx][det_idx].y /= sepd_total_charge; + } + } + + return true; +} + +bool QVecCalib::process_event_check() +{ + double cent = m_evtdata->get_event_centrality(); + int cent_bin = hSEPD_Charge_Min->FindBin(cent); + + double sepd_totalcharge = m_evtdata->get_sepd_totalcharge(); + + double sepd_totalcharge_min = hSEPD_Charge_Min->GetBinContent(cent_bin); + double sepd_totalcharge_max = hSEPD_Charge_Max->GetBinContent(cent_bin); + + return sepd_totalcharge > sepd_totalcharge_min && sepd_totalcharge < sepd_totalcharge_max; +} + +//____________________________________________________________________________.. +int QVecCalib::process_event(PHCompositeNode *topNode) +{ + m_evtdata = findNode::getClass(topNode, "EventPlaneData"); + if (!m_evtdata) + { + std::cout << PHWHERE << "EventPlaneData Node missing." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + int event_id = m_evtdata->get_event_id(); + + if (Verbosity() && m_event % PROGRESS_REPORT_INTERVAL == 0) + { + std::cout << "Progress: " << m_event << ", Global: " << event_id << std::endl; + } + ++m_event; + + double cent = m_evtdata->get_event_centrality(); + + bool isGood = process_event_check(); + + // Skip Events with non correlation between centrality and sEPD + if (!isGood) + { + ++m_event_counters.bad_centrality_sepd_correlation; + return Fun4AllReturnCodes::ABORTEVENT; + } + + isGood = process_sEPD(); + + // Skip Events with Zero sEPD Total Charge in either arm + if (!isGood) + { + ++m_event_counters.zero_sepd_total_charge; + return Fun4AllReturnCodes::ABORTEVENT; + } + + hCentrality->Fill(cent); + + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + const auto& q_S = m_q_vectors[h_idx][0]; // 0 for South + const auto& q_N = m_q_vectors[h_idx][1]; // 1 for North + + // --- First Pass: Derive 1st Order --- + if (m_pass == Pass::ComputeRecentering) + { + process_averages(cent, q_S, q_N, m_average_hists[h_idx]); + } + + // --- Second Pass: Apply 1st Order, Derive 2nd Order --- + else if (m_pass == Pass::ApplyRecentering) + { + process_recentering(cent, h_idx, q_S, q_N, m_recenter_hists[h_idx]); + } + + // --- Third Pass: Apply 2nd Order, Validate --- + else if (m_pass == Pass::ApplyFlattening) + { + process_flattening(cent, h_idx, q_S, q_N, m_flattening_hists[h_idx]); + } + } + + return Fun4AllReturnCodes::EVENT_OK; +} + +//____________________________________________________________________________.. +int QVecCalib::ResetEvent(PHCompositeNode * /*topNode*/) +{ + m_q_vectors = {}; + + return Fun4AllReturnCodes::EVENT_OK; +} + +void QVecCalib::compute_averages(size_t cent_bin, int h_idx) +{ + int n = m_harmonics[h_idx]; + + std::string S_x_avg_name = QVecShared::get_hist_name("S", "x", n); + std::string S_y_avg_name = QVecShared::get_hist_name("S", "y", n); + std::string N_x_avg_name = QVecShared::get_hist_name("N", "x", n); + std::string N_y_avg_name = QVecShared::get_hist_name("N", "y", n); + + int bin = cent_bin + 1; + + double Q_S_x_avg = m_profiles[S_x_avg_name]->GetBinContent(bin); + double Q_S_y_avg = m_profiles[S_y_avg_name]->GetBinContent(bin); + double Q_N_x_avg = m_profiles[N_x_avg_name]->GetBinContent(bin); + double Q_N_y_avg = m_profiles[N_y_avg_name]->GetBinContent(bin); + + m_correction_data[cent_bin][h_idx][static_cast(QVecShared::Subdetector::S)].avg_Q = {Q_S_x_avg, Q_S_y_avg}; + m_correction_data[cent_bin][h_idx][static_cast(QVecShared::Subdetector::N)].avg_Q = {Q_N_x_avg, Q_N_y_avg}; + + std::cout << std::format( + "Centrality Bin: {}, " + "Harmonic: {}, " + "Q_S_x_avg: {:13.10f}, " + "Q_S_y_avg: {:13.10f}, " + "Q_N_x_avg: {:13.10f}, " + "Q_N_y_avg: {:13.10f}", + cent_bin, + n, + Q_S_x_avg, + Q_S_y_avg, + Q_N_x_avg, + Q_N_y_avg) << std::endl; +} + +void QVecCalib::compute_recentering(size_t cent_bin, int h_idx) +{ + int n = m_harmonics[h_idx]; + + std::string S_x_corr_avg_name = QVecShared::get_hist_name("S", "x", n, "_corr"); + std::string S_y_corr_avg_name = QVecShared::get_hist_name("S", "y", n, "_corr"); + std::string N_x_corr_avg_name = QVecShared::get_hist_name("N", "x", n, "_corr"); + std::string N_y_corr_avg_name = QVecShared::get_hist_name("N", "y", n, "_corr"); + + int bin = cent_bin + 1; + + double Q_S_x_corr_avg = m_profiles[S_x_corr_avg_name]->GetBinContent(bin); + double Q_S_y_corr_avg = m_profiles[S_y_corr_avg_name]->GetBinContent(bin); + double Q_N_x_corr_avg = m_profiles[N_x_corr_avg_name]->GetBinContent(bin); + double Q_N_y_corr_avg = m_profiles[N_y_corr_avg_name]->GetBinContent(bin); + + // -- Compute 2nd Order Correction -- + std::string S_xx_avg_name = QVecShared::get_hist_name("S", "xx", n); + std::string S_yy_avg_name = QVecShared::get_hist_name("S", "yy", n); + std::string S_xy_avg_name = QVecShared::get_hist_name("S", "xy", n); + std::string N_xx_avg_name = QVecShared::get_hist_name("N", "xx", n); + std::string N_yy_avg_name = QVecShared::get_hist_name("N", "yy", n); + std::string N_xy_avg_name = QVecShared::get_hist_name("N", "xy", n); + + double Q_S_xx_avg = m_profiles[S_xx_avg_name]->GetBinContent(bin); + double Q_S_yy_avg = m_profiles[S_yy_avg_name]->GetBinContent(bin); + double Q_S_xy_avg = m_profiles[S_xy_avg_name]->GetBinContent(bin); + double Q_N_xx_avg = m_profiles[N_xx_avg_name]->GetBinContent(bin); + double Q_N_yy_avg = m_profiles[N_yy_avg_name]->GetBinContent(bin); + double Q_N_xy_avg = m_profiles[N_xy_avg_name]->GetBinContent(bin); + + // -- Compute NS Matrix -- + std::string NS_xx_avg_name = QVecShared::get_hist_name("NS", "xx", n); + std::string NS_yy_avg_name = QVecShared::get_hist_name("NS", "yy", n); + std::string NS_xy_avg_name = QVecShared::get_hist_name("NS", "xy", n); + + double Q_NS_xx_avg = m_profiles[NS_xx_avg_name]->GetBinContent(bin); + double Q_NS_yy_avg = m_profiles[NS_yy_avg_name]->GetBinContent(bin); + double Q_NS_xy_avg = m_profiles[NS_xy_avg_name]->GetBinContent(bin); + + m_correction_data[cent_bin][h_idx][static_cast(QVecShared::Subdetector::NS)].X_matrix = calculate_flattening_matrix(Q_NS_xx_avg, Q_NS_yy_avg, Q_NS_xy_avg, n, cent_bin, "NS"); + + for (size_t det_idx = 0; det_idx < 2; ++det_idx) + { + double xx = (det_idx == 0) ? Q_S_xx_avg : Q_N_xx_avg; + double yy = (det_idx == 0) ? Q_S_yy_avg : Q_N_yy_avg; + double xy = (det_idx == 0) ? Q_S_xy_avg : Q_N_xy_avg; + + std::string label = (det_idx == 0) ? "S" : "N"; + + m_correction_data[cent_bin][h_idx][det_idx].X_matrix = calculate_flattening_matrix(xx, yy, xy, n, cent_bin, label); + } + + std::cout << std::format( + "Centrality Bin: {}, " + "Harmonic: {}, " + "Q_S_x_corr_avg: {:13.10f}, " + "Q_S_y_corr_avg: {:13.10f}, " + "Q_N_x_corr_avg: {:13.10f}, " + "Q_N_y_corr_avg: {:13.10f}, " + "Q_S_xx_avg / Q_S_yy_avg: {:13.10f}, " + "Q_N_xx_avg / Q_N_yy_avg: {:13.10f}, " + "Q_NS_xx_avg / Q_NS_yy_avg: {:13.10f}, " + "Q_S_xy_avg: {:13.10f}, " + "Q_N_xy_avg: {:13.10f}, " + "Q_NS_xy_avg: {:13.10f}", + cent_bin, + n, + Q_S_x_corr_avg, + Q_S_y_corr_avg, + Q_N_x_corr_avg, + Q_N_y_corr_avg, + Q_S_xx_avg / Q_S_yy_avg, + Q_N_xx_avg / Q_N_yy_avg, + Q_NS_xx_avg / Q_NS_yy_avg, + Q_S_xy_avg, + Q_N_xy_avg, + Q_NS_xy_avg) << std::endl; +} + +void QVecCalib::print_flattening(size_t cent_bin, int n) const +{ + std::string S_x_corr2_avg_name = QVecShared::get_hist_name("S", "x", n, "_corr2"); + std::string S_y_corr2_avg_name = QVecShared::get_hist_name("S", "y", n, "_corr2"); + std::string N_x_corr2_avg_name = QVecShared::get_hist_name("N", "x", n, "_corr2"); + std::string N_y_corr2_avg_name = QVecShared::get_hist_name("N", "y", n, "_corr2"); + + std::string S_xx_corr_avg_name = QVecShared::get_hist_name("S", "xx", n, "_corr"); + std::string S_yy_corr_avg_name = QVecShared::get_hist_name("S", "yy", n, "_corr"); + std::string S_xy_corr_avg_name = QVecShared::get_hist_name("S", "xy", n, "_corr"); + std::string N_xx_corr_avg_name = QVecShared::get_hist_name("N", "xx", n, "_corr"); + std::string N_yy_corr_avg_name = QVecShared::get_hist_name("N", "yy", n, "_corr"); + std::string N_xy_corr_avg_name = QVecShared::get_hist_name("N", "xy", n, "_corr"); + + std::string NS_xx_corr_avg_name = QVecShared::get_hist_name("NS", "xx", n, "_corr"); + std::string NS_yy_corr_avg_name = QVecShared::get_hist_name("NS", "yy", n, "_corr"); + std::string NS_xy_corr_avg_name = QVecShared::get_hist_name("NS", "xy", n, "_corr"); + + int bin = cent_bin + 1; + + double Q_S_x_corr2_avg = m_profiles.at(S_x_corr2_avg_name)->GetBinContent(bin); + double Q_S_y_corr2_avg = m_profiles.at(S_y_corr2_avg_name)->GetBinContent(bin); + double Q_N_x_corr2_avg = m_profiles.at(N_x_corr2_avg_name)->GetBinContent(bin); + double Q_N_y_corr2_avg = m_profiles.at(N_y_corr2_avg_name)->GetBinContent(bin); + + double Q_S_xx_corr_avg = m_profiles.at(S_xx_corr_avg_name)->GetBinContent(bin); + double Q_S_yy_corr_avg = m_profiles.at(S_yy_corr_avg_name)->GetBinContent(bin); + double Q_S_xy_corr_avg = m_profiles.at(S_xy_corr_avg_name)->GetBinContent(bin); + double Q_N_xx_corr_avg = m_profiles.at(N_xx_corr_avg_name)->GetBinContent(bin); + double Q_N_yy_corr_avg = m_profiles.at(N_yy_corr_avg_name)->GetBinContent(bin); + double Q_N_xy_corr_avg = m_profiles.at(N_xy_corr_avg_name)->GetBinContent(bin); + + double Q_NS_xx_corr_avg = m_profiles.at(NS_xx_corr_avg_name)->GetBinContent(bin); + double Q_NS_yy_corr_avg = m_profiles.at(NS_yy_corr_avg_name)->GetBinContent(bin); + double Q_NS_xy_corr_avg = m_profiles.at(NS_xy_corr_avg_name)->GetBinContent(bin); + + std::cout << std::format( + "Centrality Bin: {}, " + "Harmonic: {}, " + "Q_S_x_corr2_avg: {:13.10f}, " + "Q_S_y_corr2_avg: {:13.10f}, " + "Q_N_x_corr2_avg: {:13.10f}, " + "Q_N_y_corr2_avg: {:13.10f}, " + "Q_S_xx_corr_avg / Q_S_yy_corr_avg: {:13.10f}, " + "Q_N_xx_corr_avg / Q_N_yy_corr_avg: {:13.10f}, " + "Q_NS_xx_corr_avg / Q_NS_yy_corr_avg: {:13.10f}, " + "Q_S_xy_corr_avg: {:13.10f}, " + "Q_N_xy_corr_avg: {:13.10f}, " + "Q_NS_xy_corr_avg: {:13.10f}", + cent_bin, + n, + Q_S_x_corr2_avg, + Q_S_y_corr2_avg, + Q_N_x_corr2_avg, + Q_N_y_corr2_avg, + Q_S_xx_corr_avg / Q_S_yy_corr_avg, + Q_N_xx_corr_avg / Q_N_yy_corr_avg, + Q_NS_xx_corr_avg / Q_NS_yy_corr_avg, + Q_S_xy_corr_avg, + Q_N_xy_corr_avg, + Q_NS_xy_corr_avg) << std::endl; +} + +void QVecCalib::write_cdb() +{ + std::error_code ec; + if (std::filesystem::create_directories(m_cdb_output_dir, ec)) + { + std::cout << "Success: Directory " << m_cdb_output_dir << " created" << std::endl; + } + else if (ec) + { + std::cout << "Failed to create directory " << m_cdb_output_dir << ": " << ec.message() << std::endl; + exit(1); + } + else + { + std::cout << "Info: Directory " << m_cdb_output_dir << " already exists." << std::endl; + } + + write_cdb_BadTowers(); + write_cdb_EventPlane(); +} + +void QVecCalib::write_cdb_BadTowers() +{ + std::cout << "Writing Bad Towers CDB" << std::endl; + + std::string payload = "SEPD_HotMap"; + std::string fieldname_status = "status"; + std::string fieldname_sigma = "SEPD_sigma"; + std::string output_file = std::format("{}/{}-{}-{}.root", m_cdb_output_dir, payload, m_dst_tag, m_runnumber); + + CDBTTree cdbttree(output_file); + + for (int channel = 0; channel < QVecShared::SEPD_CHANNELS; ++channel) + { + unsigned int key = TowerInfoDefs::encode_epd(channel); + int status = hSEPD_Bad_Channels->GetBinContent(channel+1); + + float sigma = 0; + + // Hot + if (status == static_cast(QVecShared::ChannelStatus::Hot)) + { + sigma = SIGMA_HOT; + } + + // Cold + else if (status == static_cast(QVecShared::ChannelStatus::Cold)) + { + sigma = SIGMA_COLD; + } + + cdbttree.SetIntValue(key, fieldname_status, status); + cdbttree.SetFloatValue(key, fieldname_sigma, sigma); + } + + std::cout << "Saving CDB: " << payload << " to " << output_file << std::endl; + + cdbttree.Commit(); + cdbttree.WriteCDBTTree(); +} + +void QVecCalib::write_cdb_EventPlane() +{ + std::cout << "Writing Event Plane CDB" << std::endl; + + std::string payload = "SEPD_EventPlaneCalib"; + std::string output_file = std::format("{}/{}-{}-{}.root", m_cdb_output_dir, payload, m_dst_tag, m_runnumber); + + CDBTTree cdbttree(output_file); + + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + int n = m_harmonics[h_idx]; + + // Define lambdas to generate field names consistently + auto field = [&](const std::string& det, const std::string& var) + { + return std::format("Q_{}_{}_{}_avg", det, var, n); + }; + + for (size_t cent_bin = 0; cent_bin < m_cent_bins; ++cent_bin) + { + int key = cent_bin; + + // Iterate through all subdetectors (S, N, NS) using the Enum Count + for (size_t d = 0; d < static_cast(QVecShared::Subdetector::Count); ++d) + { + auto det_enum = static_cast(d); + + // Map enum to the string labels used in the CDB field names + std::string det_label; + switch (det_enum) + { + case QVecShared::Subdetector::S: + det_label = "S"; + break; + case QVecShared::Subdetector::N: + det_label = "N"; + break; + case QVecShared::Subdetector::NS: + det_label = "NS"; + break; + default: + continue; + } + + const auto& data = m_correction_data[cent_bin][h_idx][d]; + // 1st Order Moments (Recentering) - Skip for NS as it is a combined vector + if (det_enum != QVecShared::Subdetector::NS) + { + cdbttree.SetDoubleValue(key, field(det_label, "x"), data.avg_Q.x); + cdbttree.SetDoubleValue(key, field(det_label, "y"), data.avg_Q.y); + } + + // 2nd Order Moments (Flattening) - Applicable to S, N, and NS + cdbttree.SetDoubleValue(key, field(det_label, "xx"), data.avg_Q_xx); + cdbttree.SetDoubleValue(key, field(det_label, "yy"), data.avg_Q_yy); + cdbttree.SetDoubleValue(key, field(det_label, "xy"), data.avg_Q_xy); + } + } + } + + std::cout << "Saving CDB: " << payload << " to " << output_file << std::endl; + + cdbttree.Commit(); + cdbttree.WriteCDBTTree(); +} + +//____________________________________________________________________________.. +int QVecCalib::End(PHCompositeNode * /*topNode*/) +{ + std::cout << "QVecCalib::End(PHCompositeNode *topNode) This is the End..." << std::endl; + + std::cout << "\n--- Event Counter Summary ---" << std::endl; + std::cout << "Bad Centrality/sEPD corr: " << m_event_counters.bad_centrality_sepd_correlation << std::endl; + std::cout << "Zero sEPD Charge: " << m_event_counters.zero_sepd_total_charge << std::endl; + std::cout << "Total Events Seen: " << m_event << std::endl; + std::cout << "-----------------------------\n" << std::endl; + + for (size_t cent_bin = 0; cent_bin < m_cent_bins; ++cent_bin) + { + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + int n = m_harmonics[h_idx]; + + if (m_pass == Pass::ComputeRecentering) + { + compute_averages(cent_bin, h_idx); + } + + else if (m_pass == Pass::ApplyRecentering) + { + compute_recentering(cent_bin, h_idx); + } + + else if (m_pass == Pass::ApplyFlattening) + { + print_flattening(cent_bin, n); + } + } + } + + if (m_pass == Pass::ApplyFlattening) + { + write_cdb(); + } + + return Fun4AllReturnCodes::EVENT_OK; +} diff --git a/calibrations/sepd/sepd_eventplanecalib/QVecCalib.h b/calibrations/sepd/sepd_eventplanecalib/QVecCalib.h new file mode 100644 index 0000000000..7f834273b2 --- /dev/null +++ b/calibrations/sepd/sepd_eventplanecalib/QVecCalib.h @@ -0,0 +1,435 @@ +#ifndef SEPDEVENTPLANECALIB_QVECCALIB_H +#define SEPDEVENTPLANECALIB_QVECCALIB_H + +#include "QVecDefs.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +class PHCompositeNode; +class EventPlaneData; +class TFile; +class TH1; +class TH2; +class TProfile; + +/** + * @class QVecCalib + * @brief Orchestrates the multi-pass anisotropy calibration for the sEPD Q-vectors. + * + * This class implements a three-pass correction procedure designed to remove + * detector-induced biases from the sEPD event plane reconstruction: + * * 1. **ComputeRecentering**: Calculates the first-order vector offsets (re-centering) + * per centrality bin. + * 2. **ApplyRecentering**: Applies the first-order offsets and computes the + * second-order whitening/flattening matrix. + * 3. **ApplyFlattening**: Applies the full correction (re-centering + flattening) + * to produce final validated event planes. + * * The class manages event-level selections based on charge-centrality correlations + * and handles the exclusion of "bad" (hot/cold/dead) sEPD channels. + */ +class QVecCalib : public SubsysReco +{ + public: + explicit QVecCalib(const std::string& name = "QVecCalib"); + + /** Called during initialization. + Typically this is where you can book histograms, and e.g. + register them to Fun4AllServer (so they can be output to file + using Fun4AllServer::dumpHistos() method). + */ + int Init(PHCompositeNode* topNode) override; + + /** Called for first event when run number is known. + Typically this is where you may want to fetch data from + database, because you know the run number. + */ + int InitRun(PHCompositeNode *topNode) override; + + /** Called for each event. + This is where you do the real work. + */ + int process_event(PHCompositeNode* topNode) override; + + /// Clean up internals after each event. + int ResetEvent(PHCompositeNode* topNode) override; + + /// Called at the end of all processing. + int End(PHCompositeNode* topNode) override; + + enum class Pass + { + ComputeRecentering, + ApplyRecentering, + ApplyFlattening + }; + + void set_pass(int pass) + { + m_pass = validate_pass(pass); + } + + void set_input_hist(std::string_view file) + { + m_input_hist = file; + } + + void set_input_Q_calib(std::string_view file) + { + m_input_Q_calib = file; + } + + void set_dst_tag(std::string_view tag) + { + m_dst_tag = tag; + } + + void set_cdb_output_dir(std::string_view cdb_dir) + { + m_cdb_output_dir = cdb_dir; + } + + private: + static Pass validate_pass(int pass) + { + switch (pass) + { + case 0: + return Pass::ComputeRecentering; + case 1: + return Pass::ApplyRecentering; + case 2: + return Pass::ApplyFlattening; + default: + throw std::invalid_argument("Invalid pass value"); + } + } + + struct CorrectionData + { + QVecShared::QVec avg_Q{}; + + double avg_Q_xx{0.0}; + double avg_Q_yy{0.0}; + double avg_Q_xy{0.0}; + + std::array, 2> X_matrix{}; + }; + + static constexpr size_t m_cent_bins = QVecShared::CENT_BINS; + static constexpr auto m_harmonics = QVecShared::HARMONICS; + + static constexpr float SIGMA_HOT {6.0}; + static constexpr float SIGMA_COLD {-6.0}; + + double m_cent_low{-0.5}; + double m_cent_high{79.5}; + + std::string m_input_hist; + std::string m_input_Q_calib; + std::string m_dst_tag; + std::string m_cdb_output_dir{"."}; + Pass m_pass{Pass::ComputeRecentering}; + EventPlaneData* m_evtdata{nullptr}; + + int m_event{0}; + int m_runnumber{0}; + + struct EventCounters + { + int bad_centrality_sepd_correlation{0}; + int zero_sepd_total_charge{0}; + int total_processed{0}; + }; + + EventCounters m_event_counters; + + std::array, m_harmonics.size()> m_q_vectors{}; + + static constexpr int PROGRESS_REPORT_INTERVAL = 10000; + + // Holds all correction data + // key: [Cent][Harmonic][Subdetector] + // Harmonics {2,3,4} -> 3 elements + // Subdetectors {S,N,NS} -> 3 elements + std::array, m_harmonics.size()>, m_cent_bins> m_correction_data; + + // Store harmonic orders and subdetectors for easy iteration + static constexpr std::array m_subdetectors = {QVecShared::Subdetector::S, QVecShared::Subdetector::N}; + static constexpr std::array m_components = {QVecShared::QComponent::X, QVecShared::QComponent::Y}; + + // [Harmonic Index][Channel Index] -> {cos, sin} + std::vector>> m_trig_cache; + + struct AverageHists + { + TProfile* S_x_avg{nullptr}; + TProfile* S_y_avg{nullptr}; + TProfile* N_x_avg{nullptr}; + TProfile* N_y_avg{nullptr}; + + TH2* Psi_S{nullptr}; + TH2* Psi_N{nullptr}; + TH2* Psi_NS{nullptr}; + }; + + struct RecenterHists + { + TProfile* S_x_corr_avg{nullptr}; + TProfile* S_y_corr_avg{nullptr}; + TProfile* N_x_corr_avg{nullptr}; + TProfile* N_y_corr_avg{nullptr}; + + TProfile* S_xx_avg{nullptr}; + TProfile* S_yy_avg{nullptr}; + TProfile* S_xy_avg{nullptr}; + TProfile* N_xx_avg{nullptr}; + TProfile* N_yy_avg{nullptr}; + TProfile* N_xy_avg{nullptr}; + + TProfile* NS_xx_avg{nullptr}; + TProfile* NS_yy_avg{nullptr}; + TProfile* NS_xy_avg{nullptr}; + + TH2* Psi_S_corr{nullptr}; + TH2* Psi_N_corr{nullptr}; + TH2* Psi_NS_corr{nullptr}; + }; + + struct FlatteningHists + { + TProfile* S_x_corr2_avg{nullptr}; + TProfile* S_y_corr2_avg{nullptr}; + TProfile* N_x_corr2_avg{nullptr}; + TProfile* N_y_corr2_avg{nullptr}; + + TProfile* S_xx_corr_avg{nullptr}; + TProfile* S_yy_corr_avg{nullptr}; + TProfile* S_xy_corr_avg{nullptr}; + + TProfile* N_xx_corr_avg{nullptr}; + TProfile* N_yy_corr_avg{nullptr}; + TProfile* N_xy_corr_avg{nullptr}; + + TProfile* NS_xx_corr_avg{nullptr}; + TProfile* NS_yy_corr_avg{nullptr}; + TProfile* NS_xy_corr_avg{nullptr}; + + TH2* Psi_S_corr2{nullptr}; + TH2* Psi_N_corr2{nullptr}; + TH2* Psi_NS_corr2{nullptr}; + }; + + // sEPD Bad Channels + std::unordered_set m_bad_channels; + + double m_sEPD_min_avg_charge_threshold{1}; + double m_sEPD_sigma_threshold{3}; + + // Hists + TH1* hCentrality{nullptr}; + + TH2* h2SEPD_Charge{nullptr}; + TH2* h2SEPD_Chargev2{nullptr}; + + TH2* h2SEPD_South_Charge_rbin{nullptr}; + TH2* h2SEPD_North_Charge_rbin{nullptr}; + + TH2* h2SEPD_South_Charge_rbinv2{nullptr}; + TH2* h2SEPD_North_Charge_rbinv2{nullptr}; + + TProfile* hSEPD_Charge_Min{nullptr}; + TProfile* hSEPD_Charge_Max{nullptr}; + + TProfile* hSEPD_Bad_Channels{nullptr}; + + std::map m_hists2D; + std::map m_profiles; + + std::vector m_average_hists; + std::vector m_recenter_hists; + std::vector m_flattening_hists; + + /** + * @brief Initializes all output histograms and profiles. + * * Dynamically generates histogram names using the shared naming helper based on + * the current calibration pass (e.g., adding "_corr" or "_corr2" suffixes). + */ + void init_hists(); + + /** + * @brief Safely retrieves a ROOT object from a file and returns a managed pointer. + * * Performs a dynamic_cast to verify the requested type T and Clones the object + * to ensure it remains valid after the source file is closed. + * * @tparam T The ROOT class type (e.g., TProfile). + * @param file Pointer to the source TFile. + * @param name The name of the object within the file. + * @return T* A managed pointer to the cloned object. + * @throws std::runtime_error If the object is not found or type mismatch occurs. + */ + template + T* load_and_clone(TFile* file, const std::string& name); + + /** + * @brief Loads the results of previous passes from a calibration file. + * * Populates the internal correction data structure with averages and/or + * matrices required for the current processing pass. + */ + int load_correction_data(); + + /** + * @brief Validates events based on sEPD total charge vs. centrality correlation. + * * Compares the current event's total charge against the 3-sigma bounds derived + * from the QA histograms to reject pile-up or background-dominated events. + * @return True if the event falls within the acceptable charge window. + */ + bool process_event_check(); + + /** + * @brief Performs the primary tower-by-tower Q-vector calculation and normalization. + * * Loops through sEPD channels, excludes bad channels, calculates the raw Q-vector + * for all harmonics, and normalizes the results by the total arm charge. + * @return True if both South and North arms have non-zero total charge. + */ + bool process_sEPD(); + + /** + * @brief Calculates and fills profiles for the initial Q-vector averages. + * @param cent The event centrality. + * @param q_S The South arm normalized Q-vector. + * @param q_N The North arm normalized Q-vector. + * @param h Reference to the cache of profiles for the first pass. + */ + static void process_averages(double cent, const QVecShared::QVec& q_S, const QVecShared::QVec& q_N, const AverageHists& h); + + /** + * @brief Applies re-centering offsets and fills profiles for second-moment calculation. + * @param cent The event centrality. + * @param h_idx Harmonic index. + * @param q_S The South arm normalized Q-vector. + * @param q_N The North arm normalized Q-vector. + * @param h Reference to the cache of profiles for the second pass. + */ + void process_recentering(double cent, size_t h_idx, const QVecShared::QVec& q_S, const QVecShared::QVec& q_N, const RecenterHists& h); + + /** + * @brief Applies the full correction (re-centering + flattening) for validation. + * @param cent The event centrality. + * @param h_idx Harmonic index. + * @param q_S The South arm normalized Q-vector. + * @param q_N The North arm normalized Q-vector. + * @param h Reference to the cache of profiles for the third pass. + */ + void process_flattening(double cent, size_t h_idx, const QVecShared::QVec& q_S, const QVecShared::QVec& q_N, const FlatteningHists& h); + + /** + * @brief Calculates the 2x2 anisotropy correction (whitening) matrix. + * * This matrix transforms the elliptical Q-vector distribution into a circularly + * symmetric (isotropic) distribution. It effectively corrects for detector + * acceptance effects and gain non-uniformities by normalizing the second-order + * moments of the Q-vector. + * * @param xx The second moment. + * @param yy The second moment. + * @param xy The cross-moment. + * @param n Harmonic order (used for error logging context). + * @param cent_bin Centrality bin (used for error logging context). + * @param det_label Detector label ("S" or "N"). + * @return std::array, 2> The 2x2 correction matrix. + */ + std::array, 2> calculate_flattening_matrix(double xx, double yy, double xy, int n, int cent_bin, const std::string& det_label); + + /** + * @brief Computes 1st-order re-centering offsets for a specific centrality bin. + * * Extracts average Q-vector components from histograms and stores them in the + * correction data matrix for use in subsequent processing passes. + * * @param cent_bin The index of the centrality bin. + * @param h_idx The index of the harmonic order in the harmonics array. + */ + void compute_averages(size_t cent_bin, int h_idx); + + /** + * @brief Computes re-centering parameters and solves the flattening matrices. + * * Extracts the re-centered second moments from the profiles and populates the + * internal CorrectionData matrix with calculated flattening coefficients. + * @param cent_bin The centrality bin index. + * @param h_idx The harmonic index. + */ + void compute_recentering(size_t cent_bin, int h_idx); + + /** + * @brief Logs the final corrected moments to verify successful flattening. + * @param cent_bin The centrality bin index. + * @param n The harmonic order. + */ + void print_flattening(size_t cent_bin, int n) const; + + void prepare_hists(); + + /** + * @brief Prepares a vector of pointers to histograms used in the first pass. + * @return A vector of AverageHists structs, indexed by harmonic. + */ + void prepare_average_hists(); + + /** + * @brief Prepares a vector of pointers to histograms used in the second pass. + * @return A vector of RecenterHists structs, indexed by harmonic. + */ + void prepare_recenter_hists(); + + /** + * @brief Prepares a vector of pointers to histograms used in the third pass. + * @return A vector of FlatteningHists structs, indexed by harmonic. + */ + void prepare_flattening_hists(); + + /** + * @brief Top-level driver for processing Quality Assurance histograms. + * * Loads the reference histogram file to identify bad channels and establish + * event-level charge thresholds as a function of centrality. + */ + int process_QA_hist(); + + /** + * @brief Identifies and catalogs "Bad" (Hot, Cold, or Dead) sEPD channels. + * * Uses a reference charge histogram to compute Z-scores based on mean charge + * per radial bin. Channels exceeding the sigma threshold are added to the internal exclusion set. + * * @param file Pointer to the open TFile containing QA histograms. + */ + int process_bad_channels(TFile* file); + + /** + * @brief Establishes sEPD charge-cut thresholds for event selection. + * * Uses the 2D total charge vs. centrality distribution to derive mean and + * sigma values, generating a 1D profile of the selection window. + * @param file Pointer to the open QA histogram file. + */ + int process_sEPD_event_thresholds(TFile* file); + + void write_cdb(); + + /** + * @brief Writes the Event Plane calibration constants to a CDB-formatted TTree. + * * Formats the re-centering and flattening moments into a CDBTTree payload + * indexed by centrality bin for sPHENIX database integration. + * * @param output_dir The filesystem directory where the .root payload will be saved. + */ + void write_cdb_EventPlane(); + + /** + * @brief Writes the Hot/Cold tower status map to a CDB-formatted TTree. + * * Encodes sEPD channel indices into TowerInfo keys and maps status codes (1=Dead, + * 2=Hot, 3=Cold) to the final database payload. + * * @param output_dir The filesystem directory where the .root payload will be saved. + */ + void write_cdb_BadTowers(); +}; + +#endif // SEPDEVENTPLANECALIB_QVECCALIB_H diff --git a/calibrations/sepd/sepd_eventplanecalib/QVecDefs.h b/calibrations/sepd/sepd_eventplanecalib/QVecDefs.h new file mode 100644 index 0000000000..656ec1dc8f --- /dev/null +++ b/calibrations/sepd/sepd_eventplanecalib/QVecDefs.h @@ -0,0 +1,58 @@ +#ifndef SEPDEVENTPLANECALIB_QVECDEFS_H +#define SEPDEVENTPLANECALIB_QVECDEFS_H + +#include +#include +#include +#include + +namespace QVecShared +{ + static constexpr size_t CENT_BINS = 80; + static constexpr std::array HARMONICS = {2, 3, 4}; + static constexpr int SEPD_CHANNELS = 744; + + enum class ChannelStatus : int + { + Good = 0, + Dead = 1, + Hot = 2, + Cold = 3 + }; + + enum class Subdetector : size_t + { + S = 0, + N = 1, + NS = 2, + Count = 3 + }; + + enum class QComponent + { + X, + Y + }; + + struct QVec + { + double x{0.0}; + double y{0.0}; + }; + + /** + * @brief Centralized helper to generate standard histogram names for the sEPD calibration. + * * Standardizes the naming convention: h_sEPD_Q_{det}_{var}_{n}{suffix}_avg + * * @param det The detector arm ("S" for South, "N" for North). + * @param var The physics variable or moment (e.g., "x", "y", "xx", "xy"). + * @param n The harmonic order (e.g., 2, 3, 4). + * @param suffix Optional pass-specific suffix (e.g., "_corr", "_corr2"). + * @return A formatted std::string representing the ROOT histogram name. + */ + inline std::string get_hist_name(const std::string& det, const std::string& var, int n, const std::string& suffix = "") + { + return std::format("h_sEPD_Q_{}_{}_{}{}_avg", det, var, n, suffix); + } +} // namespace QVecShared + +#endif // SEPDEVENTPLANECALIB_QVECDEFS_H diff --git a/calibrations/sepd/sepd_eventplanecalib/autogen.sh b/calibrations/sepd/sepd_eventplanecalib/autogen.sh new file mode 100755 index 0000000000..18aced5f8f --- /dev/null +++ b/calibrations/sepd/sepd_eventplanecalib/autogen.sh @@ -0,0 +1,8 @@ +#!/bin/sh +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +(cd "$srcdir" || exit 1; aclocal -I "${OFFLINE_MAIN}/share" && +libtoolize --force && automake -a --add-missing && autoconf) + +$srcdir/configure "$@" diff --git a/calibrations/sepd/sepd_eventplanecalib/configure.ac b/calibrations/sepd/sepd_eventplanecalib/configure.ac new file mode 100644 index 0000000000..5fcb1af63a --- /dev/null +++ b/calibrations/sepd/sepd_eventplanecalib/configure.ac @@ -0,0 +1,19 @@ +AC_INIT(sepd_eventplanecalib,[1.00]) +AC_CONFIG_SRCDIR([configure.ac]) + +AM_INIT_AUTOMAKE +AC_PROG_CXX(CC g++) + +LT_INIT([disable-static]) + +dnl no point in suppressing warnings people should +dnl at least see them, so here we go for g++: -Wall +if test $ac_cv_prog_gxx = yes; then + CXXFLAGS="$CXXFLAGS -Wshadow -Wall -Wextra -Werror" +fi + +CINTDEFS=" -noIncludePaths -inlineInputHeader " +AC_SUBST(CINTDEFS) + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/calibrations/sepd/sepd_eventplanecalib/sEPD_TreeGen.cc b/calibrations/sepd/sepd_eventplanecalib/sEPD_TreeGen.cc new file mode 100644 index 0000000000..7f11a07255 --- /dev/null +++ b/calibrations/sepd/sepd_eventplanecalib/sEPD_TreeGen.cc @@ -0,0 +1,343 @@ +#include "sEPD_TreeGen.h" +#include "QVecDefs.h" +#include "EventPlaneData.h" + +// -- Calo +#include +#include + +// -- Vtx +#include +#include + +// -- MB +#include + +#include + +// -- sEPD +#include + +// -- event +#include + +// -- Fun4All +#include +#include + +// -- Nodes +#include +#include +#include + +// -- ROOT +#include +#include + +// -- c++ +#include +#include + +//____________________________________________________________________________.. +sEPD_TreeGen::sEPD_TreeGen(const std::string &name) + : SubsysReco(name) +{ +} + +//____________________________________________________________________________.. +int sEPD_TreeGen::Init(PHCompositeNode *topNode) +{ + Fun4AllServer *se = Fun4AllServer::instance(); + if (Verbosity() > 0) + { + se->Print("NODETREE"); + } + unsigned int bins_sepd_totalcharge{100}; + double sepd_totalcharge_low{0}; + double sepd_totalcharge_high{2e4}; + + unsigned int bins_centrality{80}; + double centrality_low{-0.5}; + double centrality_high{79.5}; + + hSEPD_Charge = new TProfile("hSEPD_Charge", "|z| < 10 cm and MB; Channel; Avg Charge", QVecShared::SEPD_CHANNELS, 0, QVecShared::SEPD_CHANNELS); + hSEPD_Charge->Sumw2(); + + h2SEPD_totalcharge_centrality = new TH2F("h2SEPD_totalcharge_centrality", + "|z| < 10 cm and MB; sEPD Total Charge; Centrality [%]", + bins_sepd_totalcharge, sepd_totalcharge_low, sepd_totalcharge_high, + bins_centrality, centrality_low, centrality_high); + + se->registerHisto(hSEPD_Charge); + se->registerHisto(h2SEPD_totalcharge_centrality); + + PHNodeIterator node_itr(topNode); + PHCompositeNode *dstNode = dynamic_cast(node_itr.findFirst("PHCompositeNode", "DST")); + + if (!dstNode) + { + std::cout << PHWHERE << "DST node missing, cannot attach EventPlaneData." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + EventPlaneData *evtdata = findNode::getClass(topNode, "EventPlaneData"); + if (!evtdata) + { + evtdata = new EventPlaneData(); + PHIODataNode *newNode = new PHIODataNode(evtdata, "EventPlaneData", "PHObject"); + dstNode->addNode(newNode); + } + + return Fun4AllReturnCodes::EVENT_OK; +} + +//____________________________________________________________________________.. +int sEPD_TreeGen::process_event_check(PHCompositeNode *topNode) +{ + GlobalVertexMap *vertexmap = findNode::getClass(topNode, "GlobalVertexMap"); + + if (!vertexmap) + { + std::cout << PHWHERE << "GlobalVertexMap Node missing, doing nothing." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + if (vertexmap->empty()) + { + if (Verbosity() > 1) + { + std::cout << PHWHERE << "GlobalVertexMap Empty, Skipping Event: " << m_data.event_id << std::endl; + } + return Fun4AllReturnCodes::ABORTEVENT; + } + + GlobalVertex *vtx = vertexmap->begin()->second; + double zvtx = vtx->get_z(); + + MinimumBiasInfo *m_mb_info = findNode::getClass(topNode, "MinimumBiasInfo"); + if (!m_mb_info) + { + std::cout << PHWHERE << "MinimumBiasInfo Node missing, doing nothing." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + // skip event if not minimum bias + if (!m_mb_info->isAuAuMinimumBias()) + { + if (Verbosity() > 1) + { + std::cout << "Event: " << m_data.event_id << ", Not Min Bias, Skipping" << std::endl; + } + return Fun4AllReturnCodes::ABORTEVENT; + } + + // skip event if zvtx is too large + if (std::abs(zvtx) >= m_cuts.m_zvtx_max) + { + if (Verbosity() > 1) + { + std::cout << "Event: " << m_data.event_id << ", Z: " << zvtx << " cm, Skipping" << std::endl; + } + return Fun4AllReturnCodes::ABORTEVENT; + } + + m_evtdata->set_event_zvertex(zvtx); + + return Fun4AllReturnCodes::EVENT_OK; +} + +//____________________________________________________________________________.. +int sEPD_TreeGen::process_centrality(PHCompositeNode *topNode) +{ + CentralityInfo *centInfo = findNode::getClass(topNode, "CentralityInfo"); + if (!centInfo) + { + std::cout << PHWHERE << "CentralityInfo Node missing, doing nothing." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + double cent = centInfo->get_centile(CentralityInfo::PROP::mbd_NS) * 100; + + // skip event if centrality is bad or too peripheral + if (!std::isfinite(cent) || cent < 0 || cent >= m_cuts.m_cent_max) + { + if (Verbosity() > 1) + { + std::cout << "Event: " << m_data.event_id << ", Centrality: " << cent << ", Skipping" << std::endl; + } + return Fun4AllReturnCodes::ABORTEVENT; + } + + m_evtdata->set_event_centrality(cent); + m_data.event_centrality = cent; + + return Fun4AllReturnCodes::EVENT_OK; +} + +//____________________________________________________________________________.. +int sEPD_TreeGen::process_sEPD(PHCompositeNode *topNode) +{ + TowerInfoContainer *towerinfosEPD = findNode::getClass(topNode, "TOWERINFO_CALIB_SEPD"); + if (!towerinfosEPD) + { + std::cout << PHWHERE << "TOWERINFO_CALIB_SEPD Node missing, doing nothing." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + EpdGeom *epdgeom = findNode::getClass(topNode, "TOWERGEOM_EPD"); + if (!epdgeom) + { + std::cout << PHWHERE << "TOWERGEOM_EPD Node missing, doing nothing." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + // sepd + unsigned int sepd_channels = towerinfosEPD->size(); + + if(sepd_channels != QVecShared::SEPD_CHANNELS) + { + if (Verbosity() > 1) + { + std::cout << "Event: " << m_data.event_id << ", SEPD Channels = " << sepd_channels << " != " << QVecShared::SEPD_CHANNELS << std::endl; + } + return Fun4AllReturnCodes::ABORTEVENT; + } + + double sepd_totalcharge = 0; + + for (unsigned int channel = 0; channel < sepd_channels; ++channel) + { + TowerInfo *tower = towerinfosEPD->get_tower_at_channel(channel); + + if (!tower) + { + if (Verbosity() > 1) + { + std::cout << PHWHERE << "Null SEPD tower at channel " << channel << std::endl; + } + continue; + } + + double charge = tower->get_energy(); + bool isZS = tower->get_isZS(); + + // exclude ZS + // exclude Nmips + if (isZS || charge < m_cuts.m_sepd_charge_min) + { + continue; + } + + m_evtdata->set_sepd_charge(channel, charge); + + sepd_totalcharge += charge; + + hSEPD_Charge->Fill(channel, charge); + } + + m_evtdata->set_sepd_totalcharge(sepd_totalcharge); + h2SEPD_totalcharge_centrality->Fill(sepd_totalcharge, m_data.event_centrality); + + return Fun4AllReturnCodes::EVENT_OK; +} + +//____________________________________________________________________________.. +void sEPD_TreeGen::Print([[maybe_unused]] const std::string &what) const +{ + // Only execute if Verbosity is high enough + if (Verbosity() <= 2) + { + return; + } + + std::cout << "\n============================================================" << std::endl; + std::cout << "sEPD_TreeGen::Print -> Event Data State" << std::endl; + + if (!m_evtdata) + { + std::cout << " [WARNING] m_evtdata is null." << std::endl; + return; + } + + // Verbosity > 2: Print basic scalars + std::cout << " Event ID: " << m_evtdata->get_event_id() << std::endl; + std::cout << " Z-Vertex: " << m_evtdata->get_event_zvertex() << " cm" << std::endl; + std::cout << " Centrality: " << m_evtdata->get_event_centrality() << " %" << std::endl; + std::cout << " sEPD Total Charge: " << m_evtdata->get_sepd_totalcharge() << std::endl; + + // Verbosity > 3: Print channel arrays + if (Verbosity() > 3) + { + std::cout << " Active Towers (Charge > 0):" << std::endl; + for (int i = 0; i < QVecShared::SEPD_CHANNELS; ++i) + { + double charge = m_evtdata->get_sepd_charge(i); + if (charge > 0) + { + std::cout << " Channel: " << std::setw(3) << i + << " | Charge: " << std::fixed << std::setprecision(4) << charge << std::endl; + } + } + } + std::cout << "============================================================\n" << std::endl; +} + +//____________________________________________________________________________.. +int sEPD_TreeGen::process_event(PHCompositeNode *topNode) +{ + EventHeader *eventInfo = findNode::getClass(topNode, "EventHeader"); + if (!eventInfo) + { + std::cout << PHWHERE << "EventHeader Node missing, doing nothing." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + m_data.event_id = eventInfo->get_EvtSequence(); + + if (Verbosity() && m_event % PROGRESS_PRINT_INTERVAL == 0) + { + std::cout << "Progress: " << m_event << ", Global: " << m_data.event_id << std::endl; + } + ++m_event; + + m_evtdata = findNode::getClass(topNode, "EventPlaneData"); + if (!m_evtdata) + { + std::cout << PHWHERE << "EventPlaneData Node missing." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + m_evtdata->set_event_id(m_data.event_id); + + int ret = process_event_check(topNode); + if (ret) + { + return ret; + } + + ret = process_centrality(topNode); + if (ret) + { + return ret; + } + + ret = process_sEPD(topNode); + if (ret) + { + return ret; + } + + Print(); + + return Fun4AllReturnCodes::EVENT_OK; +} + +//____________________________________________________________________________.. +int sEPD_TreeGen::ResetEvent([[maybe_unused]] PHCompositeNode *topNode) +{ + // Event + m_data.event_id = -1; + m_data.event_centrality = 9999; + + return Fun4AllReturnCodes::EVENT_OK; +} diff --git a/calibrations/sepd/sepd_eventplanecalib/sEPD_TreeGen.h b/calibrations/sepd/sepd_eventplanecalib/sEPD_TreeGen.h new file mode 100644 index 0000000000..2d777f4011 --- /dev/null +++ b/calibrations/sepd/sepd_eventplanecalib/sEPD_TreeGen.h @@ -0,0 +1,138 @@ +#ifndef SEPDEVENTPLANECALIB_SEPDTREEGEN_H +#define SEPDEVENTPLANECALIB_SEPDTREEGEN_H + +// -- sPHENIX +#include + +// -- c++ +#include + +class EventPlaneData; +class PHCompositeNode; +class TH2; +class TProfile; + +/** + * @class sEPD_TreeGen + * @brief SubsysReco module to produce flat TTrees and QA histograms for sEPD calibration. + * + * This module extracts event-level info (vertex, centrality) and sEPD tower-level info + * (charge, phi, channel ID), applying basic event selections (Minimum Bias, Z-vertex) + * and tower-level cuts (charge threshold, zero-suppression). + */ +class sEPD_TreeGen : public SubsysReco +{ + public: + /** + * @brief Constructor for sEPD_TreeGen. + * @param name The name assigned to this SubsysReco module. + */ + explicit sEPD_TreeGen(const std::string &name = "sEPD_TreeGen"); + + /** + * @brief Initializes the module and creates the output TTree and QA histograms. + * @param topNode Pointer to the node tree. + * @return Fun4All return code. + */ + int Init(PHCompositeNode *topNode) override; + + /** + * @brief Main event-by-event processing method. + * @details Orchestrates event checks, centrality retrieval, sEPD tower processing, + * and fills the TTree for valid events. + * @param topNode Pointer to the node tree. + * @return Fun4All return code. + */ + int process_event(PHCompositeNode *topNode) override; + + /** + * @brief Resets event-level data structures before the next event. + * @param topNode Pointer to the node tree. + * @return Fun4All return code. + */ + int ResetEvent(PHCompositeNode *topNode) override; + + /** + * @brief Prints the current state of the EventPlaneData object. + * @param what Optional string to specify what to print (default "ALL"). + */ + void Print(const std::string &what = "ALL") const override; + + /** + * @brief Sets the maximum allowed Z-vertex position for event selection. + * @param zvtx_max Maximum vertex Z in cm. + */ + void set_zvtx_max(double zvtx_max) + { + m_cuts.m_zvtx_max = zvtx_max; + } + + /** + * @brief Sets the minimum charge threshold for individual sEPD towers. + * @param charge_min Minimum charge to include a tower in the TTree. + */ + void set_sepd_charge_threshold(double charge_min) + { + m_cuts.m_sepd_charge_min = charge_min; + } + + /** + * @brief Sets the maximum centrality centile allowed for processing. + * @param cent_max Maximum centile (e.g., 80 for 0-80%). + */ + void set_cent_max(double cent_max) + { + m_cuts.m_cent_max = cent_max; + } + + private: + /** + * @brief Validates event-level conditions (GlobalVertex, Minimum Bias). + * @param topNode Pointer to the node tree. + * @return Fun4All return code. + */ + int process_event_check(PHCompositeNode *topNode); + + /** + * @brief Processes individual sEPD towers and calculates total charge. + * @details Applies tower cuts, fills QA histograms, and stores tower data in vectors. + * @param topNode Pointer to the node tree. + * @return Fun4All return code. + */ + int process_sEPD(PHCompositeNode *topNode); + + /** + * @brief Retrieves and validates centrality information. + * @param topNode Pointer to the node tree. + * @return Fun4All return code. + */ + int process_centrality(PHCompositeNode *topNode); + + int m_event{0}; + + static constexpr int PROGRESS_PRINT_INTERVAL = 20; + + // Cuts + struct Cuts + { + double m_zvtx_max{10}; /*cm*/ + double m_sepd_charge_min{0.2}; + double m_cent_max{80}; + }; + + Cuts m_cuts; + + struct EventData + { + int event_id{0}; + double event_centrality{9999}; + }; + + EventData m_data; + EventPlaneData* m_evtdata{nullptr}; + + TProfile *hSEPD_Charge{nullptr}; + TH2 *h2SEPD_totalcharge_centrality{nullptr}; +}; + +#endif // SEPDEVENTPLANECALIB_SEPDTREEGEN_H diff --git a/calibrations/tpc/dEdx/GlobaldEdxFitter.cc b/calibrations/tpc/dEdx/GlobaldEdxFitter.cc new file mode 100644 index 0000000000..1cefa44dcd --- /dev/null +++ b/calibrations/tpc/dEdx/GlobaldEdxFitter.cc @@ -0,0 +1,346 @@ +#include "GlobaldEdxFitter.h" + +#include "bethe_bloch.h" +#include "TF1.h" +#include "TF2.h" +#include "TF3.h" +#include "TChain.h" +#include "TGraph.h" +#include "Math/Minimizer.h" +#include "Math/Functor.h" +#include "Math/Factory.h" + +void GlobaldEdxFitter::processResidualData(const std::string& infile, size_t ntracks, size_t skip) +{ + std::unique_ptr t = std::make_unique(); + t->Add((infile+"?#residualtree").c_str()); +// TFile* f = TFile::Open(infile.c_str()); +// TTree* t = (TTree*)f->Get("residualtree"); + + float px; + float py; + float pz; + float dedx; + float eta; + int nmaps; + int nintt; + int ntpc; + float dcaxy; + + t->SetBranchAddress("px",&px); + t->SetBranchAddress("py",&py); + t->SetBranchAddress("pz",&pz); + t->SetBranchAddress("dedx",&dedx); + t->SetBranchAddress("eta",&eta); + t->SetBranchAddress("nmaps",&nmaps); + t->SetBranchAddress("nintt",&nintt); + t->SetBranchAddress("ntpc",&ntpc); + t->SetBranchAddress("dcaxy",&dcaxy); + + size_t total_entries = t->GetEntriesFast(); + + for(size_t entry=skip; entry<(skip+ntracks); entry++) + { + if(entry==total_entries) + { + break; + } + if(entry % 1000 == 0) + { + std::cout << entry << std::endl; + } + t->GetEntry(entry); + if(nmaps>0 && nintt>0 && std::fabs(eta)<1. && dcaxy<0.5 && ntpc>30) + { + p.push_back(std::sqrt(px*px+py*py+pz*pz)); + dEdx.push_back(dedx); + } + } + std::cout << "number of good tracks: " << p.size() << std::endl; + //f->Close(); +} + +void GlobaldEdxFitter::addTrack(double trk_dEdx, double trk_p) +{ + dEdx.push_back(trk_dEdx); + p.push_back(trk_p); +} + +double GlobaldEdxFitter::get_fitquality_new(double A) +{ + //double chi2 = 0.; + //double ndf = -1.; + + double pi_chi2 = 0.; + double K_chi2 = 0.; + double p_chi2 = 0.; + double d_chi2 = 0.; + double pi_ndf = -1.; + double K_ndf = -1.; + double p_ndf = -1.; + double d_ndf = -1.; + + for(size_t i=0; i GlobaldEdxFitter::get_betagamma(double A) +{ + std::vector betagamma; + for(size_t i=0; iGetMinimumXYZ(minA,minB,minC); + delete f; + return std::make_tuple(minA,minB,minC); +*/ + ROOT::Math::Minimizer* minimizer = ROOT::Math::Factory::CreateMinimizer("Minuit2"); + minimizer->SetMaxFunctionCalls(1000000); + minimizer->SetMaxIterations(10000); + minimizer->SetTolerance(0.1); + minimizer->SetPrintLevel(1); + ROOT::Math::Functor f(this,&GlobaldEdxFitter::get_fitquality_functor,1); + double step[1] = {.01}; + double variable[1] = {20.}; + minimizer->SetFunction(f); + minimizer->SetVariable(0,"A",variable[0],step[0]); + minimizer->Minimize(); + const double *xs = minimizer->X(); + delete minimizer; + return xs[0]; +} + +double GlobaldEdxFitter::get_minimum() +{ + TF1* f = create_TF1("temp"); + f->SetNpx(1000); + double minX = f->GetMinimumX(); + delete f; + return minX; +} + +std::pair GlobaldEdxFitter::get_minimum_ZS() +{ + TF2* f = create_TF2("temp"); + double minX; + double minY; + f->GetMinimumXY(minX,minY); + delete f; + return std::make_pair(minX,minY); +} + +TGraph* GlobaldEdxFitter::graph_vsbetagamma(double A) +{ + std::vector betagamma = get_betagamma(A); + TGraph* g = new TGraph(dEdx.size(),betagamma.data(),dEdx.data()); + return g; +} + +TGraph* GlobaldEdxFitter::graph_vsp() +{ + TGraph* g = new TGraph(dEdx.size(),p.data(),dEdx.data()); + return g; +} diff --git a/calibrations/tpc/dEdx/GlobaldEdxFitter.h b/calibrations/tpc/dEdx/GlobaldEdxFitter.h new file mode 100644 index 0000000000..9d8dada662 --- /dev/null +++ b/calibrations/tpc/dEdx/GlobaldEdxFitter.h @@ -0,0 +1,69 @@ +#ifndef GLOBALDEDXFITTER_H +#define GLOBALDEDXFITTER_H + +#include "bethe_bloch.h" +#include "TF1.h" +#include "TF2.h" +#include "TF3.h" +#include "TChain.h" +#include "TGraph.h" +#include "Math/Minimizer.h" +#include "Math/Functor.h" +#include "Math/Factory.h" + +class GlobaldEdxFitter +{ + public: + explicit GlobaldEdxFitter(double xmin = 10., double xmax = 50.) + : min_norm(xmin), max_norm(xmax) + {}; + void processResidualData(const std::string& infile, + size_t ntracks = 200000, + size_t skip = 0); + void addTrack(double trk_dEdx, double trk_p); + size_t getNtracks() + { + return dEdx.size(); + } + + double get_fitquality(double norm, double ZS_loss = 0.); + double get_fitquality_new(double A); + TF1* create_TF1(const std::string& name); + TF2* create_TF2(const std::string& name); + TF3* create_TF3_new(const std::string& name); + double get_minimum(); + double get_minimum_new(); + std::pair get_minimum_ZS(); + void set_range(double xmin, double xmax, double ZSmin, double ZSmax) + { + min_norm = xmin; + max_norm = xmax; + min_ZS = ZSmin; + max_ZS = ZSmax; + } + void reset() + { + p.clear(); + dEdx.clear(); + } + std::vector get_betagamma(double A); + TGraph* graph_vsbetagamma(double A); + TGraph* graph_vsp(); + private: + std::vector p; + std::vector dEdx; + + double get_fitquality_functor(const double* x); + + double get_fitquality_wrapper(double* x, double* par); + double get_fitquality_wrapper_ZS(double* x, double* par); + double get_fitquality_wrapper_new(double* x, double* par); + double min_norm = 10.; + double max_norm = 50.; + double min_ZS = 0.; + double max_ZS = 200.; + double min_B = 8.; + double max_B = 12.; +}; + +#endif // GLOBALDEDXFITTER_H diff --git a/calibrations/tpc/dEdx/Makefile.am b/calibrations/tpc/dEdx/Makefile.am new file mode 100644 index 0000000000..d0eeaa9c5a --- /dev/null +++ b/calibrations/tpc/dEdx/Makefile.am @@ -0,0 +1,50 @@ +AUTOMAKE_OPTIONS = foreign + +AM_CPPFLAGS = \ + -I$(includedir) \ + -isystem$(OFFLINE_MAIN)/include \ + -isystem$(ROOTSYS)/include + +AM_LDFLAGS = \ + -L$(libdir) \ + -L$(OFFLINE_MAIN)/lib \ + -L$(OFFLINE_MAIN)/lib64 + +pkginclude_HEADERS = \ + dEdxFitter.h \ + GlobaldEdxFitter.h \ + bethe_bloch.h + +lib_LTLIBRARIES = \ + libdedxfitter.la + +libdedxfitter_la_SOURCES = \ + dEdxFitter.cc \ + GlobaldEdxFitter.cc + +libdedxfitter_la_LIBADD = \ + -lphool \ + -ltrack_io \ + -lg4detectors \ + -ltrackbase_historic \ + -ltrackbase_historic_io \ + -lglobalvertex \ + -lSubsysReco + +BUILT_SOURCES = testexternals.cc + +noinst_PROGRAMS = \ + testexternals + +testexternals_SOURCES = testexternals.cc +testexternals_LDADD = libdedxfitter.la + +testexternals.cc: + echo "//*** this is a generated file. Do not commit, do not edit" > $@ + echo "int main()" >> $@ + echo "{" >> $@ + echo " return 0;" >> $@ + echo "}" >> $@ + +clean-local: + rm -f $(BUILT_SOURCES) diff --git a/calibrations/tpc/dEdx/autogen.sh b/calibrations/tpc/dEdx/autogen.sh new file mode 100755 index 0000000000..dea267bbfd --- /dev/null +++ b/calibrations/tpc/dEdx/autogen.sh @@ -0,0 +1,8 @@ +#!/bin/sh +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +(cd $srcdir; aclocal -I ${OFFLINE_MAIN}/share;\ +libtoolize --force; automake -a --add-missing; autoconf) + +$srcdir/configure "$@" diff --git a/calibrations/tpc/dEdx/bethe_bloch.h b/calibrations/tpc/dEdx/bethe_bloch.h new file mode 100644 index 0000000000..a359a98294 --- /dev/null +++ b/calibrations/tpc/dEdx/bethe_bloch.h @@ -0,0 +1,208 @@ +#ifndef BETHE_BLOCH_H_ +#define BETHE_BLOCH_H_ + +#include + +namespace dedx_constants +{ + // hadron masses + constexpr double m_pi = 0.1396; // GeV + constexpr double m_K = 0.4937; // GeV + constexpr double m_p = 0.9382; // GeV + constexpr double m_d = 1.876; // GeV + + // electron mass [eV] + constexpr double m_e = 511e3; + + // TPC gas fractions + constexpr double ar_frac = 0.75; + constexpr double cf4_frac = 0.2; + constexpr double isobutane_frac = 0.05; + + // Mean excitation [src: W. Blum, W. Riegler, L. Rolandi, "Particle Detection with Drift Chambers"] + constexpr double ar_I = 188; // eV + constexpr double cf4_I = 115; // eV + constexpr double isobutane_I = 48.3; // eV + + // Mean excitation of mixture approximated using Bragg additivity rule + constexpr double sphenix_I = ar_frac*ar_I + cf4_frac*cf4_I + isobutane_frac*isobutane_I; +} + +// Bethe-Bloch fit function, vs. betagamma +// A = normalization constant, equal to (ADC conversion)*4pi*n*Z^2*e^4/(m_e*c^2*4pi*epsilon_0^2) +// B = A*(ln(2*m_e/I)-1) - (zero-suppression loss factor) +inline double bethe_bloch_new(const double betagamma, const double A, const double B, const double C) +{ + const double beta = betagamma/sqrt(1.+betagamma*betagamma); + + return A/(beta*beta)*TMath::Log(betagamma) + A/(beta*beta)*B - A - C; +} + +inline double bethe_bloch_new_2D(const double betagamma, const double A, const double B) +{ + const double beta = betagamma/sqrt(1.+betagamma*betagamma); + + return A/(beta*beta)*(2.*TMath::Log(2.*dedx_constants::m_e/dedx_constants::sphenix_I * betagamma) - beta*beta) - B; +} + +inline double bethe_bloch_new_1D(const double betagamma, const double A) +{ + const double beta = betagamma/sqrt(1.+betagamma*betagamma); + + return A/(beta*beta)*(2.*TMath::Log(2.*dedx_constants::m_e/dedx_constants::sphenix_I * betagamma) - beta*beta); +} + +// dE/dx for one gas species, up to normalization +inline double bethe_bloch_species(const double betagamma, const double I) +{ + const double m_e = 511e3; // eV + + const double beta = betagamma/sqrt(1.+betagamma*betagamma); + + return 1./(beta*beta)*(TMath::Log(2.*m_e/I*betagamma*betagamma)-beta*beta); +} + +// dE/dx for TPC gas mixture, up to normalization +inline double bethe_bloch_total(const double betagamma) +{ + return dedx_constants::ar_frac * bethe_bloch_species(betagamma,dedx_constants::ar_I) + + dedx_constants::cf4_frac * bethe_bloch_species(betagamma,dedx_constants::cf4_I) + + dedx_constants::isobutane_frac * bethe_bloch_species(betagamma,dedx_constants::isobutane_I); +} + +inline Double_t bethe_bloch_new_wrapper(const Double_t* const x, const Double_t* const par) +{ + Double_t betagamma = x[0]; + Double_t A = par[0]; + Double_t B = par[1]; + Double_t C = par[2]; + + return bethe_bloch_new(betagamma,A,B,C); +} + +inline Double_t bethe_bloch_new_2D_wrapper(const Double_t* const x, const Double_t* const par) +{ + Double_t betagamma = x[0]; + Double_t A = par[0]; + Double_t B = par[1]; + + return bethe_bloch_new_2D(betagamma,A,B); +} + +inline Double_t bethe_bloch_new_1D_wrapper(const Double_t* const x, const Double_t* const par) +{ + Double_t betagamma = x[0]; + Double_t A = par[0]; + + return bethe_bloch_new_1D(betagamma,A); +} + +// wrapper function for TF1 constructor, for fitting +inline Double_t bethe_bloch_wrapper(const Double_t* const ln_bg, const Double_t* const par) +{ + Double_t betagamma = exp(ln_bg[0]); + + Double_t norm = par[0]; + + return norm * bethe_bloch_total(betagamma); +} + +inline Double_t bethe_bloch_vs_p_wrapper(const Double_t* const x, const Double_t* const par) +{ + Double_t p = x[0]; + Double_t norm = par[0]; + Double_t m = par[1]; + + return norm * bethe_bloch_total(fabs(p)/m); +} + +inline Double_t bethe_bloch_vs_logp_wrapper(const Double_t* const x, const Double_t* const par) +{ + Double_t p = pow(10.,x[0]); + Double_t norm = par[0]; + Double_t m = par[1]; + + return norm * bethe_bloch_total(fabs(p)/m); +} + +inline Double_t bethe_bloch_vs_p_wrapper_ZS(const Double_t* const x, const Double_t* const par) +{ + Double_t p = x[0]; + Double_t norm = par[0]; + Double_t m = par[1]; + Double_t ZS_loss = par[2]; + + return norm * bethe_bloch_total(fabs(p)/m) - ZS_loss; +} + +inline Double_t bethe_bloch_vs_p_wrapper_new(const Double_t* const x, const Double_t* const par) +{ + Double_t p = x[0]; + Double_t A = par[0]; + Double_t B = par[1]; + Double_t C = par[2]; + Double_t m = par[3]; + + return bethe_bloch_new(fabs(p)/m,A,B,C); +} + +inline Double_t bethe_bloch_vs_p_wrapper_new_2D(const Double_t* const x, const Double_t* const par) +{ + Double_t p = x[0]; + Double_t A = par[0]; + Double_t B = par[1]; + Double_t m = par[2]; + + return bethe_bloch_new_2D(fabs(p)/m,A,B); +} + +inline Double_t bethe_bloch_vs_p_wrapper_new_1D(const Double_t* const x, const Double_t* const par) +{ + Double_t p = x[0]; + Double_t A = par[0]; + Double_t m = par[1]; + + return bethe_bloch_new_1D(fabs(p)/m,A); +} + +inline Double_t bethe_bloch_vs_logp_wrapper_ZS(const Double_t* const x, const Double_t* const par) +{ + Double_t p = pow(10.,x[0]); + Double_t norm = par[0]; + Double_t m = par[1]; + Double_t ZS_loss = par[2]; + + return norm * bethe_bloch_total(fabs(p)/m) - ZS_loss; +} + +inline Double_t bethe_bloch_vs_logp_wrapper_new(const Double_t* const x, const Double_t* const par) +{ + Double_t p = pow(10.,x[0]); + Double_t A = par[0]; + Double_t B = par[1]; + Double_t C = par[2]; + Double_t m = par[3]; + + return bethe_bloch_new(fabs(p)/m,A,B,C); +} + +inline Double_t bethe_bloch_vs_logp_wrapper_new_1D(const Double_t* const x, const Double_t* const par) +{ + Double_t p = pow(10.,x[0]); + Double_t A = par[0]; + Double_t m = par[1]; + + return bethe_bloch_new_1D(fabs(p)/m,A); +} + +// ratio of dE/dx between two particle species at the same momentum +// (useful for dE/dx peak fits) +inline double dedx_ratio(const double p, const double m1, const double m2) +{ + const double betagamma1 = fabs(p)/m1; + const double betagamma2 = fabs(p)/m2; + + return bethe_bloch_total(betagamma1)/bethe_bloch_total(betagamma2); +} + +#endif // BETHE_BLOCH_H_ diff --git a/calibrations/tpc/dEdx/configure.ac b/calibrations/tpc/dEdx/configure.ac new file mode 100644 index 0000000000..efef9411e9 --- /dev/null +++ b/calibrations/tpc/dEdx/configure.ac @@ -0,0 +1,16 @@ +AC_INIT( dEdxFitter,[1.00]) +AC_CONFIG_SRCDIR([configure.ac]) + +AM_INIT_AUTOMAKE +AC_PROG_CXX(CC g++) + +LT_INIT([disable-static]) + +dnl enable more warnings and make them fatal +dnl this package needs openmp which requires -fopenmp for clang +if test $ac_cv_prog_gxx = yes; then + CXXFLAGS="$CXXFLAGS -Wall -Wshadow -Wextra -Werror" +fi + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/calibrations/tpc/dEdx/dEdxFitter.cc b/calibrations/tpc/dEdx/dEdxFitter.cc new file mode 100644 index 0000000000..4277d3f059 --- /dev/null +++ b/calibrations/tpc/dEdx/dEdxFitter.cc @@ -0,0 +1,249 @@ +#include "dEdxFitter.h" + +#include +#include +#include +#include +#include +#include + +#include + +//____________________________________ +dEdxFitter::dEdxFitter(const std::string &name): + SubsysReco(name), + fitter(std::make_unique()) +{ + //initialize +} + +//___________________________________ +int dEdxFitter::InitRun(PHCompositeNode * /*topNode*/) +{ + std::cout << PHWHERE << " Opening file " << _outfile << std::endl; + outf = new TFile( _outfile.c_str(), "RECREATE"); + + return 0; +} + +//__________________________________ +//Call user instructions for every event +int dEdxFitter::process_event(PHCompositeNode *topNode) +{ + _event++; + if(_event%1000==0) + { + std::cout << PHWHERE << "Events processed: " << _event << std::endl; + } + + GetNodes(topNode); + + if(Verbosity()>1) + { + std::cout << "--------------------------------" << std::endl; + std::cout << "event " << _event << std::endl; + } + + process_tracks(); + + return 0; +} + +//_____________________________________ +void dEdxFitter::process_tracks() +{ + + for(const auto &[key, track] : *_trackmap) + { + if(!track) + { + continue; + } + + double trackID = track->get_id(); + if(Verbosity()>1) + { + std::cout << "track ID " << trackID << std::endl; + } + if(std::isnan(track->get_x()) || + std::isnan(track->get_y()) || + std::isnan(track->get_z()) || + std::isnan(track->get_px()) || + std::isnan(track->get_py()) || + std::isnan(track->get_pz())) + { + std::cout << "malformed track:" << std::endl; + track->identify(); + std::cout << "skipping..." << std::endl; + continue; + } + + // ignore TPC-only tracks + if(!track->get_silicon_seed()) + { + if(Verbosity()>1) + { + std::cout << "TPC-only track, skipping..." << std::endl; + } + continue; + } + + std::tuple nclus = get_nclus(track); + int nmaps = std::get<0>(nclus); + int nintt = std::get<1>(nclus); + int ntpc = std::get<2>(nclus); + + if(nmaps>=nmaps_cut && nintt>=nintt_cut && ntpc>=ntpc_cut && std::fabs(track->get_eta())addTrack(get_dedx(track),track->get_p()); + } + + if(fitter->getNtracks() > ntracks_to_fit) + { + minima.push_back(fitter->get_minimum()); + fitter->reset(); + } + } +} + +std::tuple dEdxFitter::get_nclus(SvtxTrack* track) +{ + int nmaps = 0; + int nintt = 0; + int ntpc = 0; + + if(track->get_silicon_seed()) + { + for(auto it = track->get_silicon_seed()->begin_cluster_keys(); it != track->get_silicon_seed()->end_cluster_keys(); ++it) + { + TrkrDefs::cluskey ckey = *it; + auto trkrid = TrkrDefs::getTrkrId(ckey); + if(trkrid == TrkrDefs::mvtxId) + { + nmaps++; + } + else if(trkrid == TrkrDefs::inttId) + { + nintt++; + } + } + } + if(track->get_tpc_seed()) + { + for(auto it = track->get_tpc_seed()->begin_cluster_keys(); it != track->get_tpc_seed()->end_cluster_keys(); ++it) + { + ntpc++; + } + } + + return std::make_tuple(nmaps,nintt,ntpc); +} + +double dEdxFitter::get_dedx(SvtxTrack* track) +{ + float layerThicknesses[4] = {0.0, 0.0, 0.0, 0.0}; + // These are randomly chosen layer thicknesses for the TPC, to get the + // correct region thicknesses in an easy to pass way to the helper fxn + layerThicknesses[0] = _tpcgeom->GetLayerCellGeom(7)->get_thickness(); + layerThicknesses[1] = _tpcgeom->GetLayerCellGeom(8)->get_thickness(); + layerThicknesses[2] = _tpcgeom->GetLayerCellGeom(27)->get_thickness(); + layerThicknesses[3] = _tpcgeom->GetLayerCellGeom(50)->get_thickness(); + + return TrackAnalysisUtils::calc_dedx(track->get_tpc_seed(), _clustermap, _geometry, layerThicknesses); +} + +double dEdxFitter::get_dcaxy(SvtxTrack* track) +{ + auto vertexit = _vertexmap->find(track->get_vertex_id()); + if(vertexit != _vertexmap->end()) + { + SvtxVertex* vtx = vertexit->second; + Acts::Vector3 vertex(vtx->get_x(),vtx->get_y(),vtx->get_z()); + auto dcapair = TrackAnalysisUtils::get_dca(track,vertex); + return dcapair.first.first; + } + // if no vertex found + return std::numeric_limits::quiet_NaN(); +} + +//___________________________________ +void dEdxFitter::GetNodes(PHCompositeNode *topNode) +{ + + _trackmap = findNode::getClass(topNode,"SvtxTrackMap"); + if(!_trackmap && _event<2) + { + std::cout << PHWHERE << " cannot find SvtxTrackMap" << std::endl; + } + + _clustermap = findNode::getClass(topNode,"TRKR_CLUSTER"); + if(!_clustermap && _event<2) + { + std::cout << PHWHERE << " cannot find TrkrClusterContainer TRKR_CLUSTER" << std::endl; + } + + _geometry = findNode::getClass(topNode,"ActsGeometry"); + if(!_geometry && _event<2) + { + std::cout << PHWHERE << " cannot find ActsGeometry" << std::endl; + } + + _tpcgeom = findNode::getClass(topNode,"TPCGEOMCONTAINER"); + if(!_tpcgeom && _event<2) + { + std::cout << PHWHERE << " cannot find PHG4TpcGeomContainer TPCGEOMCONTAINER" << std::endl; + } + + _vertexmap = findNode::getClass(topNode,"SvtxVertexMap"); + if(!_vertexmap && _event<2) + { + std::cout << PHWHERE << " cannot find SvtxVertexMap" << std::endl; + } +} + +//______________________________________ +int dEdxFitter::End(PHCompositeNode * /*topNode*/) +{ + if(minima.empty()) + { + minima.push_back(fitter->get_minimum()); + } + + double avg_minimum = 0.; + for(double m : minima) + { + avg_minimum += m; + } + avg_minimum /= (double)minima.size(); + + outf->cd(); + + TF1* pi_band = new TF1("pi_band","bethe_bloch_new_1D(fabs(x)/[1],[0])"); + pi_band->SetParameter(0,avg_minimum); + pi_band->SetParameter(1,dedx_constants::m_pi); + pi_band->Write(); + + TF1* K_band = new TF1("K_band","bethe_bloch_new_1D(fabs(x)/[1],[0])"); + K_band->SetParameter(0,avg_minimum); + K_band->SetParameter(1,dedx_constants::m_K); + K_band->Write(); + + TF1* p_band = new TF1("p_band","bethe_bloch_new_1D(fabs(x)/[1],[0])"); + p_band->SetParameter(0,avg_minimum); + p_band->SetParameter(1,dedx_constants::m_p); + p_band->Write(); + + TF1* d_band = new TF1("d_band","bethe_bloch_new_1D(fabs(x)/[1],[0])"); + d_band->SetParameter(0,avg_minimum); + d_band->SetParameter(1,dedx_constants::m_d); + d_band->Write(); + + if(Verbosity()>0) + { + std::cout << "dEdxFitter extracted minimum: " << avg_minimum << std::endl; + } + + outf->Close(); + + return 0; +} diff --git a/calibrations/tpc/dEdx/dEdxFitter.h b/calibrations/tpc/dEdx/dEdxFitter.h new file mode 100644 index 0000000000..0dc4da0f0c --- /dev/null +++ b/calibrations/tpc/dEdx/dEdxFitter.h @@ -0,0 +1,94 @@ +#ifndef DEDXFITTER_H_ +#define DEDXFITTER_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "GlobaldEdxFitter.h" + +//Forward declerations +class PHCompositeNode; +class TFile; + +// dEdx fit analysis module +class dEdxFitter: public SubsysReco +{ + public: + //Default constructor + explicit dEdxFitter(const std::string &name="dEdxFitter"); + + //Initialization, called for initialization + int InitRun(PHCompositeNode * /*topNode*/) override; + + //Process Event, called for each event + int process_event(PHCompositeNode *topNode) override; + + //End, write and close files + int End(PHCompositeNode * /*topNode*/) override; + + //Change output filename + void set_filename(const char* file) + { + if(file) + { + _outfile = file; + } + } + + void set_nmaps_cut(int nmaps) + { nmaps_cut = nmaps; } + + void set_nintt_cut(int nintt) + { nintt_cut = nintt; } + + void set_ntpc_cut(int ntpc) + { ntpc_cut = ntpc; } + + void set_eta_cut(float eta) + { eta_cut = eta; } + + void set_dcaxy_cut(float dcaxy) + { dcaxy_cut = dcaxy; } + + void set_ntracks_to_fit(size_t ntrk) + { ntracks_to_fit = ntrk; } + + private: + //output filename + std::string _outfile = "dedx_outfile.root"; + TFile* outf = nullptr; + size_t _event = 0; + + SvtxTrackMap* _trackmap = nullptr; + TrkrClusterContainer* _clustermap = nullptr; + ActsGeometry* _geometry = nullptr; + PHG4TpcGeomContainer* _tpcgeom = nullptr; + SvtxVertexMap* _vertexmap = nullptr; + + //Get all the nodes + void GetNodes(PHCompositeNode * /*topNode*/); + + void process_tracks(); + + int nmaps_cut = 1; + int nintt_cut = 1; + int ntpc_cut = 30; + float eta_cut = 1.; + float dcaxy_cut = 0.5; + + size_t ntracks_to_fit = 40000; + std::vector minima; + std::unique_ptr fitter; + + std::tuple get_nclus(SvtxTrack* track); + double get_dedx(SvtxTrack* track); + double get_dcaxy(SvtxTrack* track); + +}; + +#endif //* DEDXFITTER_H_ *// diff --git a/calibrations/tpc/dEdx/test_sample_size.C b/calibrations/tpc/dEdx/test_sample_size.C new file mode 100644 index 0000000000..8464aba486 --- /dev/null +++ b/calibrations/tpc/dEdx/test_sample_size.C @@ -0,0 +1,200 @@ +#include "GlobaldEdxFitter.h" + +#include +#include +#include +#include +#include + +#include +#include + +void test_sample_size(const std::string& infile="/sphenix/tg/tg01/hf/mjpeters/run53877_tracks/track_output_53877_*.root") +{ + std::vector samplesizes = {1000,2000,5000,10000,20000};//,50000,100000,200000,500000,1000000};//,2000000,5000000}; + + const int n_samples = 20; + const float fluctuation_ymin = 5.; + const float fluctuation_ymax = 26.; + const int distribution_nbins = 30; + const float distribution_xmin = 5.; + const float distribution_xmax = 26.; + + std::vector> fitvalues_all; + std::vector fitvalues_avg; + std::vector fitvalues_stdev; + + std::vector fluctuations; + std::vector distributions; + + std::vector dist_h; + + std::vector> gfs; + + for(int i=0; i()); + + const std::string& fluctuation_canvasname = "fluctuations_"+std::to_string((int)floor(samplesizes[i])); + const std::string& distribution_canvasname = "distributions_"+std::to_string((int)floor(samplesizes[i])); + fluctuations.push_back(new TCanvas(fluctuation_canvasname.c_str(),fluctuation_canvasname.c_str(),600,600)); + distributions.push_back(new TCanvas(distribution_canvasname.c_str(),distribution_canvasname.c_str(),600,600)); + + for(int j=0;jprocessResidualData(infile,floor(samplesizes[i]),j*samplesizes[i]); + double min = gfs[i]->get_minimum(); + std::cout << "minimum: " << min << std::endl; + fitvalues_all[i].push_back(min); + if(jreset(); + } +/* + tf1s[i]->cd(); + TF1* tf1copy = gfs[i]->create_TF1(("ntrk_"+std::to_string(samplesizes[i])).c_str()); + tf1copy->SetLineColor(base_color); + tf1copy->GetYaxis()->SetRangeUser(1.,tf1copy->GetMaximum()); + if(i==0) tf1copy->Draw(); + else tf1copy->Draw("SAME"); +*/ + } + } + + std::vector sample_index(n_samples); + std::iota(sample_index.begin(),sample_index.end(),0.); + + for(int i=0; icd(); + TGraph* g = new TGraph(n_samples,sample_index.data(),fitvalues_all[i].data()); + g->GetYaxis()->SetRangeUser(fluctuation_ymin,fluctuation_ymax); + g->SetMarkerStyle(kFullCircle); + g->SetMarkerSize(1.); + g->Draw("APL"); + + distributions[i]->cd(); + std::string hname = "h_"+std::to_string(floor(samplesizes[i])); + std::string htitle = "Distribution of fit results for sample size "+std::to_string(floor(samplesizes[i])); +/* + auto bounds = std::minmax_element(fitvalues_all[i].begin(),fitvalues_all[i].end()); + float lowerbound = floor(*bounds.first); + float upperbound = ceil(*bounds.second); +*/ + TH1F* h = new TH1F(hname.c_str(),htitle.c_str(),distribution_nbins,distribution_xmin,distribution_xmax); + for(int j=0; jFill(fitvalues_all[i][j]); + } + h->Draw(); + } + + for(int i=0; i errx(n_samples,0.); + + TCanvas* cg = new TCanvas("cg","sizes",600,600); + TGraph* g = new TGraphErrors(samplesizes.size(),samplesizes.data(),fitvalues_avg.data(),errx.data(),fitvalues_stdev.data()); + g->SetMarkerStyle(kFullCircle); + g->SetMarkerSize(1); + g->Draw("APL"); + cg->SetLogx(); + + TCanvas* cbg = new TCanvas("vsbetagamma","vsbetagamma",600,600); + TGraph* gbg = gfs.back()->graph_vsbetagamma(fitvalues_avg.back()); + gbg->SetMarkerStyle(kFullCircle); + gbg->SetMarkerSize(0.2); + gbg->Draw("AP"); + cbg->SetLogx(); + + double best_A = fitvalues_avg.back(); + + TF1* bethe = new TF1("bethebloch_vslnbg",bethe_bloch_new_1D_wrapper,0.,100.,2,1); + bethe->SetParameter(0,best_A); + bethe->SetNpx(1000); + bethe->Draw("SAME"); + + TF1* bethe_directfit = new TF1("bethebloch_directfit",bethe_bloch_new_1D_wrapper,0.,10.,1,1); + bethe_directfit->SetParameter(0,best_A); + bethe_directfit->SetLineColor(kBlue); + gbg->Fit(bethe_directfit); + double newbest_A = bethe_directfit->GetParameter(0); + std::cout << "new best: " << newbest_A << std::endl; + + TCanvas* cbands = new TCanvas("bands","bands",600,600); + TGraph* gp = gfs.back()->graph_vsp(); + gp->SetMarkerStyle(kFullCircle); + gp->SetMarkerSize(0.1); + gp->Draw("AP"); + cbands->SetLogx(); + + for(double mass : {dedx_constants::m_pi, dedx_constants::m_K, dedx_constants::m_p, dedx_constants::m_d}) + { + TF1* band = new TF1(("band_"+std::to_string(mass)).c_str(),bethe_bloch_vs_p_wrapper_new_1D,0.,10.,2,1); + band->SetParameter(0,best_A); + band->SetParameter(1,mass); + band->SetNpx(1000); + band->Draw("SAME"); + + TF1* directband = new TF1(("directband_"+std::to_string(mass)).c_str(),bethe_bloch_vs_p_wrapper_new_1D,0.,10.,2,1); + directband->SetLineColor(kBlue); + directband->SetParameters(best_A,mass); + directband->SetNpx(1000); + directband->Draw("SAME"); + } + + TCanvas* cb = new TCanvas("fullbands","fullbands",600,600); + TFile* f_h = TFile::Open("/sphenix/tg/tg01/hf/mjpeters/run53877_tracks/dedx/merged_dedx.root"); + TH2F* dedx_h = (TH2F*)f_h->Get("dedx_log_30"); + dedx_h->Draw("COLZ"); + cb->SetLogz(); + + for(double mass : {dedx_constants::m_pi, dedx_constants::m_K, dedx_constants::m_p, dedx_constants::m_d}) + { + TF1* band = new TF1(("band_"+std::to_string(mass)).c_str(),bethe_bloch_vs_logp_wrapper_new_1D,-1.,5.,2,1); + band->SetParameter(0,best_A); + band->SetParameter(1,mass); + band->Draw("SAME"); + + TF1* directband = new TF1(("directband_"+std::to_string(mass)).c_str(),bethe_bloch_vs_logp_wrapper_new_1D,-1.,5.,2,1); + directband->SetLineColor(kBlue); + directband->SetParameters(newbest_A,mass); + directband->SetNpx(1000); + directband->Draw("SAME"); + } + + TFile* fout = new TFile("dedxfitvals.root","RECREATE"); + for(auto& c : fluctuations) + { + c->Write(); + } + for(auto& c : distributions) + { + c->Write(); + } + cg->Write(); + cbg->Write(); + cbands->Write(); + cb->Write(); + fout->Close(); +} diff --git a/calibrations/xingshift/Makefile.am b/calibrations/xingshift/Makefile.am index 81ea4dbca4..08c0220b6b 100644 --- a/calibrations/xingshift/Makefile.am +++ b/calibrations/xingshift/Makefile.am @@ -23,9 +23,9 @@ libXingShiftCal_la_SOURCES = \ libXingShiftCal_la_LIBADD = \ -lcdbobjects \ -lfun4all \ + -lfun4cal \ -lphool \ - -lSubsysReco \ - -loncal + -lSubsysReco BUILT_SOURCES = testexternals.cc diff --git a/generators/Herwig/HepMCTrigger/HepMCJetTrigger.cc b/generators/Herwig/HepMCTrigger/HepMCJetTrigger.cc index 02ca208f25..506799c874 100644 --- a/generators/Herwig/HepMCTrigger/HepMCJetTrigger.cc +++ b/generators/Herwig/HepMCTrigger/HepMCJetTrigger.cc @@ -31,7 +31,6 @@ HepMCJetTrigger::HepMCJetTrigger(float trigger_thresh, int n_incom, bool up_lim, int HepMCJetTrigger::process_event(PHCompositeNode* topNode) { // std::cout << "HepMCJetTrigger::process_event(PHCompositeNode *topNode) Processing Event" << std::endl; - n_evts++; if (this->set_event_limit == true) { // needed to keep all HepMC output at the same number of events if (n_good >= this->goal_event_number) @@ -39,6 +38,7 @@ int HepMCJetTrigger::process_event(PHCompositeNode* topNode) return Fun4AllReturnCodes::ABORTEVENT; } } + n_evts++; PHHepMCGenEventMap* phg = findNode::getClass(topNode, "PHHepMCGenEventMap"); if (!phg) { @@ -96,6 +96,11 @@ std::vector HepMCJetTrigger::findAllJets(HepMC::GenEvent* e1 if (!(*iter)->end_vertex() && (*iter)->status() == 1) { auto p = (*iter)->momentum(); + auto pd = std::abs((*iter)->pdg_id()); + if (pd >= 12 && pd <= 18) + { + continue; // keep jet in the expected behavioro + } fastjet::PseudoJet pj(p.px(), p.py(), p.pz(), p.e()); pj.set_user_index((*iter)->barcode()); input.push_back(pj); @@ -122,6 +127,10 @@ int HepMCJetTrigger::jetsAboveThreshold(const std::vector& j for (const auto& j : jets) { float const pt = j.pt(); + if (std::abs(j.eta()) > 1.1) + { + continue; + } if (pt > this->threshold) { n_good_jets++; diff --git a/generators/Herwig/HepMCTrigger/HepMCJetTrigger.h b/generators/Herwig/HepMCTrigger/HepMCJetTrigger.h index 67a1a4fbe5..0917e42cdc 100644 --- a/generators/Herwig/HepMCTrigger/HepMCJetTrigger.h +++ b/generators/Herwig/HepMCTrigger/HepMCJetTrigger.h @@ -47,6 +47,8 @@ class HepMCJetTrigger : public SubsysReco /// Called at the end of all processing. /// Reset + int getNevts(){return this->n_evts;} + int getNgood(){return this->n_good;} private: bool isGoodEvent(HepMC::GenEvent* e1); @@ -54,9 +56,9 @@ class HepMCJetTrigger : public SubsysReco int jetsAboveThreshold(const std::vector& jets) const; float threshold{0.}; int goal_event_number{1000}; + bool set_event_limit{false}; int n_evts{0}; int n_good{0}; - bool set_event_limit{false}; }; #endif // HEPMCJETTRIGGER_H diff --git a/generators/Herwig/HepMCTrigger/HepMCParticleTrigger.cc b/generators/Herwig/HepMCTrigger/HepMCParticleTrigger.cc new file mode 100644 index 0000000000..eccb80ce6c --- /dev/null +++ b/generators/Herwig/HepMCTrigger/HepMCParticleTrigger.cc @@ -0,0 +1,439 @@ +#include "HepMCParticleTrigger.h" + +#include +#include +#include + +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +//____________________________________________________________________________.. +// NOLINTNEXTLINE(bugprone-easily-swappable-parameters) +HepMCParticleTrigger::HepMCParticleTrigger(float trigger_thresh, int n_incom, bool up_lim, const std::string& name) + : SubsysReco(name) + , threshold(trigger_thresh) + , goal_event_number(n_incom) + , set_event_limit(up_lim) + , _theEtaHigh(1.1) + , _theEtaLow(-1.1) + , _thePtHigh(999.9) + , _thePtLow(0) + , _thePHigh(999.9) + , _thePLow(-999.9) + , _thePzHigh(999.9) + , _thePzLow(-999.9) + , + + _doEtaHighCut(true) + , _doEtaLowCut(true) + , _doBothEtaCut(true) + , + + _doAbsEtaHighCut(false) + , _doAbsEtaLowCut(false) + , _doBothAbsEtaCut(false) + , + + _doPtHighCut(false) + , _doPtLowCut(false) + , _doBothPtCut(false) + , + _doPHighCut(false) + , _doPLowCut(false) + , _doBothPCut(false) + , + + _doPzHighCut(false) + , _doPzLowCut(false) + , _doBothPzCut(false) +{ + if (threshold != 0) + { + _doPtLowCut = true; + _thePtLow = threshold; + } +} + +//____________________________________________________________________________.. +int HepMCParticleTrigger::process_event(PHCompositeNode* topNode) +{ + // std::cout << "HepMCParticleTrigger::process_event(PHCompositeNode *topNode) Processing Event" << std::endl; + if (this->set_event_limit == true) + { // needed to keep all HepMC output at the same number of events + if (n_good >= this->goal_event_number) + { + return Fun4AllReturnCodes::ABORTEVENT; + } + } + n_evts++; + bool good_event{false}; + PHHepMCGenEventMap* phg = findNode::getClass(topNode, "PHHepMCGenEventMap"); + if (!phg) + { + return Fun4AllReturnCodes::ABORTEVENT; + } + for (PHHepMCGenEventMap::ConstIter eventIter = phg->begin(); eventIter != phg->end(); ++eventIter) + { + PHHepMCGenEvent* hepev = eventIter->second; + if (!hepev) + { + return Fun4AllReturnCodes::ABORTEVENT; + } + HepMC::GenEvent* ev = hepev->getEvent(); + if (!ev) + { + return Fun4AllReturnCodes::ABORTEVENT; + } + good_event = isGoodEvent(ev); + if (!good_event) + { + return Fun4AllReturnCodes::ABORTEVENT; + } + } + if (good_event) + { + n_good++; + } + return Fun4AllReturnCodes::EVENT_OK; +} +void HepMCParticleTrigger::AddParticle(int particlePid) +{ + _theParticles.push_back(particlePid); + return; +} +void HepMCParticleTrigger::AddParticles(const std::vector& particles) +{ + for (auto p : particles) + { + _theParticles.push_back(p); + } + return; +} + +void HepMCParticleTrigger::SetPtHigh(double pt) +{ + _thePtHigh = pt; + _doPtHighCut = true; + if (_doPtLowCut) + { + _doBothPtCut = true; + } + return; +} +void HepMCParticleTrigger::SetPtLow(double pt) +{ + _thePtLow = pt; + _doPtLowCut = true; + if (_doPtHighCut) + { + _doBothPtCut = true; + } + return; +} +void HepMCParticleTrigger::SetPtHighLow(double ptHigh, double ptLow) +{ + _thePtHigh = ptHigh; + _doPtHighCut = true; + _thePtLow = ptLow; + _doPtLowCut = true; + _doBothPtCut = true; + return; +} +void HepMCParticleTrigger::SetPHigh(double pt) +{ + _thePHigh = pt; + _doPHighCut = true; + if (_doPLowCut) + { + _doBothPCut = true; + } + return; +} +void HepMCParticleTrigger::SetPLow(double pt) +{ + _thePLow = pt; + _doPLowCut = true; + if (_doPHighCut) + { + _doBothPCut = true; + } + return; +} +void HepMCParticleTrigger::SetPHighLow(double ptHigh, double ptLow) +{ + _thePHigh = ptHigh; + _doPHighCut = true; + _thePLow = ptLow; + _doPLowCut = true; + _doBothPCut = true; + return; +} +void HepMCParticleTrigger::SetPzHigh(double pt) +{ + _thePzHigh = pt; + _doPzHighCut = true; + if (_doPzLowCut) + { + _doBothPzCut = true; + } + return; +} +void HepMCParticleTrigger::SetPzLow(double pt) +{ + _thePzLow = pt; + _doPzLowCut = true; + if (_doPzHighCut) + { + _doBothPzCut = true; + } + return; +} +void HepMCParticleTrigger::SetPzHighLow(double ptHigh, double ptLow) +{ + _thePzHigh = ptHigh; + _doPzHighCut = true; + _thePzLow = ptLow; + _doPzLowCut = true; + _doBothPzCut = true; + return; +} +void HepMCParticleTrigger::SetEtaHigh(double pt) +{ + _theEtaHigh = pt; + _doEtaHighCut = true; + if (_doEtaLowCut) + { + _doBothEtaCut = true; + } + return; +} +void HepMCParticleTrigger::SetEtaLow(double pt) +{ + _theEtaLow = pt; + _doEtaLowCut = true; + if (_doEtaHighCut) + { + _doBothEtaCut = true; + } + return; +} +void HepMCParticleTrigger::SetEtaHighLow(double ptHigh, double ptLow) +{ + _theEtaHigh = ptHigh; + _doEtaHighCut = true; + _theEtaLow = ptLow; + _doEtaLowCut = true; + _doBothEtaCut = true; + return; +} +void HepMCParticleTrigger::SetAbsEtaHigh(double pt) +{ + _theEtaHigh = pt; + _doAbsEtaHighCut = true; + if (_doAbsEtaLowCut) + { + _doBothAbsEtaCut = true; + } + return; +} +void HepMCParticleTrigger::SetAbsEtaLow(double pt) +{ + _theEtaLow = pt; + _doAbsEtaLowCut = true; + if (_doAbsEtaHighCut) + { + _doBothAbsEtaCut = true; + } + return; +} +void HepMCParticleTrigger::SetAbsEtaHighLow(double ptHigh, double ptLow) +{ + _theEtaHigh = ptHigh; + _doAbsEtaHighCut = true; + _theEtaLow = ptLow; + _doAbsEtaLowCut = true; + _doBothAbsEtaCut = true; + return; +} +bool HepMCParticleTrigger::isGoodEvent(HepMC::GenEvent* e1) +{ + std::vector n_trigger_particles = getParticles(e1); + for (auto ntp : n_trigger_particles) + { + if (ntp <= 0) + { + return false; // make sure all particles have at least 1 + } + } + return true; +} + +std::vector HepMCParticleTrigger::getParticles(HepMC::GenEvent* e1) +{ + std::vector n_trigger{}; + std::unordered_set particle_pids; + particle_pids.reserve(_theParticles.size()); + for (auto it : _theParticles) + { + particle_pids.insert(std::abs(it)); + } + std::unordered_map particle_types; + particle_types.reserve(particle_pids.size()); + + for (HepMC::GenEvent::particle_const_iterator iter = e1->particles_begin(); iter != e1->particles_end(); ++iter) + { + const HepMC::GenParticle *g = *iter; + if (m_doStableParticleOnly && (g->end_vertex() || g->status() != 1)) + { + continue; + } + + int pid = std::abs(g->pdg_id()); + auto ipidx = particle_pids.find(pid); + if(ipidx == particle_pids.end()) + { + continue; + } + + if (m_rejectFromHadronDecay) + { + if(IsFromHadronDecay(g)) + { + continue; + } + } + + auto p = g->momentum(); + float px = p.px(); + float py = p.py(); + float pz = p.pz(); + float p_M = std::sqrt(std::pow(px, 2) + std::pow(py, 2) + std::pow(pz, 2)); + float pt = std::sqrt(std::pow(px, 2) + std::pow(py, 2)); + double eta = p.eta(); + + if ((_doEtaHighCut || _doBothEtaCut) && eta > _theEtaHigh) + { + continue; + } + if ((_doEtaLowCut || _doBothEtaCut) && eta < _theEtaLow) + { + continue; + } + if ((_doAbsEtaHighCut || _doBothAbsEtaCut) && std::abs(eta) > _theEtaHigh) + { + continue; + } + if ((_doAbsEtaLowCut || _doBothAbsEtaCut) && std::abs(eta) < _theEtaLow) + { + continue; + } + if ((_doPtHighCut || _doBothPtCut) && pt > _thePtHigh) + { + continue; + } + if ((_doPtLowCut || _doBothPtCut) && pt < _thePtLow) + { + continue; + } + if ((_doPHighCut || _doBothPCut) && p_M > _thePHigh) + { + continue; + } + if ((_doPLowCut || _doBothPCut) && p_M < _thePLow) + { + continue; + } + if ((_doPzHighCut || _doBothPzCut) && pz > _thePzHigh) + { + continue; + } + if ((_doPzLowCut || _doBothPzCut) && pz < _thePzLow) + { + continue; + } + + particle_types[pid]++; + + if(particle_types.size() == particle_pids.size()) + { + break; + } + } + + n_trigger.reserve(_theParticles.size()); + + for (auto it : _theParticles) + { + auto ptid = particle_types.find(std::abs(it)); + n_trigger.push_back((ptid != particle_types.end()) ? ptid->second : 0); + } + return n_trigger; +} + +int HepMCParticleTrigger::particleAboveThreshold(const std::map& n_particles, int trigger_particle) +{ + // search through for the number of identified trigger particles passing cuts + auto it = n_particles.find(std::abs(trigger_particle)); + if (it != n_particles.end()) + { + return it->second; + } + return 0; +} + +bool HepMCParticleTrigger::IsFromHadronDecay(const HepMC::GenParticle* gp) +{ + if (!gp) + { + return false; + } + + const HepMC::GenVertex* vtx = gp->production_vertex(); + if (!vtx) + { + return false; + } + + for (auto it = vtx->particles_in_const_begin(); it != vtx->particles_in_const_end(); ++it) + { + const HepMC::GenParticle* mom = *it; + if (!mom) + { + continue; + } + + if (IsHadronPDG(mom->pdg_id())) + { + return true; + } + } + return false; +} + + +bool HepMCParticleTrigger::IsHadronPDG(int _pdg) +{ + if(IsIonPDG(_pdg)) + { + return false; + } + + if(std::abs(_pdg) < 100 ) + { + return false; + } + + return true; +} diff --git a/generators/Herwig/HepMCTrigger/HepMCParticleTrigger.h b/generators/Herwig/HepMCTrigger/HepMCParticleTrigger.h new file mode 100644 index 0000000000..22bcf241d4 --- /dev/null +++ b/generators/Herwig/HepMCTrigger/HepMCParticleTrigger.h @@ -0,0 +1,124 @@ +// Tell emacs that this is a C++ source +// -*- C++ -*-. +#ifndef HEPMCPARTICLETRIGGER_H +#define HEPMCPARTICLETRIGGER_H + +#include + +#include + +#include +#include +#include +#include + +class PHCompositeNode; +namespace HepMC +{ + class GenEvent; + class GenParticle; +} + +class HepMCParticleTrigger : public SubsysReco +{ + public: + HepMCParticleTrigger(float trigger_thresh = 10., int n_incom = 1000, bool up_lim = false, const std::string& name = "HepMCParticleTrigger"); + + ~HepMCParticleTrigger() override = default; + + /** Called for each event. + This is where you do the real work. + */ + int process_event(PHCompositeNode* topNode) override; + + /// Clean up internals after each event. + + /// Called at the end of each run. + + /// Called at the end of all processing. + + /// Reset + void AddParticles(const std::vector&); //exclusively take input in the form of a pdg_ids (22 for photon, primary use case) + void AddParticle(int); + + /* void AddParents(const std::string &parents); + void AddParents(int parent); + void AddParents(std::vector parents); + void AddParentspID(std::vector parents); + */ + void SetPtHigh(double); + void SetPtLow(double); + void SetPtHighLow(double, double); + + void SetPHigh(double); + void SetPLow(double); + void SetPHighLow(double, double); + + void SetEtaHigh(double); + void SetEtaLow(double); + void SetEtaHighLow(double, double); + + void SetAbsEtaHigh(double); + void SetAbsEtaLow(double); + void SetAbsEtaHighLow(double, double); + + void SetPzHigh(double); + void SetPzLow(double); + void SetPzHighLow(double, double); + + void SetRejectFromHadronDecay(bool b) {m_rejectFromHadronDecay = b;} + void SetStableParticleOnly(bool b) { m_doStableParticleOnly = b; } + + int getNevts(){return this->n_evts;} + int getNgood(){return this->n_good;} + + bool IsFromHadronDecay(const HepMC::GenParticle* gp); + bool IsIonPDG(int _pdg) { return (std::abs(_pdg) >= 1000000000); } + + private: + bool isGoodEvent(HepMC::GenEvent* e1); + std::vector getParticles(HepMC::GenEvent* e1); + int particleAboveThreshold(const std::map& n_particles, int particle); + // std::vector _theParentsi {}; + std::vector _theParticles{}; + bool m_doStableParticleOnly{true}; + bool m_rejectFromHadronDecay{true}; + float threshold{0.}; + int goal_event_number{1000}; + bool set_event_limit{false}; + int n_evts{0}; + int n_good{0}; + + float _theEtaHigh{2.0}; + float _theEtaLow{-2.0}; + float _thePtHigh{999.9}; + float _thePtLow{-999.9}; + float _thePHigh{999.9}; + float _thePLow{-999.9}; + float _thePzHigh{999.9}; + float _thePzLow{-999.9}; + + bool _doEtaHighCut{true}; + bool _doEtaLowCut{true}; + bool _doBothEtaCut{true}; + + bool _doAbsEtaHighCut{false}; + bool _doAbsEtaLowCut{false}; + bool _doBothAbsEtaCut{false}; + + bool _doPtHighCut{false}; + bool _doPtLowCut{false}; + bool _doBothPtCut{false}; + + bool _doPHighCut{false}; + bool _doPLowCut{false}; + bool _doBothPCut{false}; + + bool _doPzHighCut{false}; + bool _doPzLowCut{false}; + bool _doBothPzCut{false}; + + bool IsHadronPDG(int _pdg); +}; + +#endif // HEPMCPARTICLETRIGGER_H diff --git a/generators/Herwig/HepMCTrigger/Makefile.am b/generators/Herwig/HepMCTrigger/Makefile.am index 17ef6c4221..9807a9a78e 100644 --- a/generators/Herwig/HepMCTrigger/Makefile.am +++ b/generators/Herwig/HepMCTrigger/Makefile.am @@ -12,20 +12,31 @@ AM_LDFLAGS = \ `fastjet-config --libs` pkginclude_HEADERS = \ - HepMCJetTrigger.h + HepMCJetTrigger.h \ + HepMCParticleTrigger.h lib_LTLIBRARIES = \ - libHepMCJetTrigger.la + libHepMCJetTrigger.la \ + libHepMCParticleTrigger.la libHepMCJetTrigger_la_SOURCES = \ HepMCJetTrigger.cc +libHepMCParticleTrigger_la_SOURCES = \ + HepMCParticleTrigger.cc + libHepMCJetTrigger_la_LIBADD = \ -lphool \ -lSubsysReco \ -lfun4all \ -lphhepmc +libHepMCParticleTrigger_la_LIBADD = \ + -lphool \ + -lSubsysReco \ + -lfun4all \ + -lphhepmc + BUILT_SOURCES = testexternals.cc noinst_PROGRAMS = \ diff --git a/generators/PHPythia8/PHPythia8.cc b/generators/PHPythia8/PHPythia8.cc index 9aa14d4684..ab059542b4 100644 --- a/generators/PHPythia8/PHPythia8.cc +++ b/generators/PHPythia8/PHPythia8.cc @@ -33,6 +33,20 @@ #include #include // for operator<<, endl +/** + * @brief Construct a PHPythia8 generator instance and configure HepMC conversion. + * + * Initializes the Pythia8 engine using the path from the environment variable + * `PYTHIA8`, configures a HepMC::Pythia8ToHepMC converter to store process, + * PDF, and cross-section information, and sets the default embedding ID to 1. + * The constructor preserves and restores std::cout formatting around Pythia8 + * construction to avoid altering global stream state. + * + * If `PYTHIA8` is not set, an error message is printed and the Pythia8 instance + * remains uninitialized. + * + * @param name Name forwarded to the SubsysReco base class (module instance name). + */ PHPythia8::PHPythia8(const std::string &name) : SubsysReco(name) { @@ -45,8 +59,12 @@ PHPythia8::PHPythia8(const std::string &name) std::string thePath(charPath); thePath += "/xmldoc/"; + // the pythia8 ctor messes with the formatting, so we save the cout state here + // and restore it later + std::ios old_state(nullptr); + old_state.copyfmt(std::cout); m_Pythia8.reset(new Pythia8::Pythia(thePath)); - + std::cout.copyfmt(old_state); m_Pythia8ToHepMC.reset(new HepMC::Pythia8ToHepMC()); m_Pythia8ToHepMC->set_store_proc(true); m_Pythia8ToHepMC->set_store_pdf(true); @@ -55,6 +73,18 @@ PHPythia8::PHPythia8(const std::string &name) PHHepMCGenHelper::set_embedding_id(1); // default embedding ID to 1 } +/** + * @brief Initialize the Pythia8 generator, configure nodes, and seed the RNG. + * + * Performs module initialization: reads an optional configuration file and any + * queued Pythia command strings, creates the required node tree under the + * provided top-level node, sets Pythia's random seed (mapped from PHRandomSeed + * into Pythia's valid range) and prints it for reproducibility, then calls + * Pythia8::init(). + * + * @param topNode Top-level PHCompositeNode under which generator nodes are created. + * @return int Fun4All return code; returns Fun4AllReturnCodes::EVENT_OK on success. + */ int PHPythia8::Init(PHCompositeNode *topNode) { if (!m_ConfigFileName.empty()) @@ -92,8 +122,15 @@ int PHPythia8::Init(PHCompositeNode *topNode) // print out seed so we can make this is reproducible std::cout << "PHPythia8 random seed: " << seed << std::endl; + +// pythia again messes with the cout formatting + std::ios old_state(nullptr); + old_state.copyfmt(std::cout); // save current state + m_Pythia8->init(); + std::cout.copyfmt(old_state); // restore state to saved state + return Fun4AllReturnCodes::EVENT_OK; } @@ -139,7 +176,7 @@ int PHPythia8::read_config(const std::string &cfg_file) if (Verbosity() >= VERBOSITY_SOME) { - std::cout << "PHPythia8::read_config - Reading " << m_ConfigFileName << std::endl; + std::cout << Name() << " PHPythia8::read_config - Reading " << m_ConfigFileName << std::endl; } std::ifstream infile(m_ConfigFileName); @@ -164,12 +201,15 @@ int PHPythia8::process_event(PHCompositeNode * /*topNode*/) { if (Verbosity() >= VERBOSITY_MORE) { - std::cout << "PHPythia8::process_event - event: " << m_EventCount << std::endl; + std::cout << Name() << " PHPythia8::process_event - event: " << m_EventCount << std::endl; } bool passedGen = false; bool passedTrigger = false; // int genCounter = 0; +// pythia again messes with the cout formatting in its event loop + std::ios old_state(nullptr); + old_state.copyfmt(std::cout); // save current state while (!passedTrigger) { @@ -208,7 +248,7 @@ int PHPythia8::process_event(PHCompositeNode * /*topNode*/) andScoreKeeper &= trigResult; } - if (Verbosity() >= VERBOSITY_EVEN_MORE && !passedTrigger) + if (Verbosity() >= VERBOSITY_EVEN_MORE && !passedTrigger && !andScoreKeeper) { std::cout << "PHPythia8::process_event - failed trigger: " << m_RegisteredTrigger->GetName() << std::endl; @@ -245,6 +285,7 @@ int PHPythia8::process_event(PHCompositeNode * /*topNode*/) if (!success) { std::cout << "PHPythia8::process_event - Failed to add event to HepMC record!" << std::endl; + std::cout.copyfmt(old_state); // restore state to saved state return Fun4AllReturnCodes::ABORTRUN; } @@ -265,6 +306,8 @@ int PHPythia8::process_event(PHCompositeNode * /*topNode*/) ++m_EventCount; + std::cout.copyfmt(old_state); // restore state to saved state + // save statistics if (m_IntegralNode) { diff --git a/generators/phhepmc/PHHepMCGenEventv1.cc b/generators/phhepmc/PHHepMCGenEventv1.cc index bc8eef6f41..3aa7515365 100644 --- a/generators/phhepmc/PHHepMCGenEventv1.cc +++ b/generators/phhepmc/PHHepMCGenEventv1.cc @@ -9,6 +9,7 @@ #include #include // for cout +#include #include // for map #include #include // for swap @@ -109,6 +110,6 @@ float PHHepMCGenEventv1::get_flow_psi(unsigned int n) const return it->second; } - std::cout << "PHHepMCGenEventv1::get_flow_psi - Warning - requested reaction plane angle psi_n for n=" << n << " does not exist. Returning 0.0" << std::endl; - return 0.0F; + std::cout << "PHHepMCGenEventv1::get_flow_psi - Warning - requested reaction plane angle psi_n for n=" << n << " does not exist. Returning NAN" << std::endl; + return std::numeric_limits::quiet_NaN(); } diff --git a/offline/QA/Calorimeters/CaloValid.cc b/offline/QA/Calorimeters/CaloValid.cc index 2451672807..fe815df37f 100644 --- a/offline/QA/Calorimeters/CaloValid.cc +++ b/offline/QA/Calorimeters/CaloValid.cc @@ -84,7 +84,23 @@ int CaloValid::Init(PHCompositeNode* /*unused*/) return Fun4AllReturnCodes::EVENT_OK; } -// Note: InitRun cannot be made static as it modifies member variable m_species +/** + * @brief Determine the collision species for the current run and set m_species. + * + * Reads the RunHeader from the provided node tree, inspects the run number, and sets + * the member variable `m_species` to one of the recognized values ("pp", "AuAu", "OO"). + * If the run number does not match any known range or the RunHeader is missing, + * `m_species` remains unchanged (default behavior uses "pp" elsewhere) and a diagnostic + * message may be printed depending on verbosity. + * + * Recognized mappings: + * - RUN2PP_* -> "pp" + * - RUN2AUAU_* or RUN3AUAU_* -> "AuAu" + * - RUN3OO_* -> "OO" + * + * @param topNode Top-level node of the event tree used to locate the RunHeader. + * @return int EVENT_OK on success. + */ int CaloValid::InitRun(PHCompositeNode* topNode) { RunHeader* runhdr = findNode::getClass(topNode, "RunHeader"); @@ -117,6 +133,14 @@ int CaloValid::InitRun(PHCompositeNode* topNode) std::cout << "This run is from Run-3 Au+Au.\n"; } } + else if (runnumber >= RunnumberRange::RUN3OO_FIRST && runnumber <= RunnumberRange::RUN3OO_LAST) + { + m_species = "OO"; + if (Verbosity() > 0) + { + std::cout << "This run is from Run-3 O+O.\n"; + } + } else { if (Verbosity() > 0) @@ -142,6 +166,20 @@ int CaloValid::process_event(PHCompositeNode* topNode) return Fun4AllReturnCodes::EVENT_OK; } +/** + * @brief Process event towers, triggers, MBD, and clusters to populate QA histograms. + * + * Reads event header, vertex, trigger (GL1), calibrated and raw tower containers for + * CEMC/HCAL (inner/outer), MBD PMTs, and CEMC clusters; computes per-detector totals, + * downscaled correlations, per-channel and per-tower QA, pi0 candidate invariant masses, + * and trigger/alignment summaries, then fills the corresponding histograms and profiles. + * + * @param topNode Top-level PHCompositeNode containing event data (towers, clusters, + * trigger/GL1 packets, vertex map, and MBD PMTs). + * @return Fun4AllReturnCodes::EVENT_OK on success; may return other Fun4All return codes + * or 0 on error conditions encountered while processing nodes. + * + */ int CaloValid::process_towers(PHCompositeNode* topNode) { //---------------------------Event header--------------------------------// @@ -176,7 +214,8 @@ int CaloValid::process_towers(PHCompositeNode* topNode) float ihcaldownscale; float ohcaldownscale; float mbddownscale; - float adc_threshold; + float adc_threshold_hcal; + float adc_threshold_emcal; float emcal_hit_threshold; float emcal_highhit_threshold; float ohcal_hit_threshold; @@ -190,7 +229,28 @@ int CaloValid::process_towers(PHCompositeNode* topNode) ihcaldownscale = 55000. / 300.; ohcaldownscale = 265000. / 600.; mbddownscale = 2800.0; - adc_threshold = 15.; + adc_threshold_hcal = 30; + adc_threshold_emcal = 70; + + emcal_hit_threshold = 0.5; // GeV + ohcal_hit_threshold = 0.5; + ihcal_hit_threshold = 0.25; + + emcal_highhit_threshold = 3.0; + ohcal_highhit_threshold = 3.0; + ihcal_highhit_threshold = 3.0; + } + else if (m_species == "OO") + { + // Scale by the ratio of nucleons: OO/AuAu + float scale_factor = 16. / 197.; + + emcaldownscale = (1350000. / 800.) * scale_factor; + ihcaldownscale = (55000. / 300.) * scale_factor; + ohcaldownscale = (265000. / 600.) * scale_factor; + mbddownscale = 2800.0 * scale_factor; + adc_threshold_hcal = 30; + adc_threshold_emcal = 70; emcal_hit_threshold = 0.5; // GeV ohcal_hit_threshold = 0.5; @@ -206,7 +266,8 @@ int CaloValid::process_towers(PHCompositeNode* topNode) ihcaldownscale = 4000. / 300.; ohcaldownscale = 25000. / 600.; mbddownscale = 200.0; - adc_threshold = 100.; + adc_threshold_hcal = 30; + adc_threshold_emcal = 70; emcal_hit_threshold = 0.5; // GeV ohcal_hit_threshold = 0.5; @@ -335,13 +396,16 @@ int CaloValid::process_towers(PHCompositeNode* topNode) status = status >> 1U; // clang-tidy mark 1 as unsigned } - totalcemc += offlineenergy; + if (isGood) + { + totalcemc += offlineenergy; + } h_emcaltime->Fill(_timef); if (offlineenergy > emcal_hit_threshold) { h_cemc_etaphi_time->Fill(ieta, iphi, _timef); h_cemc_etaphi->Fill(ieta, iphi); - if (isGood && (scaledBits[10] || scaledBits[11])) + if (isGood && (scaledBits[10] || scaledBits[12])) { h_cemc_etaphi_wQA->Fill(ieta, iphi, offlineenergy); } @@ -407,14 +471,17 @@ int CaloValid::process_towers(PHCompositeNode* topNode) status = status >> 1U; // clang-tidy mark 1 as unsigned } - totalihcal += offlineenergy; + if (isGood) + { + totalihcal += offlineenergy; + } h_ihcaltime->Fill(_timef); if (offlineenergy > ihcal_hit_threshold) { h_ihcal_etaphi->Fill(ieta, iphi); h_ihcal_etaphi_time->Fill(ieta, iphi, _timef); - if (isGood && (scaledBits[10] || scaledBits[11])) + if (isGood && (scaledBits[10] || scaledBits[12])) { h_ihcal_etaphi_wQA->Fill(ieta, iphi, offlineenergy); } @@ -472,14 +539,17 @@ int CaloValid::process_towers(PHCompositeNode* topNode) status = status >> 1U; // clang-tidy mark 1 as unsigned } - totalohcal += offlineenergy; + if (isGood) + { + totalohcal += offlineenergy; + } h_ohcaltime->Fill(_timef); if (offlineenergy > ohcal_hit_threshold) { h_ohcal_etaphi_time->Fill(ieta, iphi, _timef); h_ohcal_etaphi->Fill(ieta, iphi); - if (isGood && (scaledBits[10] || scaledBits[11])) + if (isGood && (scaledBits[10] || scaledBits[12])) { h_ohcal_etaphi_wQA->Fill(ieta, iphi, offlineenergy); } @@ -519,7 +589,7 @@ int CaloValid::process_towers(PHCompositeNode* topNode) } float raw_energy = tower->get_energy(); - if (raw_energy > adc_threshold) + if (raw_energy > adc_threshold_emcal) { h_cemc_etaphi_fracHitADC->Fill(ieta, iphi, 1); h_cemc_etaphi_time_raw->Fill(ieta, iphi, raw_time); @@ -549,7 +619,7 @@ int CaloValid::process_towers(PHCompositeNode* topNode) } float raw_energy = tower->get_energy(); - if (raw_energy > adc_threshold) + if (raw_energy > adc_threshold_hcal) { h_ohcal_etaphi_time_raw->Fill(ieta, iphi, raw_time); h_ohcal_etaphi_fracHitADC->Fill(ieta, iphi, 1); @@ -579,7 +649,7 @@ int CaloValid::process_towers(PHCompositeNode* topNode) } float raw_energy = tower->get_energy(); - if (raw_energy > adc_threshold) + if (raw_energy > adc_threshold_hcal) { h_ihcal_etaphi_time_raw->Fill(ieta, iphi, raw_time); h_ihcal_etaphi_fracHitADC->Fill(ieta, iphi, 1); diff --git a/offline/QA/Calorimeters/CaloValid.h b/offline/QA/Calorimeters/CaloValid.h index 2e2f9e278e..baaede0fe5 100644 --- a/offline/QA/Calorimeters/CaloValid.h +++ b/offline/QA/Calorimeters/CaloValid.h @@ -55,7 +55,7 @@ class CaloValid : public SubsysReco TriggerAnalyzer* trigAna{nullptr}; TH3* h_pi0_trigIB_mass{nullptr}; - std::vector triggerIndices{10, 28, 29, 30, 31}; // MBD NS>=1, Photon Triggers + std::vector triggerIndices{10, 12, 28, 29, 30, 31}; // MBD NS>=1, Photon Triggers TH1* h_cemc_channel_pedestal[128 * 192]{nullptr}; TH1* h_ihcal_channel_pedestal[32 * 48]{nullptr}; diff --git a/offline/QA/Jet/CaloStatusMapperDefs.h b/offline/QA/Jet/CaloStatusMapperDefs.h index c77d1b765c..08f8289fe0 100644 --- a/offline/QA/Jet/CaloStatusMapperDefs.h +++ b/offline/QA/Jet/CaloStatusMapperDefs.h @@ -59,7 +59,6 @@ namespace CaloStatusMapperDefs { Good, Hot, - BadTime, BadChi, NotInstr, NoCalib, @@ -74,7 +73,6 @@ namespace CaloStatusMapperDefs static std::map mapStatLabels = { {Stat::Good, "Good"}, {Stat::Hot, "Hot"}, - {Stat::BadTime, "BadTime"}, {Stat::BadChi, "BadChi"}, {Stat::NotInstr, "NotInstr"}, {Stat::NoCalib, "NoCalib"}, @@ -173,10 +171,6 @@ namespace CaloStatusMapperDefs { status = Stat::Hot; } - else if (tower->get_isBadTime()) - { - status = Stat::BadTime; - } else if (tower->get_isBadChi2()) { status = Stat::BadChi; @@ -204,7 +198,6 @@ namespace CaloStatusMapperDefs { bool skip = false; if ((label == "Hot") || - (label == "BadTime") || (label == "BadChi") || (label == "NoCalib") || (label == "NotInstr") || diff --git a/offline/QA/Tracking/Makefile.am b/offline/QA/Tracking/Makefile.am index f5d87546f1..75cbdf164b 100644 --- a/offline/QA/Tracking/Makefile.am +++ b/offline/QA/Tracking/Makefile.am @@ -17,6 +17,7 @@ pkginclude_HEADERS = \ TpcSeedsQA.h \ TpcSiliconQA.h \ SiliconSeedsQA.h \ + StateClusterResidualsQA.h \ MicromegasClusterQA.h \ CosmicTrackQA.h \ TrackFittingQA.h \ @@ -32,6 +33,7 @@ libtrackingqa_la_SOURCES = \ TpcSeedsQA.cc \ TpcSiliconQA.cc \ SiliconSeedsQA.cc \ + StateClusterResidualsQA.cc \ MicromegasClusterQA.cc \ CosmicTrackQA.cc \ TrackFittingQA.cc \ diff --git a/offline/QA/Tracking/MicromegasClusterQA.cc b/offline/QA/Tracking/MicromegasClusterQA.cc index 41efeffaa7..6feb510c54 100644 --- a/offline/QA/Tracking/MicromegasClusterQA.cc +++ b/offline/QA/Tracking/MicromegasClusterQA.cc @@ -73,6 +73,9 @@ int MicromegasClusterQA::InitRun(PHCompositeNode* topNode) << (m_calibration_filename.empty() ? "unspecified" : m_calibration_filename) << std::endl; + std::cout << "MicromegasClusterQA::InitRun - m_sample_min: " << m_sample_min << std::endl; + std::cout << "MicromegasClusterQA::InitRun - m_sample_max: " << m_sample_max << std::endl; + // read calibrations if (!m_calibration_filename.empty()) { @@ -162,6 +165,13 @@ int MicromegasClusterQA::process_event(PHCompositeNode* topNode) // find associated hits const auto hit_range = m_cluster_hit_map->getHits(ckey); + // check hit samples + // if none of the associated hits' sample is within acceptable range, skip the cluster + if( std::none_of( hit_range.first, hit_range.second, + [this]( const TrkrClusterHitAssoc::Map::value_type& pair ) + { return MicromegasDefs::getSample( pair.second ) >= m_sample_min && MicromegasDefs::getSample( pair.second ) < m_sample_max; } ) ) + { continue; } + // store cluster size and fill cluster size histogram const int cluster_size = std::distance(hit_range.first, hit_range.second); m_h_cluster_size->Fill(detid, cluster_size); diff --git a/offline/QA/Tracking/MicromegasClusterQA.h b/offline/QA/Tracking/MicromegasClusterQA.h index 338e5302de..d6de8344c4 100644 --- a/offline/QA/Tracking/MicromegasClusterQA.h +++ b/offline/QA/Tracking/MicromegasClusterQA.h @@ -51,6 +51,13 @@ class MicromegasClusterQA : public SubsysReco m_calibration_filename = value; } + /// set min sample for signal hits + void set_sample_min(uint16_t value) { m_sample_min = value; } + + /// set max sample for signal hits + void set_sample_max(uint16_t value) { m_sample_max = value; } + + private: void create_histograms(); @@ -98,6 +105,12 @@ class MicromegasClusterQA : public SubsysReco /// keep track of detector names std::vector m_detector_names; + /// min sample for signal + uint16_t m_sample_min = 0; + + /// max sample for signal + uint16_t m_sample_max = 1024; + ///@name calibration filename //@{ diff --git a/offline/QA/Tracking/SiliconSeedsQA.cc b/offline/QA/Tracking/SiliconSeedsQA.cc index 14a9feeaed..6f2ba5e91a 100644 --- a/offline/QA/Tracking/SiliconSeedsQA.cc +++ b/offline/QA/Tracking/SiliconSeedsQA.cc @@ -233,7 +233,7 @@ void SiliconSeedsQA::createHistos() } { - h_ntrack1d = new TH1F(std::string(getHistoPrefix() + "nrecotracks1d").c_str(), "Number of reconstructed tracks;Number of silicon tracklets;Entries", 50, 0, 200); + h_ntrack1d = new TH1F(std::string(getHistoPrefix() + "nrecotracks1d").c_str(), "Number of reconstructed tracks;Number of silicon tracklets;Entries", 500, 0, 2000); hm->registerHisto(h_ntrack1d); } @@ -248,7 +248,7 @@ void SiliconSeedsQA::createHistos() } { - h_trackcrossing = new TH1F(std::string(getHistoPrefix() + "trackcrossing").c_str(), "Track beam bunch crossing;Track crossing;Entries", 110, -10, 100); + h_trackcrossing = new TH1F(std::string(getHistoPrefix() + "trackcrossing").c_str(), "Track beam bunch crossing;Track crossing;Entries", 1000, -200, 800); hm->registerHisto(h_trackcrossing); } @@ -304,7 +304,7 @@ void SiliconSeedsQA::createHistos() // vertex { - h_nvertex = new TH1F(std::string(getHistoPrefix() + "nrecovertices").c_str(), "Num of reco vertices per event;Number of vertices;Entries", 20, 0, 20); + h_nvertex = new TH1F(std::string(getHistoPrefix() + "nrecovertices").c_str(), "Num of reco vertices per event;Number of vertices;Entries", 60, 0, 60); hm->registerHisto(h_nvertex); } diff --git a/offline/QA/Tracking/StateClusterResidualsQA.cc b/offline/QA/Tracking/StateClusterResidualsQA.cc new file mode 100644 index 0000000000..d2239ede5d --- /dev/null +++ b/offline/QA/Tracking/StateClusterResidualsQA.cc @@ -0,0 +1,400 @@ +#include "StateClusterResidualsQA.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +namespace +{ + template + inline T square (T const& t) { return t * t; } + + template + class range_adaptor + { + public: + explicit range_adaptor( + T const& begin, + T const& end) + : m_begin(begin) + , m_end(end) + { + } + T const& begin() { return m_begin; } + T const& end() { return m_end; } + + private: + T m_begin; + T m_end; + }; +} // namespace + +StateClusterResidualsQA::StateClusterResidualsQA(const std::string& name) + : SubsysReco(name) +{ +} + +int StateClusterResidualsQA::InitRun( + PHCompositeNode* top_node) +{ + createHistos(); + + // F4A will not actually ABORTRUN unless that return code is issued here + auto* track_map = findNode::getClass(top_node, m_track_map_node_name); + if (!track_map) + { + std::cout + << PHWHERE << "\n" + << "\tCould not get track map:\n" + << "\t\"" << m_track_map_node_name << "\"\n" + << "\tAborting\n" + << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + auto* cluster_map = findNode::getClass(top_node, m_clusterContainerName); + if (!cluster_map) + { + std::cout + << PHWHERE << "\n" + << "\tCould not get cluster map:\n" + << "\t\"" << m_clusterContainerName << "\"\n" + << "\tAborting\n" + << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + auto *geometry = findNode::getClass(top_node, "ActsGeometry"); + if (!geometry) + { + std::cout + << PHWHERE << "\n" + << "\tCould not get ActsGeometry:\n" + << "\t\"" << "ActsGeometry" << "\"\n" + << "\tAborting\n" + << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + auto* hm = QAHistManagerDef::getHistoManager(); + if (!hm) + { + std::cout + << PHWHERE << "\n" + << "\tCould not get QAHistManager\n" + << "\tAborting\n" + << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + for (const auto& cfg : m_pending) + { + if (m_use_local_coords) + { + m_histograms_x.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_local_rphi")))); + m_histograms_y.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_local_z")))); + m_histograms_layer_x.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_local_layer_rphi")))); + m_histograms_layer_y.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_local_layer_z")))); + m_histograms_phi_x.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_local_phi_rphi")))); + m_histograms_phi_y.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_local_phi_z")))); + m_histograms_eta_x.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_local_eta_rphi")))); + m_histograms_eta_y.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_local_eta_z")))); + } + else + { + m_histograms_x.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_x")))); + m_histograms_y.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_y")))); + m_histograms_z.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_z")))); + m_histograms_layer_x.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_layer_x")))); + m_histograms_layer_y.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_layer_y")))); + m_histograms_layer_z.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_layer_z")))); + m_histograms_phi_x.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_phi_x")))); + m_histograms_phi_y.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_phi_y")))); + m_histograms_phi_z.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_phi_z")))); + m_histograms_eta_x.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_eta_x")))); + m_histograms_eta_y.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_eta_y")))); + m_histograms_eta_z.push_back(dynamic_cast(hm->getHisto(std::string(cfg.name + "_eta_z")))); + } + } + + return Fun4AllReturnCodes::EVENT_OK; +} + +int StateClusterResidualsQA::process_event(PHCompositeNode* top_node) +{ + auto* track_map = findNode::getClass(top_node, m_track_map_node_name); + auto *cluster_map = findNode::getClass(top_node, m_clusterContainerName); + auto *geometry = findNode::getClass(top_node, "ActsGeometry"); + + for (auto const& [idkey, track] : *track_map) + { + if (!track) + { + continue; + } + + // count states + std::map counters = { + {TrkrDefs::mvtxId, 0}, + {TrkrDefs::inttId, 0}, + {TrkrDefs::tpcId, 0}, + {TrkrDefs::micromegasId, 0}, + }; + + for (auto const& [path_length, state] : range_adaptor(track->begin_states(), track->end_states())) + { + // There is an additional state representing the vertex at the beginning of the map, + // but getTrkrId will return 0 for its corresponding cluster + // Identify it as having path_length identically equal to 0 + if (path_length == 0) { continue; } + + auto trkr_id = static_cast(TrkrDefs::getTrkrId(state->get_cluskey())); + auto itr = counters.find(trkr_id); + if (itr == counters.end()) { continue; } + ++itr->second; + } + + float track_eta = track->get_eta(); + float track_phi = track->get_phi(); + float track_pt = track->get_pt(); + int h = 0; + for (const auto& cfg : m_pending) + { + if (cfg.charge != 0) + { + if ((cfg.charge < 0) && track->get_positive_charge()) + { + continue; + } + if ((cfg.charge > 0) && !(track->get_positive_charge())) + { + continue; + } + } + if (cfg.min_mvtx_clusters <= counters[TrkrDefs::mvtxId] && cfg.max_mvtx_clusters >= counters[TrkrDefs::mvtxId] + && cfg.min_intt_clusters <= counters[TrkrDefs::inttId] && cfg.max_intt_clusters >= counters[TrkrDefs::inttId] + && cfg.min_tpc_clusters <= counters[TrkrDefs::tpcId] && cfg.max_tpc_clusters >= counters[TrkrDefs::tpcId] + && cfg.phi_min <= track_phi && cfg.phi_max >= track_phi + && cfg.eta_min <= track_eta && cfg.eta_max >= track_eta + && cfg.pt_min <= track_pt && cfg.pt_max >= track_pt) + { + for (auto const& [path_length, state] : range_adaptor(track->begin_states(), track->end_states())) + { + if (path_length == 0) { continue; } + + auto *cluster = cluster_map->findCluster(state->get_cluskey()); + if (!cluster) + { + continue; + } + + float state_x; + float state_y; + float state_z; + float cluster_x; + float cluster_y; + float cluster_z; + if (m_use_local_coords == true) + { + state_x = state->get_localX(); + state_y = state->get_localY(); + Acts::Vector2 loc = geometry->getLocalCoords(state->get_cluskey(), cluster); + cluster_x = loc.x(); + cluster_y = loc.y(); + m_histograms_x[h]->Fill(state_x - cluster_x); + m_histograms_y[h]->Fill(state_y - cluster_y); + m_histograms_layer_x[h]->Fill(TrkrDefs::getLayer(state->get_cluskey()), state_x - cluster_x); + m_histograms_layer_y[h]->Fill(TrkrDefs::getLayer(state->get_cluskey()), state_y - cluster_y); + m_histograms_phi_x[h]->Fill(state->get_phi(), state_x - cluster_x); + m_histograms_phi_y[h]->Fill(state->get_phi(), state_y - cluster_y); + m_histograms_eta_x[h]->Fill(state->get_eta(), state_x - cluster_x); + m_histograms_eta_y[h]->Fill(state->get_eta(), state_y - cluster_y); + } + else + { + state_x = state->get_x(); + state_y = state->get_y(); + state_z = state->get_z(); + Acts::Vector3 glob = geometry->getGlobalPosition(state->get_cluskey(), cluster); + cluster_x = glob.x(); + cluster_y = glob.y(); + cluster_z = glob.z(); + m_histograms_x[h]->Fill(state_x - cluster_x); + m_histograms_y[h]->Fill(state_y - cluster_y); + m_histograms_z[h]->Fill(state_z - cluster_z); + m_histograms_layer_x[h]->Fill(TrkrDefs::getLayer(state->get_cluskey()), state_x - cluster_x); + m_histograms_layer_y[h]->Fill(TrkrDefs::getLayer(state->get_cluskey()), state_y - cluster_y); + m_histograms_layer_z[h]->Fill(TrkrDefs::getLayer(state->get_cluskey()), state_z - cluster_z); + m_histograms_phi_x[h]->Fill(state->get_phi(), state_x - cluster_x); + m_histograms_phi_y[h]->Fill(state->get_phi(), state_y - cluster_y); + m_histograms_phi_z[h]->Fill(state->get_phi(), state_z - cluster_z); + m_histograms_eta_x[h]->Fill(state->get_eta(), state_x - cluster_x); + m_histograms_eta_y[h]->Fill(state->get_eta(), state_y - cluster_y); + m_histograms_eta_z[h]->Fill(state->get_eta(), state_z - cluster_z); + } + } + } + ++h; + } + } + + return Fun4AllReturnCodes::EVENT_OK; +} + +void StateClusterResidualsQA::createHistos() +{ + auto *hm = QAHistManagerDef::getHistoManager(); + assert(hm); + + for (const auto& cfg : m_pending) + { + if (m_use_local_coords) + { + TH1F* h_new_x = new TH1F( + (cfg.name + "_local_rphi").c_str(), + ";State-Cluster Local r#phi Residual [cm];Entries", + m_nBins, cfg.rphi_local_lower, cfg.rphi_local_upper); + h_new_x->SetMarkerColor(kBlue); + h_new_x->SetLineColor(kBlue); + hm->registerHisto(h_new_x); + TH1F* h_new_y = new TH1F( + (cfg.name + "_local_z").c_str(), + ";State-Cluster Local Z Residual [cm];Entries", + m_nBins, cfg.z_local_lower, cfg.z_local_upper); + h_new_y->SetMarkerColor(kBlue); + h_new_y->SetLineColor(kBlue); + hm->registerHisto(h_new_y); + TH2F* h_new_layer_x = new TH2F( + (cfg.name + "_local_layer_rphi").c_str(), + ";Layer Number;State-Cluster Local r#phi Residual [cm]", + 60, -0.5, 59.5, m_nBins, cfg.rphi_local_lower, cfg.rphi_local_upper); + hm->registerHisto(h_new_layer_x); + TH2F* h_new_layer_y = new TH2F( + (cfg.name + "_local_layer_z").c_str(), + ";Layer Number;State-Cluster Local Z Residual [cm]", + 60, -0.5, 59.5, m_nBins, cfg.z_local_lower, cfg.z_local_upper); + hm->registerHisto(h_new_layer_y); + TH2F* h_new_phi_x = new TH2F( + (cfg.name + "_local_phi_rphi").c_str(), + ";#phi [rad];State-Cluster Local r#phi Residual [cm]", + 50, -3.2, 3.2, m_nBins, cfg.rphi_local_lower, cfg.rphi_local_upper); + hm->registerHisto(h_new_phi_x); + TH2F* h_new_phi_y = new TH2F( + (cfg.name + "_local_phi_z").c_str(), + ";#phi [rad];State-Cluster Local Z Residual [cm]", + 50, -3.2, 3.2, m_nBins, cfg.z_local_lower, cfg.z_local_upper); + hm->registerHisto(h_new_phi_y); + TH2F* h_new_eta_x = new TH2F( + (cfg.name + "_local_eta_rphi").c_str(), + ";#eta;State-Cluster Local r#phi Residual [cm]", + 50, -1.1, 1.1, m_nBins, cfg.rphi_local_lower, cfg.rphi_local_upper); + hm->registerHisto(h_new_eta_x); + TH2F* h_new_eta_y = new TH2F( + (cfg.name + "_local_eta_z").c_str(), + ";#eta;State-Cluster Local Z Residual [cm]", + 50, -1.1, 1.1, m_nBins, cfg.z_local_lower, cfg.z_local_upper); + hm->registerHisto(h_new_eta_y); + } + else + { + TH1F* h_new_x = new TH1F( + (cfg.name + "_x").c_str(), + ";State-Cluster X Residual [cm];Entries", + m_nBins, cfg.x_lower, cfg.x_upper); + h_new_x->SetMarkerColor(kBlue); + h_new_x->SetLineColor(kBlue); + hm->registerHisto(h_new_x); + TH1F* h_new_y = new TH1F( + (cfg.name + "_y").c_str(), + ";State-Cluster Y Residual [cm];Entries", + m_nBins, cfg.y_lower, cfg.y_upper); + h_new_y->SetMarkerColor(kBlue); + h_new_y->SetLineColor(kBlue); + hm->registerHisto(h_new_y); + TH1F* h_new_z = new TH1F( + (cfg.name + "_z").c_str(), + ";State-Cluster Z Residual [cm];Entries", + m_nBins, cfg.z_lower, cfg.z_upper); + h_new_z->SetMarkerColor(kBlue); + h_new_z->SetLineColor(kBlue); + hm->registerHisto(h_new_z); + TH2F* h_new_layer_x = new TH2F( + (cfg.name + "_layer_x").c_str(), + ";Layer Number;State-Cluster Local X Residual [cm]", + 60, -0.5, 59.5, m_nBins, cfg.x_lower, cfg.x_upper); + hm->registerHisto(h_new_layer_x); + TH2F* h_new_layer_y = new TH2F( + (cfg.name + "_layer_y").c_str(), + ";Layer Number;State-Cluster Local Y Residual [cm]", + 60, -0.5, 59.5, m_nBins, cfg.y_lower, cfg.y_upper); + hm->registerHisto(h_new_layer_y); + TH2F* h_new_layer_z = new TH2F( + (cfg.name + "_layer_z").c_str(), + ";Layer Number;State-Cluster Local Z Residual [cm]", + 60, -0.5, 59.5, m_nBins, cfg.z_lower, cfg.z_upper); + hm->registerHisto(h_new_layer_z); + TH2F* h_new_phi_x = new TH2F( + (cfg.name + "_phi_x").c_str(), + ";#phi [rad];State-Cluster Local X Residual [cm]", + 50, -3.2, 3.2, m_nBins, cfg.x_lower, cfg.x_upper); + hm->registerHisto(h_new_phi_x); + TH2F* h_new_phi_y = new TH2F( + (cfg.name + "_phi_y").c_str(), + ";#phi [rad];State-Cluster Local Y Residual [cm]", + 50, -3.2, 3.2, m_nBins, cfg.y_lower, cfg.y_upper); + hm->registerHisto(h_new_phi_y); + TH2F* h_new_phi_z = new TH2F( + (cfg.name + "_phi_z").c_str(), + ";#phi [rad];State-Cluster Local Z Residual [cm]", + 50, -3.2, 3.2, m_nBins, cfg.z_lower, cfg.z_upper); + hm->registerHisto(h_new_phi_z); + TH2F* h_new_eta_x = new TH2F( + (cfg.name + "_eta_x").c_str(), + ";#eta;State-Cluster Local X Residual [cm]", + 50, -1.1, 1.1, m_nBins, cfg.x_lower, cfg.x_upper); + hm->registerHisto(h_new_eta_x); + TH2F* h_new_eta_y = new TH2F( + (cfg.name + "_eta_y").c_str(), + ";#eta;State-Cluster Local Y Residual [cm]", + 50, -1.1, 1.1, m_nBins, cfg.y_lower, cfg.y_upper); + hm->registerHisto(h_new_eta_y); + TH2F* h_new_eta_z = new TH2F( + (cfg.name + "_eta_z").c_str(), + ";#eta;State-Cluster Local Z Residual [cm]", + 50, -1.1, 1.1, m_nBins, cfg.z_lower, cfg.z_upper); + hm->registerHisto(h_new_eta_z); + } + } +} + +int StateClusterResidualsQA::EndRun(const int /*unused*/) +{ + auto *hm = QAHistManagerDef::getHistoManager(); + assert(hm); + + return Fun4AllReturnCodes::EVENT_OK; +} diff --git a/offline/QA/Tracking/StateClusterResidualsQA.h b/offline/QA/Tracking/StateClusterResidualsQA.h new file mode 100644 index 0000000000..587178ef9b --- /dev/null +++ b/offline/QA/Tracking/StateClusterResidualsQA.h @@ -0,0 +1,181 @@ +// Tell emacs that this is a C++ source +// -*- C++ -*-. +#ifndef STATECLUSTERRESIDUALSQA_H +#define STATECLUSTERRESIDUALSQA_H + +#include + +#include +#include +#include +#include +#include + +class PHCompositeNode; +class TH1; +class TH2; + +struct ResidualHistConfig +{ + std::string name = "h_StateClusterResidualsQA_"; + std::string title = ";Residual [cm];Entries"; + + int min_mvtx_clusters = 0; + int max_mvtx_clusters = 3; + int min_intt_clusters = 0; + int max_intt_clusters = 4; + int min_tpc_clusters = 0; + int max_tpc_clusters = 48; + + float phi_min = -M_PI; + float phi_max = M_PI; + float eta_min = -1.1; + float eta_max = 1.1; + + float pt_min = 0.0; + float pt_max = FLT_MAX; + + int charge = 0; + + float rphi_local_lower = -0.5; + float rphi_local_upper = 0.5; + float z_local_lower = -0.5; + float z_local_upper = 0.5; + float x_lower = -0.5; + float x_upper = 0.5; + float y_lower = -0.5; + float y_upper = 0.5; + float z_lower = -0.5; + float z_upper = 0.5; +}; + +class StateClusterResidualsQA : public SubsysReco +{ + public: + StateClusterResidualsQA(const std::string& name = "StateClusterResidualsQA"); + ~StateClusterResidualsQA() override = default; + + /// sets the name of node to retrieve the track map from (default member value is "SvtxTrackMap") + void set_track_map_name(std::string const& track_map_node_name) { m_track_map_node_name = track_map_node_name; } + + StateClusterResidualsQA& addHistogram(const std::string& name) + { + ResidualHistConfig cfg; + cfg.name += name; + m_pending.push_back(cfg); + return *this; + } + StateClusterResidualsQA& setNMvtx(int min, int max) + { + m_pending.back().min_mvtx_clusters = min; + m_pending.back().max_mvtx_clusters = max; + return *this; + } + StateClusterResidualsQA& setNIntt(int min, int max) + { + m_pending.back().min_intt_clusters = min; + m_pending.back().max_intt_clusters = max; + return *this; + } + StateClusterResidualsQA& setNTpc(int min, int max) + { + m_pending.back().min_tpc_clusters = min; + m_pending.back().max_tpc_clusters = max; + return *this; + } + StateClusterResidualsQA& setPhiRange(float min, float max) + { + m_pending.back().phi_min = min; + m_pending.back().phi_max = max; + return *this; + } + StateClusterResidualsQA& setEtaRange(float min, float max) + { + m_pending.back().eta_min = min; + m_pending.back().eta_max = max; + return *this; + } + StateClusterResidualsQA& setPtRange(float min, float max) + { + m_pending.back().pt_min = min; + m_pending.back().pt_max = max; + return *this; + } + StateClusterResidualsQA& setXRange(float min, float max) + { + m_pending.back().x_lower = min; + m_pending.back().x_upper = max; + return *this; + } + StateClusterResidualsQA& setYRange(float min, float max) + { + m_pending.back().y_lower = min; + m_pending.back().y_upper = max; + return *this; + } + StateClusterResidualsQA& setZRange(float min, float max) + { + m_pending.back().z_lower = min; + m_pending.back().z_upper = max; + return *this; + } + StateClusterResidualsQA& setLocalRphiRange(float min, float max) + { + m_pending.back().rphi_local_lower = min; + m_pending.back().rphi_local_upper = max; + return *this; + } + StateClusterResidualsQA& setLocalZRange(float min, float max) + { + m_pending.back().z_local_lower = min; + m_pending.back().z_local_upper = max; + return *this; + } + StateClusterResidualsQA& setPositiveTracks() + { + m_pending.back().charge = 1; + return *this; + } + StateClusterResidualsQA& setNegativeTracks() + { + m_pending.back().charge = -1; + return *this; + } + + void setUseLocalCoords() + { + m_use_local_coords = true; + } + + void createHistos(); + + int InitRun(PHCompositeNode*) override; + + int process_event(PHCompositeNode*) override; + + int EndRun(const int runnumber) override; + + private: + std::vector m_pending; + + std::string m_track_map_node_name = "SvtxTrackMap"; + std::string m_clusterContainerName = "TRKR_CLUSTER"; + + int m_nBins = 50; + bool m_use_local_coords = false; + + std::vector m_histograms_x{}; + std::vector m_histograms_y{}; + std::vector m_histograms_z{}; + std::vector m_histograms_layer_x{}; + std::vector m_histograms_layer_y{}; + std::vector m_histograms_layer_z{}; + std::vector m_histograms_phi_x{}; + std::vector m_histograms_phi_y{}; + std::vector m_histograms_phi_z{}; + std::vector m_histograms_eta_x{}; + std::vector m_histograms_eta_y{}; + std::vector m_histograms_eta_z{}; +}; + +#endif // TRACKFITTINGQA_H diff --git a/offline/database/sphenixnpc/CDBUtils.cc b/offline/database/sphenixnpc/CDBUtils.cc index 080812b419..4608605e7c 100644 --- a/offline/database/sphenixnpc/CDBUtils.cc +++ b/offline/database/sphenixnpc/CDBUtils.cc @@ -12,12 +12,12 @@ #include // for pair, make_pair CDBUtils::CDBUtils() - : cdbclient(new SphenixClient()) + : cdbclient(std::make_unique()) { } CDBUtils::CDBUtils(const std::string &globaltag) - : cdbclient(new SphenixClient(globaltag)) + : cdbclient(std::make_unique(globaltag)) { } @@ -75,23 +75,39 @@ int CDBUtils::createPayloadType(const std::string &pt) return cdbclient->createDomain(pt); } -void CDBUtils::listPayloadIOVs(uint64_t iov) +std::map> CDBUtils::PayloadIOVs(uint64_t iov, const std::string &ptype) { + std::map> iovs; nlohmann::json resp = cdbclient->getPayloadIOVs(iov); if (resp["code"] != 0) { std::cout << resp["msg"] << std::endl; - return; + return iovs; } nlohmann::json payload_iovs = resp["msg"]; - std::map> iovs; for (auto &[pt, val] : payload_iovs.items()) { std::string url = val["payload_url"]; uint64_t bts = val["minor_iov_start"]; uint64_t ets = val["minor_iov_end"]; - iovs.insert(std::make_pair(pt, std::make_tuple(url, bts, ets))); + if (ets > iov) + { + if (!ptype.empty()) + { + if (pt.find(ptype) == std::string::npos) + { + continue; + } + } + iovs.insert(std::make_pair(pt, std::make_tuple(url, bts, ets))); + } } + return iovs; +} + +void CDBUtils::listPayloadIOVs(uint64_t iov, const std::string &ptype) +{ + auto iovs = PayloadIOVs(iov,ptype); for (const auto &it : iovs) { std::cout << it.first << ": " << std::get<0>(it.second) diff --git a/offline/database/sphenixnpc/CDBUtils.h b/offline/database/sphenixnpc/CDBUtils.h index 393036236c..0e6272fab1 100644 --- a/offline/database/sphenixnpc/CDBUtils.h +++ b/offline/database/sphenixnpc/CDBUtils.h @@ -2,6 +2,8 @@ #define SPHENIXNPC_CDBUTILS_H #include // for uint64_t +#include +#include #include #include @@ -27,11 +29,9 @@ class CDBUtils int insertPayload(const std::string &pl_type, const std::string &file_url, uint64_t iov_start); int insertPayload(const std::string &pl_type, const std::string &file_url, uint64_t iov_start, uint64_t iov_end); int cloneGlobalTag(const std::string &source, const std::string &target); - int deleteGlobalTag(const std::string &); void listGlobalTags(); void listPayloadTypes(); - void listPayloadIOVs(uint64_t iov); void clearCache(); bool isGlobalTagSet(); void Verbosity(int i); @@ -39,9 +39,12 @@ class CDBUtils int deletePayloadIOV(const std::string &pl_type, uint64_t iov_start); int deletePayloadIOV(const std::string &pl_type, uint64_t iov_start, uint64_t iov_end); - private: - int m_Verbosity = 0; - SphenixClient *cdbclient = nullptr; + std::map> PayloadIOVs(uint64_t iov, const std::string &ptype = ""); + void listPayloadIOVs(uint64_t iov, const std::string &ptype = ""); + +private: + int m_Verbosity {0}; + std::unique_ptr cdbclient; std::string m_CachedGlobalTag; std::set m_PayloadTypeCache; }; diff --git a/offline/framework/ffamodules/CDBInterface.cc b/offline/framework/ffamodules/CDBInterface.cc index 2b4feef203..2a0b3e1b3c 100644 --- a/offline/framework/ffamodules/CDBInterface.cc +++ b/offline/framework/ffamodules/CDBInterface.cc @@ -185,11 +185,14 @@ std::string CDBInterface::getUrl(const std::string &domain, const std::string &f std::cout << "... reply: " << return_url << std::endl; } } - auto pret = m_UrlVector.insert(make_tuple(domain_noconst, return_url, timestamp)); - if (!pret.second && Verbosity() > 1) + if (! return_url.empty()) { - std::cout << PHWHERE << "not adding again " << domain_noconst << ", url: " << return_url - << ", time stamp: " << timestamp << std::endl; + auto pret = m_UrlVector.insert(make_tuple(domain_noconst, return_url, timestamp)); + if (!pret.second && Verbosity() > 1) + { + std::cout << PHWHERE << "not adding again " << domain_noconst << ", url: " << return_url + << ", time stamp: " << timestamp << std::endl; + } } return return_url; } diff --git a/offline/framework/ffamodules/CDBInterface.h b/offline/framework/ffamodules/CDBInterface.h index c88fae9dee..4132b35a34 100644 --- a/offline/framework/ffamodules/CDBInterface.h +++ b/offline/framework/ffamodules/CDBInterface.h @@ -10,7 +10,6 @@ #include #include // for tuple -class PHCompositeNode; class SphenixClient; class CDBInterface : public SubsysReco diff --git a/offline/framework/ffamodules/FlagHandler.h b/offline/framework/ffamodules/FlagHandler.h index f5cc06bcdb..fd7e40cca3 100644 --- a/offline/framework/ffamodules/FlagHandler.h +++ b/offline/framework/ffamodules/FlagHandler.h @@ -7,14 +7,12 @@ #include -class PHCompositeNode; - class FlagHandler : public SubsysReco { public: FlagHandler(const std::string &name = "FlagHandler"); - ~FlagHandler() override {} + ~FlagHandler() override = default; /** Create the Flag Node if it does not exist, if it exists, read back flags and copy them into recoConsts diff --git a/offline/framework/ffamodules/HeadReco.cc b/offline/framework/ffamodules/HeadReco.cc index 75e879fdff..17214758c8 100644 --- a/offline/framework/ffamodules/HeadReco.cc +++ b/offline/framework/ffamodules/HeadReco.cc @@ -84,10 +84,13 @@ int HeadReco::process_event(PHCompositeNode *topNode) { evtheader->set_ImpactParameter(hi->impact_parameter()); evtheader->set_EventPlaneAngle(hi->event_plane_angle()); - for (unsigned int n = 1; n <= 6; ++n) - { - evtheader->set_FlowPsiN(n, genevt->get_flow_psi(n)); - } + if (! genevt->get_flow_psi_map().empty()) + { + for (unsigned int n = 1; n <= 6; ++n) + { + evtheader->set_FlowPsiN(n, genevt->get_flow_psi(n)); + } + } evtheader->set_eccentricity(hi->eccentricity()); evtheader->set_ncoll(hi->Ncoll()); evtheader->set_npart(hi->Npart_targ() + hi->Npart_proj()); diff --git a/offline/framework/ffamodules/HeadReco.h b/offline/framework/ffamodules/HeadReco.h index ca2f6cf34e..53fbc3c6c3 100644 --- a/offline/framework/ffamodules/HeadReco.h +++ b/offline/framework/ffamodules/HeadReco.h @@ -7,13 +7,11 @@ #include // for string -class PHCompositeNode; - class HeadReco : public SubsysReco { public: HeadReco(const std::string &name = "HeadReco"); - ~HeadReco() override {} + ~HeadReco() override = default; int Init(PHCompositeNode *topNode) override; int InitRun(PHCompositeNode *topNode) override; int process_event(PHCompositeNode *topNode) override; diff --git a/offline/framework/ffamodules/SyncReco.h b/offline/framework/ffamodules/SyncReco.h index 0a490302a0..73d0954593 100644 --- a/offline/framework/ffamodules/SyncReco.h +++ b/offline/framework/ffamodules/SyncReco.h @@ -5,13 +5,11 @@ #include -class PHCompositeNode; - class SyncReco : public SubsysReco { public: SyncReco(const std::string &name = "SYNC"); - ~SyncReco() override {} + ~SyncReco() override = default; int Init(PHCompositeNode *topNode) override; int InitRun(PHCompositeNode *topNode) override; @@ -24,7 +22,7 @@ class SyncReco : public SubsysReco // just if we need to override the segment for e.g. embedding // where we want to reuse hijing files which normally set // the segment number - int forced_segment = -1; + int forced_segment {-1}; }; #endif /* FFAMODULES_SYNCRECO_H */ diff --git a/offline/framework/ffamodules/Timing.cc b/offline/framework/ffamodules/Timing.cc index f662ba1b33..16210e4f73 100644 --- a/offline/framework/ffamodules/Timing.cc +++ b/offline/framework/ffamodules/Timing.cc @@ -3,8 +3,6 @@ #include #include // for SubsysReco -#include - #include Timing::Timing(const std::string &name) diff --git a/offline/framework/ffamodules/Timing.h b/offline/framework/ffamodules/Timing.h index 01b95638e0..a9a5ccd39d 100644 --- a/offline/framework/ffamodules/Timing.h +++ b/offline/framework/ffamodules/Timing.h @@ -8,15 +8,13 @@ #include // for string #include -class PHCompositeNode; - class Timing : public SubsysReco { public: Timing(const std::string &name = "Timing"); - ~Timing() override {} - int InitRun(PHCompositeNode *topNode) override; - int process_event(PHCompositeNode *topNode) override; + ~Timing() override = default; + int InitRun(PHCompositeNode * /*topNode*/) override; + int process_event(PHCompositeNode * /*topNode*/) override; void SetCallCounter(unsigned int i) { calls = i; } private: diff --git a/offline/framework/frog/CreateFileList.pl b/offline/framework/frog/CreateFileList.pl index cc59083d8c..08ea13e981 100755 --- a/offline/framework/frog/CreateFileList.pl +++ b/offline/framework/frog/CreateFileList.pl @@ -41,7 +41,7 @@ my %proddesc = ( # "1" => "hijing (0-12fm) pileup 0-12fm DELETED", # "2" => "hijing (0-4.88fm) pileup 0-12fm DELETED", - "3" => "pythia8 pp MB", +# "3" => "pythia8 pp MB", "4" => "hijing (0-20fm) pileup 0-20fm", # "5" => "hijing (0-12fm) pileup 0-20fm DELETED", "6" => "hijing (0-4.88fm) pileup 0-20fm", @@ -64,7 +64,7 @@ "23" => "cosmic field off", "24" => "AMPT", "25" => "EPOS", - "26" => "JS pythia8 Detroit", + "26" => "JS pythia8 Detroit (MB)", "27" => "JS pythia8 Photonjet ptmin = 5GeV", "28" => "JS pythia8 Photonjet ptmin = 10GeV", "29" => "JS pythia8 Photonjet ptmin = 20GeV", @@ -74,7 +74,15 @@ "33" => "JS pythia8 Jet ptmin = 15GeV", "34" => "JS pythia8 Jet ptmin = 50GeV", "35" => "JS pythia8 Jet ptmin = 70GeV", - "36" => "JS pythia8 Jet ptmin = 5GeV" + "36" => "JS pythia8 Jet ptmin = 5GeV", + "37" => "hijing O+O (0-15fm)", + "38" => "JS pythia8 Jet ptmin = 60GeV", + "39" => "JS pythia8 Jet ptmin = 12GeV", + "40" => "Herwig Jet ptmin = 5 GeV", + "41" => "Herwig Jet ptmin = 12 GeV", + "42" => "Herwig Jet ptmin = 20 GeV", + "43" => "Herwig Jet ptmin = 40 GeV", + "44" => "Herwig Jet ptmin = 50 GeV" ); my %pileupdesc = ( @@ -102,6 +110,7 @@ my $pmax; my $production; my $momentum; +my $double; # that should teach me a lesson to not give a flag an optional string value # just using embed:s leads to the next ARGV to be used as argument, even if it # is the next option. Sadly getopt swallows the - so parsing this becomes @@ -126,7 +135,7 @@ else { push(@newargs, $argument); - if ($ARGV[$iarg+1] ne "pau" && $ARGV[$iarg+1] ne "auau" && $ARGV[$iarg+1] ne "central") + if ($ARGV[$iarg+1] ne "pau" && $ARGV[$iarg+1] ne "auau" && $ARGV[$iarg+1] ne "central" && $ARGV[$iarg+1] ne "oo" ) { push(@newargs,"auau"); } @@ -139,7 +148,7 @@ $iarg++; } @ARGV=@newargs; -GetOptions('embed:s' => \$embed, 'l:i' => \$last_segment, 'momentum:s' => \$momentum, 'n:i' => \$nEvents, "nobkgpileup" => \$nobkgpileup, "nopileup" => \$nopileup, "particle:s" => \$particle, 'pileup:i' => \$pileup, "pmin:i" => \$pmin, "pmax:i"=>\$pmax, "production:s"=>\$production, 'rand' => \$randomize, 'run:i' => \$runnumber, 's:i' => \$start_segment, 'type:i' =>\$prodtype, "verbose" =>\$verbose); +GetOptions('double' => \$double, 'embed:s' => \$embed, 'l:i' => \$last_segment, 'momentum:s' => \$momentum, 'n:i' => \$nEvents, "nobkgpileup" => \$nobkgpileup, "nopileup" => \$nopileup, "particle:s" => \$particle, 'pileup:i' => \$pileup, "pmin:i" => \$pmin, "pmax:i"=>\$pmax, "production:s"=>\$production, 'rand' => \$randomize, 'run:i' => \$runnumber, 's:i' => \$start_segment, 'type:i' =>\$prodtype, "verbose" =>\$verbose); my $filenamestring; my %filetypes = (); my %notlike = (); @@ -147,6 +156,7 @@ my $AuAu_pileupstring; my $pp_pileupstring; my $pAu_pileupstring; +my $OO_pileupstring; my $pileupstring; if (! defined $runnumber && $#newargs >= 0) @@ -167,6 +177,7 @@ } my $pAu_bkgpileup = sprintf("_bkg_0_20fm"); my $AuAu_bkgpileup = sprintf("_bkg_0_10fm"); +my $OO_bkgpileup = sprintf("_bkg_0_15fm"); if ($pileup == 1) { $AuAu_pileupstring = sprintf("_50kHz%s",$AuAu_bkgpileup); @@ -192,15 +203,18 @@ else { $pp_pileupstring = sprintf("_%dkHz",$pileup); - $AuAu_pileupstring = sprintf("_%dkHz%s",$AuAu_bkgpileup); + $AuAu_pileupstring = sprintf("_%dkHz%s",$pileup, $AuAu_bkgpileup); + $OO_pileupstring = sprintf("_%dkHz%s",$pileup,$OO_bkgpileup); } if (defined $nobkgpileup) { $pp_pileupstring = sprintf(""); $AuAu_pileupstring = sprintf(""); + $OO_pileupstring = sprintf(""); } my $embedok = 0; +my $doubleok = 0; if (defined $prodtype) { @@ -314,6 +328,10 @@ { $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } else { $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); @@ -343,6 +361,10 @@ { $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } else { $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); @@ -509,6 +531,10 @@ { $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } else { $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); @@ -552,6 +578,10 @@ { $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } else { $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); @@ -652,6 +682,10 @@ { $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } else { $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); @@ -669,6 +703,11 @@ { $embedok = 1; $filenamestring = "pythia8_PhotonJet10"; + if (defined $double) + { + $doubleok = 1; + $filenamestring = "pythia8_PhotonJet10_pythia8_Detroit"; + } if (! defined $nopileup) { if (defined $embed) @@ -681,6 +720,10 @@ { $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } else { $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); @@ -710,6 +753,10 @@ { $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } else { $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); @@ -826,6 +873,10 @@ { $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } else { $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); @@ -855,6 +906,10 @@ { $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } else { $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); @@ -884,6 +939,10 @@ { $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } else { $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); @@ -902,6 +961,240 @@ $embedok = 1; $filenamestring = "pythia8_Jet5"; if (! defined $nopileup) + { + if (defined $embed) + { + if ($embed eq "pau") + { + $filenamestring = sprintf("%s_sHijing_pAu_0_10fm%s",$filenamestring, $pAu_pileupstring); + } + elsif ($embed eq "central") + { + $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); + } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } + else + { + $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); + } + } + else + { + $filenamestring = sprintf("%s%s",$filenamestring,$pp_pileupstring); + } + } + $pileupstring = $pp_pileupstring; + &commonfiletypes(); + } + elsif ($prodtype == 37) + { + if (defined $nopileup) + { + $filenamestring = sprintf("sHijing_OO_0_15fm"); + } + else + { + $filenamestring = sprintf("sHijing_OO_0_15fm%s",$OO_pileupstring); + } + $notlike{$filenamestring} = ["pythia8" ,"single", "special"]; + $pileupstring = $AuAu_pileupstring; + &commonfiletypes(); + } + elsif ($prodtype == 38) + { + $embedok = 1; + $filenamestring = "pythia8_Jet60"; + if (! defined $nopileup) + { + if (defined $embed) + { + if ($embed eq "pau") + { + $filenamestring = sprintf("%s_sHijing_pAu_0_10fm%s",$filenamestring, $pAu_pileupstring); + } + elsif ($embed eq "central") + { + $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); + } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } + else + { + $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); + } + } + else + { + $filenamestring = sprintf("%s%s",$filenamestring,$pp_pileupstring); + } + } + $pileupstring = $pp_pileupstring; + &commonfiletypes(); + } + elsif ($prodtype == 39) + { + $embedok = 1; + $filenamestring = "pythia8_Jet12"; + if (defined $double) + { + $doubleok = 1; + $filenamestring = "pythia8_Jet12_pythia8_Detroit"; + } + if (! defined $nopileup) + { + if (defined $embed) + { + if ($embed eq "pau") + { + $filenamestring = sprintf("%s_sHijing_pAu_0_10fm%s",$filenamestring, $pAu_pileupstring); + } + elsif ($embed eq "central") + { + $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); + } + elsif ($embed eq "oo") + { + $filenamestring = sprintf("%s_sHijing_OO_0_15fm%s",$filenamestring, $OO_pileupstring); + } + else + { + $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); + } + } + else + { + $filenamestring = sprintf("%s%s",$filenamestring,$pp_pileupstring); + } + } + $pileupstring = $pp_pileupstring; + &commonfiletypes(); + } + elsif ($prodtype == 40) + { + $embedok = 1; + $filenamestring = "Herwig_Jet5"; + if (! defined $nopileup) + { + if (defined $embed) + { + if ($embed eq "pau") + { + $filenamestring = sprintf("%s_sHijing_pAu_0_10fm%s",$filenamestring, $pAu_pileupstring); + } + elsif ($embed eq "central") + { + $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); + } + else + { + $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); + } + } + else + { + $filenamestring = sprintf("%s%s",$filenamestring,$pp_pileupstring); + } + } + $pileupstring = $pp_pileupstring; + &commonfiletypes(); + } + elsif ($prodtype == 41) + { + $embedok = 1; + $filenamestring = "Herwig_Jet12"; + if (! defined $nopileup) + { + if (defined $embed) + { + if ($embed eq "pau") + { + $filenamestring = sprintf("%s_sHijing_pAu_0_10fm%s",$filenamestring, $pAu_pileupstring); + } + elsif ($embed eq "central") + { + $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); + } + else + { + $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); + } + } + else + { + $filenamestring = sprintf("%s%s",$filenamestring,$pp_pileupstring); + } + } + $pileupstring = $pp_pileupstring; + &commonfiletypes(); + } + elsif ($prodtype == 42) + { + $embedok = 1; + $filenamestring = "Herwig_Jet20"; + if (! defined $nopileup) + { + if (defined $embed) + { + if ($embed eq "pau") + { + $filenamestring = sprintf("%s_sHijing_pAu_0_10fm%s",$filenamestring, $pAu_pileupstring); + } + elsif ($embed eq "central") + { + $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); + } + else + { + $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); + } + } + else + { + $filenamestring = sprintf("%s%s",$filenamestring,$pp_pileupstring); + } + } + $pileupstring = $pp_pileupstring; + &commonfiletypes(); + } + elsif ($prodtype == 43) + { + $embedok = 1; + $filenamestring = "Herwig_Jet40"; + if (! defined $nopileup) + { + if (defined $embed) + { + if ($embed eq "pau") + { + $filenamestring = sprintf("%s_sHijing_pAu_0_10fm%s",$filenamestring, $pAu_pileupstring); + } + elsif ($embed eq "central") + { + $filenamestring = sprintf("%s_sHijing_0_488fm%s",$filenamestring, $AuAu_pileupstring); + } + else + { + $filenamestring = sprintf("%s_sHijing_0_20fm%s",$filenamestring, $AuAu_pileupstring); + } + } + else + { + $filenamestring = sprintf("%s%s",$filenamestring,$pp_pileupstring); + } + } + $pileupstring = $pp_pileupstring; + &commonfiletypes(); + } + elsif ($prodtype == 44) + { + $embedok = 1; + $filenamestring = "Herwig_Jet50"; + if (! defined $nopileup) { if (defined $embed) { @@ -926,7 +1219,6 @@ $pileupstring = $pp_pileupstring; &commonfiletypes(); } - else { print "no production type $prodtype\n"; @@ -940,6 +1232,11 @@ print "Embedding not implemented for type $prodtype\n"; exit(1); } +if (defined $double && ! $doubleok) +{ + print "Double interactions not implemented for type $prodtype\n"; + exit(1); +} my $filenamestring_with_runnumber = sprintf("%s\-%010d-",$filenamestring,$runnumber); if ($#ARGV < 0) @@ -948,6 +1245,7 @@ { print "usage: CreateFileLists.pl -type \n"; print "parameters:\n"; + print "-double : double interactions, pp of your type and Detroit pp\n"; print "-embed : pp embedded into MB AuAu hijing (only for pp types)\n"; print " -embed pau : embedded into pAu (only for pp types)\n"; print " -embed central : embedded into central AuAu\n"; diff --git a/offline/framework/fun4all/CreateSubsysRecoModule.pl b/offline/framework/fun4all/CreateSubsysRecoModule.pl index 51f64ea25c..f46c37053d 100755 --- a/offline/framework/fun4all/CreateSubsysRecoModule.pl +++ b/offline/framework/fun4all/CreateSubsysRecoModule.pl @@ -138,6 +138,8 @@ () print F "// void $classname\:\:Print(const std::string &what) const\n"; print F "// Called from the command line - useful to print information when you need it\n"; print F "//\n"; + print F "// [[maybe_unused]] suppresses compiler warnings if topNode is not used in this method\n"; + print F "//\n"; print F "//____________________________________________________________________________..\n"; print F "\n"; @@ -166,7 +168,7 @@ () print F "\n"; print F "//____________________________________________________________________________..\n"; - print F "int $classname\:\:Init(PHCompositeNode *topNode)\n"; + print F "int $classname\:\:Init([[maybe_unused]] PHCompositeNode *topNode)\n"; print F "{\n"; print F " std::cout << \"$classname\:\:Init(PHCompositeNode *topNode) Initializing\" << std::endl;\n"; print F " return Fun4AllReturnCodes::EVENT_OK;\n"; @@ -174,7 +176,7 @@ () print F "\n"; print F "//____________________________________________________________________________..\n"; - print F "int $classname\:\:InitRun(PHCompositeNode *topNode)\n"; + print F "int $classname\:\:InitRun([[maybe_unused]] PHCompositeNode *topNode)\n"; print F "{\n"; print F " std::cout << \"$classname\:\:InitRun(PHCompositeNode *topNode) Initializing for Run XXX\" << std::endl;\n"; print F " return Fun4AllReturnCodes::EVENT_OK;\n"; @@ -182,7 +184,7 @@ () print F "\n"; print F "//____________________________________________________________________________..\n"; - print F "int $classname\:\:process_event(PHCompositeNode *topNode)\n"; + print F "int $classname\:\:process_event([[maybe_unused]] PHCompositeNode *topNode)\n"; print F "{\n"; print F " std::cout << \"$classname\:\:process_event(PHCompositeNode *topNode) Processing Event\" << std::endl;\n"; print F " return Fun4AllReturnCodes::EVENT_OK;\n"; @@ -190,7 +192,7 @@ () print F "\n"; print F "//____________________________________________________________________________..\n"; - print F "int $classname\:\:ResetEvent(PHCompositeNode *topNode)\n"; + print F "int $classname\:\:ResetEvent([[maybe_unused]] PHCompositeNode *topNode)\n"; print F "{\n"; print F " std::cout << \"$classname\:\:ResetEvent(PHCompositeNode *topNode) Resetting internal structures, prepare for next event\" << std::endl;\n"; print F " return Fun4AllReturnCodes::EVENT_OK;\n"; @@ -206,7 +208,7 @@ () print F "\n"; print F "//____________________________________________________________________________..\n"; - print F "int $classname\:\:End(PHCompositeNode *topNode)\n"; + print F "int $classname\:\:End([[maybe_unused]] PHCompositeNode *topNode)\n"; print F "{\n"; print F " std::cout << \"$classname\:\:End(PHCompositeNode *topNode) This is the End...\" << std::endl;\n"; print F " return Fun4AllReturnCodes::EVENT_OK;\n"; @@ -214,7 +216,7 @@ () print F "\n"; print F "//____________________________________________________________________________..\n"; - print F "int $classname\:\:Reset(PHCompositeNode *topNode)\n"; + print F "int $classname\:\:Reset([[maybe_unused]] PHCompositeNode *topNode)\n"; print F "{\n"; print F " std::cout << \"$classname\:\:Reset(PHCompositeNode *topNode) being Reset\" << std::endl;\n"; print F " return Fun4AllReturnCodes::EVENT_OK;\n"; @@ -331,7 +333,7 @@ () print F "dnl no point in suppressing warnings people should \n"; print F "dnl at least see them, so here we go for g++: -Wall\n"; print F "if test \$ac_cv_prog_gxx = yes; then\n"; - print F " CXXFLAGS=\"\$CXXFLAGS -Wall -Werror\"\n"; + print F " CXXFLAGS=\"\$CXXFLAGS -Wall -Wextra -Wshadow -Werror\"\n"; print F "fi\n"; print F "\n"; @@ -348,7 +350,7 @@ () print F "AM_CPPFLAGS = \\\n"; print F " -I\$(includedir) \\\n"; - print F " -I\$(OFFLINE_MAIN)/include \\\n"; + print F " -isystem\$(OFFLINE_MAIN)/include \\\n"; print F " -isystem\$(ROOTSYS)/include\n"; print F "\n"; diff --git a/offline/framework/fun4all/Fun4AllServer.cc b/offline/framework/fun4all/Fun4AllServer.cc index 9d8779204e..9dc68afbb0 100644 --- a/offline/framework/fun4all/Fun4AllServer.cc +++ b/offline/framework/fun4all/Fun4AllServer.cc @@ -128,9 +128,9 @@ void Fun4AllServer::InitAll() { gSystem->IgnoreSignal((ESignals) i); } + m_saved_cout_state.copyfmt(std::cout); // save current state Fun4AllMonitoring::instance()->Snapshot("StartUp"); - std::string histomanagername; - histomanagername = Name() + "HISTOS"; + std::string histomanagername = Name() + "HISTOS"; ServerHistoManager = new Fun4AllHistoManager(histomanagername); registerHistoManager(ServerHistoManager); double uplim = NFRAMEWORKBINS - 0.5; @@ -245,6 +245,7 @@ int Fun4AllServer::registerSubsystem(SubsysReco *subsystem, const std::string &t << subsystem->Name() << std::endl; exit(1); } + std::cout.copyfmt(m_saved_cout_state); // restore cout to default formatting gROOT->cd(currdir.c_str()); if (iret) { @@ -576,6 +577,7 @@ int Fun4AllServer::process_event() ffamemtracker->Snapshot("Fun4AllServerProcessEvent"); #endif int retcode = Subsystem.first->process_event(Subsystem.second); + std::cout.copyfmt(m_saved_cout_state); // restore cout to default formatting #ifdef FFAMEMTRACKER ffamemtracker->Snapshot("Fun4AllServerProcessEvent"); #endif @@ -899,6 +901,7 @@ int Fun4AllServer::BeginRun(const int runno) for (iter = Subsystems.begin(); iter != Subsystems.end(); ++iter) { iret = BeginRunSubsystem(*iter); + std::cout.copyfmt(m_saved_cout_state); // restore cout to default formatting } for (; !NewSubsystems.empty(); NewSubsystems.pop_front()) { @@ -1092,6 +1095,7 @@ int Fun4AllServer::EndRun(const int runno) << (*iter).first->Name() << std::endl; exit(1); } + std::cout.copyfmt(m_saved_cout_state); // restore cout to default formatting } gROOT->cd(currdir.c_str()); @@ -1144,6 +1148,7 @@ int Fun4AllServer::End() << (*iter).first->Name() << std::endl; exit(1); } + std::cout.copyfmt(m_saved_cout_state); // restore cout to default formatting } gROOT->cd(currdir.c_str()); PHNodeIterator nodeiter(TopNode); diff --git a/offline/framework/fun4all/Fun4AllServer.h b/offline/framework/fun4all/Fun4AllServer.h index 0c7ea72c14..9f360b9502 100644 --- a/offline/framework/fun4all/Fun4AllServer.h +++ b/offline/framework/fun4all/Fun4AllServer.h @@ -143,7 +143,8 @@ class Fun4AllServer : public Fun4AllBase int eventnumber{0}; int eventcounter{0}; int keep_db_connected{0}; - + + std::ios m_saved_cout_state{nullptr}; std::vector ComplaintList; std::vector ResetNodeList {"DST"}; std::vector> Subsystems; diff --git a/offline/framework/fun4all/InputFileHandler.cc b/offline/framework/fun4all/InputFileHandler.cc index 8939b67568..0fdc858db8 100644 --- a/offline/framework/fun4all/InputFileHandler.cc +++ b/offline/framework/fun4all/InputFileHandler.cc @@ -3,10 +3,13 @@ #include +#include + #include #include #include #include +#include int InputFileHandler::AddFile(const std::string &filename) { @@ -89,6 +92,19 @@ int InputFileHandler::OpenNextFile() { std::cout << PHWHERE << " opening next file: " << *iter << std::endl; } + if (!GetOpeningScript().empty()) + { + std::vector stringvec; + stringvec.push_back(*iter); + if (!m_FileName.empty()) + { + stringvec.push_back(m_FileName); + } + if (RunBeforeOpening(stringvec)) + { + std::cout << PHWHERE << " RunBeforeOpening() failed" << std::endl; + } + } if (fileopen(*iter)) { std::cout << PHWHERE << " could not open file: " << *iter << std::endl; @@ -145,3 +161,40 @@ int InputFileHandler::fileopen(const std::string &fname) std::cout << "InputFileHandler::fileopen opening " << fname << std::endl; return 0; } + +int InputFileHandler::RunBeforeOpening(const std::vector &stringvec) +{ + if (m_RunBeforeOpeningScript.empty()) + { + return 0; + } + if (!std::filesystem::exists(m_RunBeforeOpeningScript)) + { + std::cout << PHWHERE << " script " << m_RunBeforeOpeningScript << " not found" + << std::endl; + return -1; + } + if (!((std::filesystem::status(m_RunBeforeOpeningScript).permissions() & std::filesystem::perms::owner_exec) == std::filesystem::perms::owner_exec)) + { + std::cout << PHWHERE << "RunBeforeOpeningScript script " + << m_RunBeforeOpeningScript << " is not owner executable" << std::endl; + return -1; + } + std::string fullcmd = m_RunBeforeOpeningScript + " " + m_OpeningArgs; + for (const auto& iter : stringvec) + { + fullcmd += " " + iter; + } + + if (m_Verbosity > 1) + { + std::cout << PHWHERE << " running " << fullcmd << std::endl; + } + unsigned int iret = gSystem->Exec(fullcmd.c_str()); + + if (iret) + { + iret = iret >> 8U; + } + return static_cast (iret); +} diff --git a/offline/framework/fun4all/InputFileHandler.h b/offline/framework/fun4all/InputFileHandler.h index 823ae33b38..49df4aa379 100644 --- a/offline/framework/fun4all/InputFileHandler.h +++ b/offline/framework/fun4all/InputFileHandler.h @@ -4,13 +4,14 @@ #include #include #include +#include class InputFileHandler { public: InputFileHandler() = default; virtual ~InputFileHandler() = default; - virtual int fileopen(const std::string & /*filename*/);// { return 0; } + virtual int fileopen(const std::string & /*filename*/); // { return 0; } virtual int fileclose() { return -1; } virtual int ResetFileList(); @@ -32,12 +33,19 @@ class InputFileHandler std::pair::const_iterator, std::list::const_iterator> FileOpenListBeginEnd() { return std::make_pair(m_FileListOpened.begin(), m_FileListOpened.end()); } const std::list &GetFileList() const { return m_FileListCopy; } const std::list &GetFileOpenedList() const { return m_FileListOpened; } + void SetOpeningScript(const std::string &script) { m_RunBeforeOpeningScript = script; } + const std::string &GetOpeningScript() const { return m_RunBeforeOpeningScript; } + void SetOpeningScriptArgs(const std::string &args) { m_OpeningArgs = args; } + const std::string &GetOpeningScriptArgs() const { return m_OpeningArgs; } + int RunBeforeOpening(const std::vector &stringvec); private: int m_IsOpen{0}; int m_Repeat{0}; uint64_t m_Verbosity{0}; std::string m_FileName; + std::string m_RunBeforeOpeningScript; + std::string m_OpeningArgs; std::list m_FileList; std::list m_FileListCopy; std::list m_FileListOpened; // all files which were opened during running diff --git a/offline/framework/fun4allraw/Fun4AllStreamingInputManager.cc b/offline/framework/fun4allraw/Fun4AllStreamingInputManager.cc index 78b3e3a365..0bea81197b 100644 --- a/offline/framework/fun4allraw/Fun4AllStreamingInputManager.cc +++ b/offline/framework/fun4allraw/Fun4AllStreamingInputManager.cc @@ -776,9 +776,15 @@ int Fun4AllStreamingInputManager::FillIntt() { h_taggedAllFee_intt->Fill(refbcobitshift); } - while (m_InttRawHitMap.begin()->first <= select_crossings - m_intt_negative_bco) + + for (auto& [bco, hitinfo] : m_InttRawHitMap) { - for (auto *intthititer : m_InttRawHitMap.begin()->second.InttRawHitVector) + if (bco > select_crossings) + { + break; + } + + for (auto *intthititer : hitinfo.InttRawHitVector) { if (Verbosity() > 1) { @@ -788,25 +794,9 @@ int Fun4AllStreamingInputManager::FillIntt() } inttcont->AddHit(intthititer); } - for (auto *iter : m_InttInputVector) - { - iter->CleanupUsedPackets(m_InttRawHitMap.begin()->first); - if (m_intt_negative_bco < 2) // triggered mode - { - iter->clearPacketBClkStackMap(m_InttRawHitMap.begin()->first); - iter->clearFeeGTML1BCOMap(m_InttRawHitMap.begin()->first); - } - } - m_InttRawHitMap.begin()->second.InttRawHitVector.clear(); - m_InttRawHitMap.erase(m_InttRawHitMap.begin()); - if (m_InttRawHitMap.empty()) - { - break; - } - } + } return 0; } - int Fun4AllStreamingInputManager::FillMvtx() { int iret = FillMvtxPool(); @@ -846,7 +836,7 @@ int Fun4AllStreamingInputManager::FillMvtx() } select_crossings += m_RefBCO; - uint64_t ref_bco_minus_range = m_RefBCO < m_mvtx_bco_range ? 0 : m_RefBCO - m_mvtx_bco_range; + uint64_t ref_bco_minus_range = m_RefBCO < m_mvtx_negative_bco ? 0 : m_RefBCO - m_mvtx_negative_bco; if (Verbosity() > 2) { std::cout << "select MVTX crossings" @@ -981,90 +971,42 @@ int Fun4AllStreamingInputManager::FillMvtx() } taggedPacketsFEEs.clear(); - if (m_mvtx_is_triggered) + uint64_t lower_limit = m_mvtx_is_triggered ? select_crossings : select_crossings - m_mvtx_bco_range - m_mvtx_negative_bco; + uint64_t upper_limit = m_mvtx_is_triggered ? select_crossings + m_mvtx_bco_range : select_crossings; + + for (auto& [bco, hitinfo] : m_MvtxRawHitMap) { - while (select_crossings <= m_MvtxRawHitMap.begin()->first && m_MvtxRawHitMap.begin()->first <= select_crossings + m_mvtx_bco_range) // triggered + if (bco < lower_limit) { - if (Verbosity() > 2) - { - std::cout << "Adding 0x" << std::hex << m_MvtxRawHitMap.begin()->first - << " ref: 0x" << select_crossings << std::dec << std::endl; - } - for (auto *mvtxFeeIdInfo : m_MvtxRawHitMap.begin()->second.MvtxFeeIdInfoVector) - { - if (Verbosity() > 1) - { - mvtxFeeIdInfo->identify(); - } - mvtxEvtHeader->AddFeeIdInfo(mvtxFeeIdInfo); - delete mvtxFeeIdInfo; - } - m_MvtxRawHitMap.begin()->second.MvtxFeeIdInfoVector.clear(); - mvtxEvtHeader->AddL1Trg(m_MvtxRawHitMap.begin()->second.MvtxL1TrgBco); + continue; + } + if (bco > upper_limit) + { + break; + } - for (auto *mvtxhititer : m_MvtxRawHitMap.begin()->second.MvtxRawHitVector) - { - if (Verbosity() > 1) - { - mvtxhititer->identify(); - } - mvtxcont->AddHit(mvtxhititer); - } - for (auto *iter : m_MvtxInputVector) - { - iter->CleanupUsedPackets(m_MvtxRawHitMap.begin()->first); - } - m_MvtxRawHitMap.begin()->second.MvtxRawHitVector.clear(); - m_MvtxRawHitMap.begin()->second.MvtxL1TrgBco.clear(); - m_MvtxRawHitMap.erase(m_MvtxRawHitMap.begin()); - // m_MvtxRawHitMap.empty() need to be checked here since we do not call FillPoolMvtx() - if (m_MvtxRawHitMap.empty()) - { - break; - } + if (Verbosity() > 2) + { + std::cout << "Adding 0x" << std::hex << bco + << " ref: 0x" << select_crossings << std::dec << std::endl; } - } - else - { - while (select_crossings - m_mvtx_bco_range - m_mvtx_negative_bco <= m_MvtxRawHitMap.begin()->first && m_MvtxRawHitMap.begin()->first <= select_crossings) // streamed + for (auto *mvtxFeeIdInfo : hitinfo.MvtxFeeIdInfoVector) { - if (Verbosity() > 2) - { - std::cout << "Adding 0x" << std::hex << m_MvtxRawHitMap.begin()->first - << " ref: 0x" << select_crossings << std::dec << std::endl; - } - for (auto *mvtxFeeIdInfo : m_MvtxRawHitMap.begin()->second.MvtxFeeIdInfoVector) + if (Verbosity() > 1) { - if (Verbosity() > 1) - { - mvtxFeeIdInfo->identify(); - } - mvtxEvtHeader->AddFeeIdInfo(mvtxFeeIdInfo); - delete mvtxFeeIdInfo; + mvtxFeeIdInfo->identify(); } - m_MvtxRawHitMap.begin()->second.MvtxFeeIdInfoVector.clear(); - mvtxEvtHeader->AddL1Trg(m_MvtxRawHitMap.begin()->second.MvtxL1TrgBco); + mvtxEvtHeader->AddFeeIdInfo(mvtxFeeIdInfo); + } + mvtxEvtHeader->AddL1Trg(hitinfo.MvtxL1TrgBco); - for (auto *mvtxhititer : m_MvtxRawHitMap.begin()->second.MvtxRawHitVector) - { - if (Verbosity() > 1) - { - mvtxhititer->identify(); - } - mvtxcont->AddHit(mvtxhititer); - } - for (auto *iter : m_MvtxInputVector) - { - iter->CleanupUsedPackets(m_MvtxRawHitMap.begin()->first); - } - m_MvtxRawHitMap.begin()->second.MvtxRawHitVector.clear(); - m_MvtxRawHitMap.begin()->second.MvtxL1TrgBco.clear(); - m_MvtxRawHitMap.erase(m_MvtxRawHitMap.begin()); - // m_MvtxRawHitMap.empty() need to be checked here since we do not call FillPoolMvtx() - if (m_MvtxRawHitMap.empty()) + for (auto *mvtxhititer : hitinfo.MvtxRawHitVector) + { + if (Verbosity() > 1) { - break; + mvtxhititer->identify(); } + mvtxcont->AddHit(mvtxhititer); } } @@ -1422,7 +1364,7 @@ int Fun4AllStreamingInputManager::FillMicromegasPool() int Fun4AllStreamingInputManager::FillMvtxPool() { - uint64_t ref_bco_minus_range = m_RefBCO < m_mvtx_bco_range ? m_mvtx_bco_range : m_RefBCO - m_mvtx_bco_range; + uint64_t ref_bco_minus_range = m_RefBCO < m_mvtx_negative_bco ? m_mvtx_negative_bco : m_RefBCO - m_mvtx_negative_bco; for (auto *iter : m_MvtxInputVector) { if (Verbosity() > 3) diff --git a/offline/framework/fun4allraw/Makefile.am b/offline/framework/fun4allraw/Makefile.am index ef0c1b54a2..7f852ce989 100644 --- a/offline/framework/fun4allraw/Makefile.am +++ b/offline/framework/fun4allraw/Makefile.am @@ -100,7 +100,9 @@ libfun4allraw_la_LIBADD = \ -lfun4all \ -lEvent \ -lphoolraw \ - -lqautils + -lqautils \ + -lffamodules \ + -lcdbobjects BUILT_SOURCES = testexternals.cc diff --git a/offline/framework/fun4allraw/SingleMicromegasPoolInput_v2.cc b/offline/framework/fun4allraw/SingleMicromegasPoolInput_v2.cc index 7500e3badf..89c0caa9f3 100644 --- a/offline/framework/fun4allraw/SingleMicromegasPoolInput_v2.cc +++ b/offline/framework/fun4allraw/SingleMicromegasPoolInput_v2.cc @@ -607,6 +607,7 @@ void SingleMicromegasPoolInput_v2::createQAHistos() m_evaluation_file.reset(new TFile(m_evaluation_filename.c_str(), "RECREATE")); m_evaluation_tree = new TTree("T", "T"); m_evaluation_tree->Branch("is_heartbeat", &m_waveform.is_heartbeat); + m_evaluation_tree->Branch("matched", &m_waveform.matched); m_evaluation_tree->Branch("packet_id", &m_waveform.packet_id); m_evaluation_tree->Branch("fee_id", &m_waveform.fee_id); m_evaluation_tree->Branch("channel", &m_waveform.channel); @@ -912,6 +913,13 @@ void SingleMicromegasPoolInput_v2::process_fee_data(int packet_id, unsigned int // try get gtm bco matching fee const auto& fee_bco = payload.bx_timestamp; + if( m_do_evaluation ) + { + m_waveform.is_heartbeat = is_heartbeat; + m_waveform.fee_id = fee_id; + m_waveform.channel = payload.channel; + m_waveform.fee_bco = fee_bco; + } // find matching gtm bco uint64_t gtm_bco = 0; @@ -920,9 +928,20 @@ void SingleMicromegasPoolInput_v2::process_fee_data(int packet_id, unsigned int { // assign gtm bco gtm_bco = result.value(); - } - else - { + if( m_do_evaluation ) + { + m_waveform.matched = true; + m_waveform.gtm_bco_matched = gtm_bco; + { + const auto predicted = bco_matching_information.get_predicted_fee_bco(gtm_bco);; + if( predicted ) + { + m_waveform.fee_bco_predicted_matched = predicted.value(); + } + } + m_evaluation_tree->Fill(); + } + } else { // increment counter and histogram ++m_waveform_counters[packet_id].dropped_bco; ++m_fee_waveform_counters[fee_id].dropped_bco; @@ -935,28 +954,16 @@ void SingleMicromegasPoolInput_v2::process_fee_data(int packet_id, unsigned int ++m_fee_heartbeat_counters[fee_id].dropped_bco; } - // skip the waverform - continue; - } - - if (m_do_evaluation) - { - m_waveform.is_heartbeat = (payload.type == HEARTBEAT_T); - m_waveform.fee_id = fee_id; - m_waveform.channel = payload.channel; - m_waveform.fee_bco = fee_bco; - - m_waveform.gtm_bco_matched = gtm_bco; + if( m_do_evaluation ) { - const auto predicted = bco_matching_information.get_predicted_fee_bco(gtm_bco); - ; - if (predicted) - { - m_waveform.fee_bco_predicted_matched = predicted.value(); - } + m_waveform.matched = false; + m_waveform.gtm_bco_matched = 0; + m_waveform.fee_bco_predicted_matched = 0; + m_evaluation_tree->Fill(); } - m_evaluation_tree->Fill(); + // skip the waverform + continue; } // ignore heartbeat waveforms diff --git a/offline/framework/fun4allraw/SingleMicromegasPoolInput_v2.h b/offline/framework/fun4allraw/SingleMicromegasPoolInput_v2.h index d8c3c1da62..3746b9eb41 100644 --- a/offline/framework/fun4allraw/SingleMicromegasPoolInput_v2.h +++ b/offline/framework/fun4allraw/SingleMicromegasPoolInput_v2.h @@ -230,6 +230,9 @@ class SingleMicromegasPoolInput_v2 : public SingleStreamingInput /// true if measurement is hearbeat bool is_heartbeat = false; + /// true if matched + bool matched = false; + /// ll1 bco uint64_t gtm_bco_first {0}; diff --git a/offline/framework/fun4allraw/SingleMvtxPoolInput.cc b/offline/framework/fun4allraw/SingleMvtxPoolInput.cc index de98a9936e..4ce498ee9e 100644 --- a/offline/framework/fun4allraw/SingleMvtxPoolInput.cc +++ b/offline/framework/fun4allraw/SingleMvtxPoolInput.cc @@ -1,7 +1,7 @@ #include "SingleMvtxPoolInput.h" -#include "MvtxRawDefs.h" #include "Fun4AllStreamingInputManager.h" +#include "MvtxRawDefs.h" #include "mvtx_pool.h" #include @@ -29,7 +29,8 @@ #include SingleMvtxPoolInput::SingleMvtxPoolInput(const std::string &name) - : SingleStreamingInput(name), plist(new Packet *[2]) + : SingleStreamingInput(name) + , plist(new Packet *[2]) { m_rawHitContainerName = "MVTXRAWHIT"; @@ -161,7 +162,7 @@ void SingleMvtxPoolInput::FillPool(const uint64_t minBCO) m_BclkStack.insert(strb_bco); m_FEEBclkMap[feeId] = strb_bco; - if (strb_bco < minBCO - m_NegativeBco) + if (strb_bco < minBCO) { continue; } @@ -206,7 +207,7 @@ void SingleMvtxPoolInput::FillPool(const uint64_t minBCO) auto it = m_BclkStack.lower_bound(lv1Bco); // auto const strb_it = (it == m_BclkStack.begin()) ? (*it == lv1Bco ? it : m_BclkStack.cend()) : --it; // this is equivalent but human readable for the above: - auto strb_it = m_BclkStack.cend(); + auto strb_it = m_BclkStack.cend(); if (it == m_BclkStack.begin()) { @@ -462,7 +463,7 @@ void SingleMvtxPoolInput::ConfigureStreamingInputManager() else if (m_strobeWidth > 9 && m_strobeWidth < 11) { m_BcoRange = 500; - m_NegativeBco = 500; + m_NegativeBco = 120; } else if (m_strobeWidth < 1) // triggered mode { diff --git a/offline/framework/fun4allraw/SingleTpcTimeFrameInput.cc b/offline/framework/fun4allraw/SingleTpcTimeFrameInput.cc index 03e83f4cd0..dd9559b075 100644 --- a/offline/framework/fun4allraw/SingleTpcTimeFrameInput.cc +++ b/offline/framework/fun4allraw/SingleTpcTimeFrameInput.cc @@ -293,6 +293,7 @@ void SingleTpcTimeFrameInput::FillPool(const uint64_t targetBCO) m_TpcTimeFrameBuilderMap[packet_id] = new TpcTimeFrameBuilder(packet_id); m_TpcTimeFrameBuilderMap[packet_id]->setVerbosity(Verbosity()); + m_TpcTimeFrameBuilderMap[packet_id]->fillBadFeeMap(); if (!m_digitalCurrentDebugTTreeName.empty()) { m_TpcTimeFrameBuilderMap[packet_id]->SaveDigitalCurrentDebugTTree(m_digitalCurrentDebugTTreeName); diff --git a/offline/framework/fun4allraw/SingleTpcTimeFrameInput.h b/offline/framework/fun4allraw/SingleTpcTimeFrameInput.h index e1f9ded3dd..e9e10cae59 100644 --- a/offline/framework/fun4allraw/SingleTpcTimeFrameInput.h +++ b/offline/framework/fun4allraw/SingleTpcTimeFrameInput.h @@ -53,7 +53,7 @@ class SingleTpcTimeFrameInput : public SingleStreamingInput //! packet ID -> TimeFrame builder std::map m_TpcTimeFrameBuilderMap; std::set m_SelectedPacketIDs; - + TH1 *m_hNorm = nullptr; PHTimer *m_FillPoolTimer = nullptr; @@ -63,14 +63,14 @@ class SingleTpcTimeFrameInput : public SingleStreamingInput // NOLINTNEXTLINE(hicpp-special-member-functions) class TimeTracker - { + { public: - TimeTracker(PHTimer * timer, const std::string & name, TH1* hout) ; - virtual ~TimeTracker() ; + TimeTracker(PHTimer *timer, const std::string &name, TH1 *hout); + virtual ~TimeTracker(); void stop(); private: - PHTimer * m_timer = nullptr; + PHTimer *m_timer = nullptr; std::string m_name; TH1 *m_hNorm = nullptr; bool stopped = false; diff --git a/offline/framework/fun4allraw/SingleTriggeredInput.cc b/offline/framework/fun4allraw/SingleTriggeredInput.cc index 3bb6b30a2b..f2d3b34ef1 100644 --- a/offline/framework/fun4allraw/SingleTriggeredInput.cc +++ b/offline/framework/fun4allraw/SingleTriggeredInput.cc @@ -26,7 +26,7 @@ #include // for pair #include -SingleTriggeredInput::SingleTriggeredInput(const std::string &name) +SingleTriggeredInput::SingleTriggeredInput(const std::string& name) : Fun4AllBase(name) { m_bclkarray.fill(std::numeric_limits::max()); @@ -35,7 +35,7 @@ SingleTriggeredInput::SingleTriggeredInput(const std::string &name) SingleTriggeredInput::~SingleTriggeredInput() { - std::set evtset; + std::set evtset; for (auto& [pid, dq] : m_PacketEventDeque) { while (!dq.empty()) @@ -44,7 +44,7 @@ SingleTriggeredInput::~SingleTriggeredInput() dq.pop_front(); } } - for (auto *evt : evtset) + for (auto* evt : evtset) { delete evt; } @@ -64,7 +64,7 @@ bool SingleTriggeredInput::CheckFemDiffIdx(int pid, size_t index, const std::deq return false; } - Packet* pkt_prev = events[index-1]->getPacket(pid); + Packet* pkt_prev = events[index - 1]->getPacket(pid); Packet* pkt_curr = events[index]->getPacket(pid); if (!pkt_prev || !pkt_curr) { @@ -73,7 +73,8 @@ bool SingleTriggeredInput::CheckFemDiffIdx(int pid, size_t index, const std::deq return false; } - auto get_majority_femclk = [](Packet* pkt) -> uint16_t { + auto get_majority_femclk = [](Packet* pkt) -> uint16_t + { int nmod = pkt->iValue(0, "NRMODULES"); std::map counts; for (int j = 0; j < nmod; ++j) @@ -85,7 +86,9 @@ bool SingleTriggeredInput::CheckFemDiffIdx(int pid, size_t index, const std::deq { return std::numeric_limits::max(); } - return std::max_element(counts.begin(), counts.end(), [](const auto& a, const auto& b) { return a.second < b.second; })->first; + return std::max_element(counts.begin(), counts.end(), [](const auto& a, const auto& b) + { return a.second < b.second; }) + ->first; }; uint16_t clk_prev = get_majority_femclk(pkt_prev); @@ -108,38 +111,38 @@ bool SingleTriggeredInput::CheckPoolAlignment(int pid, const std::array bad_diff_indices; for (size_t i = 0; i < n; ++i) { - if ( sebdiff[i] != gl1diff[i] ) + if (sebdiff[i] != gl1diff[i]) { - if ( !m_packetclk_copy_runs ) + if (!m_packetclk_copy_runs) { - //backup procedure to recover stuck 16bit XMIT clock - size_t idxcheck = i == 0 ? i+1 : i; + // backup procedure to recover stuck 16bit XMIT clock + size_t idxcheck = i == 0 ? i + 1 : i; bool passFemDiffCheckIdx = CheckFemDiffIdx(pid, idxcheck, m_PacketEventDeque[pid], gl1diff[idxcheck]); - if ( passFemDiffCheckIdx ) + if (passFemDiffCheckIdx) { m_OverrideWithRepClock.insert(pid); continue; } - } + } bad_diff_indices.push_back(i); } } if (bad_diff_indices.empty()) { - if ( Verbosity() > 0 ) + if (Verbosity() > 0) { std::cout << Name() << " recovered from bad XMIT clocks. Merging pool" << std::endl; } @@ -147,14 +150,14 @@ bool SingleTriggeredInput::CheckPoolAlignment(int pid, const std::array=5) + if (bad_diff_indices.size() >= 5) { std::cout << std::endl; std::cout << "----------------- " << Name() << " -----------------" << std::endl; std::cout << "More than 5 diffs are bad.. try shifting algorithm" << std::endl; move_to_shift_algo = true; } - if(!move_to_shift_algo) + if (!move_to_shift_algo) { std::cout << std::endl; std::cout << "----------------- " << Name() << " -----------------" << std::endl; @@ -164,23 +167,23 @@ bool SingleTriggeredInput::CheckPoolAlignment(int pid, const std::array=5) + if (length >= 5) { std::cout << Name() << ": length of bad diffs >=5 with bad_diff_indices.size() " << bad_diff_indices.size() << ". This should not have happened.. rejecting pool" << std::endl; return false; } - if(start==static_cast(pooldepth - 1)) + if (start == static_cast(pooldepth - 1)) { bad_indices.push_back(start); - CurrentPoolLastDiffBad= true; + CurrentPoolLastDiffBad = true; } - else if (start==0) + else if (start == 0) { if (PrevPoolLastDiffBad) { @@ -202,14 +205,14 @@ bool SingleTriggeredInput::CheckPoolAlignment(int pid, const std::array(pooldepth - 1) && start >0) + else if (start < static_cast(pooldepth - 1) && start > 0) { - if(length==1) + if (length == 1) { std::cout << Name() << ": Isolated bad diff[" << start << "] - rejecting pool" << std::endl; return false; } - if(length>=2) + if (length >= 2) { for (int j = start; j < end; ++j) { @@ -219,7 +222,7 @@ bool SingleTriggeredInput::CheckPoolAlignment(int pid, const std::array::max()); - if ( representative_pid == -1 ) + static bool firstclockarray = true; + if (firstclockarray) + { + std::cout << "first clock call pid " << pid << " m_bclkarray_map[pid][0] : " << m_bclkarray_map[pid][0] << std::endl; + firstclockarray = false; + } + + if (representative_pid == -1) { representative_pid = pid; } } - if ( !allPacketEventDequeEmpty ) + if (!allPacketEventDequeEmpty) { return 0; } @@ -368,13 +378,18 @@ int SingleTriggeredInput::FillEventVector() while (i < pooldepth) { Event* evt{nullptr}; + bool skiptrace = false; if (this != Gl1Input()) { auto* gl1 = dynamic_cast(Gl1Input()); if (gl1) { int nskip = gl1->GetGl1SkipArray()[i]; - + if (nskip > 0) + { + skiptrace = true; + } + while (nskip > 0) { Event* skip_evt = GetEventIterator()->getNextEvent(); @@ -388,9 +403,10 @@ int SingleTriggeredInput::FillEventVector() } skip_evt = GetEventIterator()->getNextEvent(); } - + if (skip_evt->getEvtType() != DATAEVENT) { + delete skip_evt; continue; } @@ -412,14 +428,91 @@ int SingleTriggeredInput::FillEventVector() { if (Verbosity() > 0) { - std::cout << Name() << ": Early stop of SEB skip after " << (gl1->GetGl1SkipArray()[i] - nskip) << " from intial " << gl1->GetGl1SkipArray()[i] << " events." << std::endl; + std::cout << Name() << ": Early stop in pool " << i << " of SEB skip after " << (gl1->GetGl1SkipArray()[i] - nskip) << " from intial " << gl1->GetGl1SkipArray()[i] << " events. gl1diff vs sebdiff : " << gl1_diff << " vs " << seb_diff << std::endl; } evt = skip_evt; + skiptrace = false; break; } delete skip_evt; nskip--; } + + if (skiptrace) + { + evt = GetEventIterator()->getNextEvent(); + while (!evt) + { + fileclose(); + if (OpenNextFile() == InputFileHandlerReturnCodes::FAILURE) + { + FilesDone(1); + return -1; + } + evt = GetEventIterator()->getNextEvent(); + } + if (evt->getEvtType() != DATAEVENT) + { + if (Verbosity() > 0) + { + std::cout << Name() << " dropping non data event: " << evt->getEvtSequence() << std::endl; + } + delete evt; + continue; + } + + Packet* pkt = evt->getPacket(representative_pid); + if (!pkt) + { + std::cout << "representative packet invalid inside skiptrace.. continuing.." << std::endl; + continue; + } + FillPacketClock(evt, pkt, i); + uint64_t seb_diff = m_bclkdiffarray_map[representative_pid][i]; + int gl1pid = Gl1Input()->m_bclkdiffarray_map.begin()->first; + uint64_t gl1_diff = gl1->m_bclkdiffarray_map[gl1pid][i]; + + bool clockconsistency = true; + if (seb_diff != gl1_diff) + { + clockconsistency = false; + int clockconstcount = 0; + while (!clockconsistency && clockconstcount < 5) + { + std::cout << Name() << ": Still inconsistent clock diff after Gl1 drop. gl1diff vs sebdiff : " << gl1_diff << " vs " << seb_diff << std::endl; + delete pkt; + delete evt; + evt = GetEventIterator()->getNextEvent(); + while (!evt) + { + fileclose(); + if (OpenNextFile() == InputFileHandlerReturnCodes::FAILURE) + { + FilesDone(1); + return -1; + } + evt = GetEventIterator()->getNextEvent(); + } + pkt = evt->getPacket(representative_pid); + if (!pkt) + { + std::cout << "representative packet invalid inside skiptrace.. continuing.." << std::endl; + continue; + } + + FillPacketClock(evt, pkt, i); + uint64_t seb_diff_next = m_bclkdiffarray_map[representative_pid][i]; + uint64_t gl1_diff_next = gl1->m_bclkdiffarray_map[gl1pid][i]; + std::cout << "seb_diff_next : " << seb_diff_next << " , gl1_diff_next : " << gl1_diff_next << std::endl; + if (seb_diff_next == gl1_diff_next) + { + clockconsistency = true; + std::cout << Name() << " : recovered by additional skip in skiptrace" << std::endl; + } + clockconstcount++; + } + } + } } } @@ -447,22 +540,22 @@ int SingleTriggeredInput::FillEventVector() continue; } evt->convert(); - + if (firstcall) { std::cout << "Creating DSTs first call" << std::endl; CreateDSTNodes(evt); int run = evt->getRunNumber(); - m_packetclk_copy_runs = (run >= 44000 && run < 56079); + m_packetclk_copy_runs = (run >= 44000 && run < 56079); firstcall = false; } for (int pid : m_PacketSet) { - Event *thisevt = evt; + Event* thisevt = evt; if (m_PacketShiftOffset[pid] == 1) { - if (i==0) + if (i == 0) { thisevt = m_PacketEventBackup[pid]; m_ShiftedEvents[pid] = evt; @@ -471,13 +564,13 @@ int SingleTriggeredInput::FillEventVector() { thisevt = m_ShiftedEvents[pid]; m_ShiftedEvents[pid] = evt; - if (i == pooldepth -1) + if (i == pooldepth - 1) { m_PacketEventBackup[pid] = evt; } } } - + Packet* pkt = thisevt->getPacket(pid); if (!pkt) { @@ -485,14 +578,16 @@ int SingleTriggeredInput::FillEventVector() } FillPacketClock(thisevt, pkt, i); m_PacketEventDeque[pid].push_back(thisevt); + delete pkt; - + if (representative_pid == -1 && m_PacketShiftOffset[pid] == 0) { representative_pid = pid; } } i++; + eventcounter++; } size_t minSize = pooldepth; @@ -503,7 +598,7 @@ int SingleTriggeredInput::FillEventVector() return minSize; } -uint64_t SingleTriggeredInput::GetClock(Event *evt, int pid) +uint64_t SingleTriggeredInput::GetClock(Event* evt, int pid) { Packet* packet = evt->getPacket(pid); if (!packet) @@ -534,20 +629,19 @@ void SingleTriggeredInput::FillPacketClock(Event* evt, Packet* pkt, size_t event auto& clkarray = m_bclkarray_map[pid]; auto& diffarray = m_bclkdiffarray_map[pid]; - // Special handling for FEM-copied clocks if (m_packetclk_copy_runs && m_CorrectCopiedClockPackets.contains(pid)) { if (event_index == 0) { - clkarray[event_index+1] = m_PreviousValidBCOMap[pid]; + clkarray[event_index + 1] = m_PreviousValidBCOMap[pid]; } - else if (event_index >=1) + else if (event_index >= 1) { Event* shifted_evt = m_PacketEventDeque[pid][event_index - 1]; - clkarray[event_index+1] = GetClock(shifted_evt, pid); + clkarray[event_index + 1] = GetClock(shifted_evt, pid); } - + uint64_t prev = clkarray[event_index]; uint64_t curr = clkarray[event_index + 1]; @@ -563,7 +657,6 @@ void SingleTriggeredInput::FillPacketClock(Event* evt, Packet* pkt, size_t event return; } - uint64_t clk = GetClock(evt, pid); if (clk == std::numeric_limits::max()) { @@ -574,7 +667,7 @@ void SingleTriggeredInput::FillPacketClock(Event* evt, Packet* pkt, size_t event clkarray[event_index + 1] = clk; uint64_t prev = clkarray[event_index]; - if(prev == std::numeric_limits::max()) + if (prev == std::numeric_limits::max()) { static std::unordered_set warned; @@ -598,7 +691,7 @@ void SingleTriggeredInput::FillPacketClock(Event* evt, Packet* pkt, size_t event { int packet_number = pkt->iValue(0); gl1->SetPacketNumbers(gl1->GetCurrentPacketNumber(), packet_number); - if ( event_index < pooldepth ) + if (event_index < pooldepth) { gl1->SetGl1PacketNumber(event_index, packet_number); } @@ -606,7 +699,7 @@ void SingleTriggeredInput::FillPacketClock(Event* evt, Packet* pkt, size_t event int skip_count = 0; if (gl1->GetLastPacketNumber() != 0) { - int diff = gl1->GetCurrentPacketNumber() - gl1->GetLastPacketNumber() ; + int diff = gl1->GetCurrentPacketNumber() - gl1->GetLastPacketNumber(); skip_count = diff - 1; } @@ -624,7 +717,8 @@ void SingleTriggeredInput::FillPool() return; } - bool all_packets_bad = !m_PacketAlignmentProblem.empty() && std::all_of(m_PacketAlignmentProblem.begin(), m_PacketAlignmentProblem.end(), [](const std::pair &entry) -> bool { return entry.second;}); + bool all_packets_bad = !m_PacketAlignmentProblem.empty() && std::all_of(m_PacketAlignmentProblem.begin(), m_PacketAlignmentProblem.end(), [](const std::pair& entry) -> bool + { return entry.second; }); if (all_packets_bad) { std::cout << Name() << ": ALL packets are marked as bad. Stop combining for this SEB." << std::endl; @@ -647,9 +741,8 @@ void SingleTriggeredInput::FillPool() int gl1pid = Gl1Input()->m_bclkdiffarray_map.begin()->first; const auto& gl1diff = Gl1Input()->m_bclkdiffarray_map.at(gl1pid); - bool allgl1max = std::all_of(gl1diff.begin(), gl1diff.end(), [](uint64_t val) { - return val == std::numeric_limits::max(); - }); + bool allgl1max = std::all_of(gl1diff.begin(), gl1diff.end(), [](uint64_t val) + { return val == std::numeric_limits::max(); }); if (allgl1max) { std::cout << Name() << " : GL1 clock diffs all filled with max 64 bit values for PID " << gl1pid << " return and try next pool" << std::endl; @@ -660,13 +753,13 @@ void SingleTriggeredInput::FillPool() for (const auto& [pid, sebdiff] : m_bclkdiffarray_map) { size_t packetpoolsize = m_PacketEventDeque[pid].size(); - if(packetpoolsize==0) + if (packetpoolsize == 0) { std::cout << Name() << ": packet pool size is zero.... something is wrong" << std::endl; return; } - if(m_PacketAlignmentProblem[pid]) + if (m_PacketAlignmentProblem[pid]) { continue; } @@ -677,22 +770,23 @@ void SingleTriggeredInput::FillPool() bool PrevPoolLastDiffBad = m_PrevPoolLastDiffBad[pid]; bool aligned = false; - if( packetpoolsize < pooldepth && FilesDone() ) + if (packetpoolsize < pooldepth && FilesDone()) { aligned = true; } - else + else { aligned = CheckPoolAlignment(pid, sebdiff, gl1diff, bad_indices, shift, CurrentPoolLastDiffBad, PrevPoolLastDiffBad); } - + if (aligned) { m_PrevPoolLastDiffBad[pid] = CurrentPoolLastDiffBad; if (!bad_indices.empty()) { std::cout << Name() << ": Packet " << pid << " has bad indices: "; - for (int bi : bad_indices){ + for (int bi : bad_indices) + { std::cout << bi << " "; m_DitchPackets[pid].insert(bi); } @@ -704,12 +798,13 @@ void SingleTriggeredInput::FillPool() uint64_t gl1_clk = Gl1Input()->m_bclkarray_map[gl1pid][i]; uint64_t seb_clk = m_bclkarray_map[pid][i]; std::cout << "pool index i " << i << ", gl1 / seb : " << gl1_clk << " / " << seb_clk; - if(im_bclkdiffarray_map[gl1pid][i]; uint64_t seb_diff = m_bclkdiffarray_map[pid][i]; std::cout << " -> diff of gl1 vs seb : " << gl1_diff << " " << seb_diff << std::endl; } - else if(i==pooldepth) + else if (i == pooldepth) { std::cout << std::endl; } @@ -719,11 +814,11 @@ void SingleTriggeredInput::FillPool() if (shift == -1) { std::cout << Name() << ": Packet " << pid << " shifted by -1 with dropping the first seb event" << std::endl; - if(m_PacketShiftOffset[pid] == -1) + if (m_PacketShiftOffset[pid] == -1) { std::cout << "Packet " << pid << " requires an additional shift -1. Lets not handle this for the moment.. stop combining" << std::endl; m_PacketAlignmentProblem[pid] = true; - } + } if (!m_PacketEventDeque[pid].empty()) { @@ -737,12 +832,12 @@ void SingleTriggeredInput::FillPool() for (size_t i = 0; i < packetpoolsize - 1; ++i) { - m_bclkarray_map[pid][i] = m_bclkarray_map[pid][i+1]; + m_bclkarray_map[pid][i] = m_bclkarray_map[pid][i + 1]; } for (size_t i = 0; i < packetpoolsize; ++i) { - m_bclkdiffarray_map[pid][i] = ComputeClockDiff(m_bclkarray_map[pid][i+1], m_bclkarray_map[pid][i]); + m_bclkdiffarray_map[pid][i] = ComputeClockDiff(m_bclkarray_map[pid][i + 1], m_bclkarray_map[pid][i]); } Event* evt = GetEventIterator()->getNextEvent(); if (evt) @@ -770,7 +865,7 @@ void SingleTriggeredInput::FillPool() else if (shift == 1) { std::cout << Name() << ": Packet " << pid << " requires shift +1 (insert dummy at front)" << std::endl; - + if (m_packetclk_copy_runs) { std::cout << Name() << " : runs where clocks are copied from the first XMIT. Checking FEM clock diff" << std::endl; @@ -788,7 +883,7 @@ void SingleTriggeredInput::FillPool() std::cout << Name() << " : Packet identified as misaligned also with FEMs. Do normal recovery process" << std::endl; } - if(m_PacketShiftOffset[pid] == 1) + if (m_PacketShiftOffset[pid] == 1) { std::cout << "Packet " << pid << " requires an additional shift +1. Lets not handle this for the moment.. stop combining" << std::endl; m_PacketAlignmentProblem[pid] = true; @@ -796,11 +891,11 @@ void SingleTriggeredInput::FillPool() for (size_t i = pooldepth; i > 0; --i) { - m_bclkarray_map[pid][i] = m_bclkarray_map[pid][i-1]; + m_bclkarray_map[pid][i] = m_bclkarray_map[pid][i - 1]; } - for (size_t i = 1 ; i < pooldepth; ++i) + for (size_t i = 1; i < pooldepth; ++i) { - m_bclkdiffarray_map[pid][i] = ComputeClockDiff(m_bclkarray_map[pid][i+1], m_bclkarray_map[pid][i]); + m_bclkdiffarray_map[pid][i] = ComputeClockDiff(m_bclkarray_map[pid][i + 1], m_bclkarray_map[pid][i]); } m_bclkarray_map[pid][0] = 0; @@ -810,7 +905,7 @@ void SingleTriggeredInput::FillPool() if (!m_PacketEventDeque[pid].empty()) { m_PacketEventBackup[pid] = m_PacketEventDeque[pid].back(); - Event* dummy_event = m_PacketEventDeque[pid][0]; + Event* dummy_event = m_PacketEventDeque[pid][0]; m_PacketEventDeque[pid].push_front(dummy_event); m_PacketEventDeque[pid].pop_back(); } @@ -833,12 +928,13 @@ void SingleTriggeredInput::FillPool() uint64_t gl1_clk = Gl1Input()->m_bclkarray_map[gl1pid][i]; uint64_t seb_clk = m_bclkarray_map[pid][i]; std::cout << "pool index i " << i << ", gl1 / seb : " << gl1_clk << " / " << seb_clk; - if(im_bclkdiffarray_map[gl1pid][i]; uint64_t seb_diff = m_bclkdiffarray_map[pid][i]; std::cout << " -- diff of gl1 vs seb : " << gl1_diff << " " << seb_diff << std::endl; } - else if(i==pooldepth) + else if (i == pooldepth) { std::cout << std::endl; } @@ -853,10 +949,10 @@ void SingleTriggeredInput::FillPool() if (m_PacketAlignmentFailCount[pid] >= m_max_alignment_retries) { std::cout << Name() << ": Max retries reached — permanently ditching packet " << pid << std::endl; - m_PacketAlignmentFailCount[pid] = 0; + m_PacketAlignmentFailCount[pid] = 0; m_PacketAlignmentProblem[pid] = true; } - + m_PrevPoolLastDiffBad[pid] = false; } } @@ -865,7 +961,7 @@ void SingleTriggeredInput::FillPool() return; } -void SingleTriggeredInput::CreateDSTNodes(Event *evt) +void SingleTriggeredInput::CreateDSTNodes(Event* evt) { std::string CompositeNodeName = "Packets"; if (KeepMyPackets()) @@ -873,31 +969,61 @@ void SingleTriggeredInput::CreateDSTNodes(Event *evt) CompositeNodeName = "PacketsKeep"; } PHNodeIterator iter(m_topNode); - PHCompositeNode *dstNode = dynamic_cast(iter.findFirst("PHCompositeNode", "DST")); + PHCompositeNode* dstNode = dynamic_cast(iter.findFirst("PHCompositeNode", "DST")); if (!dstNode) { dstNode = new PHCompositeNode("DST"); m_topNode->addNode(dstNode); } PHNodeIterator iterDst(dstNode); - PHCompositeNode *detNode = dynamic_cast(iterDst.findFirst("PHCompositeNode", CompositeNodeName)); - if (!detNode) + PHCompositeNode* detNode{nullptr}; + PHCompositeNode* detNodeKeep{nullptr}; + if (m_KeepPacketSet.empty()) { - detNode = new PHCompositeNode(CompositeNodeName); - dstNode->addNode(detNode); + detNode = dynamic_cast(iterDst.findFirst("PHCompositeNode", CompositeNodeName)); + if (!detNode) + { + detNode = new PHCompositeNode(CompositeNodeName); + dstNode->addNode(detNode); + } } - std::vector pktvec = evt->getPacketVector(); - for (auto *piter : pktvec) + else + { + // if we want to keep a few packets, we need two detNodes, Packet and PacketKeep + // this construct here allows for the KeepMyPackets flag to take effect, then both + // node pointers detNode and detNodeKeep point to the same (so KeepMyPackets has precedence) + detNode = dynamic_cast(iterDst.findFirst("PHCompositeNode", CompositeNodeName)); + if (!detNode) + { + detNode = new PHCompositeNode(CompositeNodeName); + dstNode->addNode(detNode); + } + detNodeKeep = dynamic_cast(iterDst.findFirst("PHCompositeNode", "PacketsKeep")); + if (!detNodeKeep) + { + detNodeKeep = new PHCompositeNode("PacketsKeep"); + dstNode->addNode(detNodeKeep); + } + } + + std::vector pktvec = evt->getPacketVector(); + for (auto* piter : pktvec) { int packet_id = piter->getIdentifier(); m_PacketSet.insert(packet_id); - std::string PacketNodeName = std::to_string(packet_id); - CaloPacket *calopacket = findNode::getClass(detNode, PacketNodeName); + CaloPacket* calopacket = findNode::getClass(detNode, packet_id); if (!calopacket) { calopacket = new CaloPacketv1(); - PHIODataNode *newNode = new PHIODataNode(calopacket, PacketNodeName, "PHObject"); - detNode->addNode(newNode); + PHIODataNode* newNode = new PHIODataNode(calopacket, packet_id, "PHObject"); + if (m_KeepPacketSet.contains(packet_id)) + { + detNodeKeep->addNode(newNode); + } + else + { + detNode->addNode(newNode); + } } m_PacketShiftOffset.try_emplace(packet_id, 0); delete piter; @@ -940,8 +1066,10 @@ bool SingleTriggeredInput::FemClockAlignment(int pid, const std::deque& } int majority_clk = std::max_element( - clk_count.begin(), clk_count.end(), - [](const auto& a, const auto& b) { return a.second < b.second; })->first; + clk_count.begin(), clk_count.end(), + [](const auto& a, const auto& b) + { return a.second < b.second; }) + ->first; if (clk_count[majority_clk] < 2) { @@ -949,7 +1077,6 @@ bool SingleTriggeredInput::FemClockAlignment(int pid, const std::deque& return false; } - if (i >= 1 && prev_clk != std::numeric_limits::max() && gl1diff[i] != std::numeric_limits::max()) { uint16_t fem_diff = static_cast(ComputeClockDiff(majority_clk, prev_clk) & 0xFFFFU); @@ -968,9 +1095,9 @@ bool SingleTriggeredInput::FemClockAlignment(int pid, const std::deque& return true; } -int SingleTriggeredInput::FemEventNrClockCheck(OfflinePacket *pkt) +int SingleTriggeredInput::FemEventNrClockCheck(OfflinePacket* pkt) { - CaloPacket *calopkt = dynamic_cast(pkt); + CaloPacket* calopkt = dynamic_cast(pkt); if (!calopkt) { return 0; @@ -1008,7 +1135,7 @@ int SingleTriggeredInput::FemEventNrClockCheck(OfflinePacket *pkt) } } } - else + else { for (int j = 0; j < nrModules; j++) { @@ -1056,7 +1183,7 @@ int SingleTriggeredInput::FemEventNrClockCheck(OfflinePacket *pkt) for (const auto iterA : ClockMap) { std::cout << "Clock : 0x" << std::hex << iterA.first << std::dec - << " shows up " << iterA.second << " times" << std::endl; + << " shows up " << iterA.second << " times" << std::endl; } } return -1; @@ -1067,8 +1194,8 @@ int SingleTriggeredInput::FemEventNrClockCheck(OfflinePacket *pkt) void SingleTriggeredInput::dumpdeque() { - const auto *iter1 = clkdiffbegin(); - const auto *iter2 = Gl1Input()->clkdiffbegin(); + const auto* iter1 = clkdiffbegin(); + const auto* iter2 = Gl1Input()->clkdiffbegin(); while (iter1 != clkdiffend()) { std::cout << Name() << " clk: 0x" << std::hex << *iter1 @@ -1100,11 +1227,11 @@ int SingleTriggeredInput::ReadEvent() std::cout << "deque size: " << size << std::endl; } - auto *ref_evt = m_PacketEventDeque.begin()->second.front(); + auto* ref_evt = m_PacketEventDeque.begin()->second.front(); RunNumber(ref_evt->getRunNumber()); uint64_t event_number = ref_evt->getEvtSequence(); - if(event_number % 10000==0) + if (event_number % 10000 == 0) { std::cout << "processed events : " << event_number << std::endl; } @@ -1113,19 +1240,19 @@ int SingleTriggeredInput::ReadEvent() bool all_packets_unshifted = std::all_of( m_PacketShiftOffset.begin(), m_PacketShiftOffset.end(), - [](const std::pair& p) { return p.second == 0; }); + [](const std::pair& p) + { return p.second == 0; }); std::set events_to_delete; - for (auto& [pid, dq] : m_PacketEventDeque) { - if(m_PacketAlignmentProblem[pid]) + if (m_PacketAlignmentProblem[pid]) { continue; } + Event* evt = dq.front(); Packet* packet = evt->getPacket(pid); - int packet_id = packet->getIdentifier(); if (packet_id != pid) { @@ -1135,9 +1262,8 @@ int SingleTriggeredInput::ReadEvent() return -1; } - CaloPacket *newhit = findNode::getClass(m_topNode, packet_id); + CaloPacket* newhit = findNode::getClass(m_topNode, packet_id); newhit->Reset(); - if (m_DitchPackets.contains(packet_id) && m_DitchPackets[packet_id].contains(0)) { newhit->setStatus(OfflinePacket::PACKET_DROPPED); @@ -1164,7 +1290,7 @@ int SingleTriggeredInput::ReadEvent() { uint64_t prev_packet_clock = m_PreviousValidBCOMap[packet_id]; newhit->setBCO(prev_packet_clock); - m_PreviousValidBCOMap[packet_id] = GetClock(evt,packet_id); + m_PreviousValidBCOMap[packet_id] = GetClock(evt, packet_id); } else { @@ -1203,7 +1329,7 @@ int SingleTriggeredInput::ReadEvent() int iret = FemEventNrClockCheck(newhit); if (iret < 0) { - std::cout << Name() <<" : failed on FemEventNrClockCheck reset calo packet " << std::endl; + std::cout << Name() << " : failed on FemEventNrClockCheck reset calo packet " << std::endl; newhit->Reset(); } @@ -1213,7 +1339,7 @@ int SingleTriggeredInput::ReadEvent() } } - for(Event *evtdelete : events_to_delete) + for (Event* evtdelete : events_to_delete) { delete evtdelete; } diff --git a/offline/framework/fun4allraw/SingleTriggeredInput.h b/offline/framework/fun4allraw/SingleTriggeredInput.h index 088be73bef..cad0d64bf0 100644 --- a/offline/framework/fun4allraw/SingleTriggeredInput.h +++ b/offline/framework/fun4allraw/SingleTriggeredInput.h @@ -17,6 +17,7 @@ #include #include #include +#include #include class Event; @@ -34,9 +35,6 @@ class SingleTriggeredInput : public Fun4AllBase, public InputFileHandler virtual void FillPool(); virtual void RunNumber(const int runno) { m_RunNumber = runno; } virtual int RunNumber() const { return m_RunNumber; } - virtual void EventNumber(const int i) { m_EventNumber = i; } - virtual int EventNumber() const { return m_EventNumber; } - virtual int EventsInThisFile() const { return m_EventsThisFile; } virtual int fileopen(const std::string &filename) override; virtual int fileclose() override; virtual int AllDone() const { return m_AllDone; } @@ -45,6 +43,8 @@ class SingleTriggeredInput : public Fun4AllBase, public InputFileHandler virtual void FilesDone(const int i) { m_FilesDone = i; } virtual void EventAlignmentProblem(const int i) { m_EventAlignmentProblem = i; } virtual int EventAlignmentProblem() const { return m_EventAlignmentProblem; } + virtual void EventNumber(const int i) { m_EventNumber = i; } + virtual int EventNumber() const { return m_EventNumber; } virtual void CreateDSTNodes(Event *evt); // these ones are used directly by the derived classes, maybe later // move to cleaner accessors @@ -59,15 +59,16 @@ class SingleTriggeredInput : public Fun4AllBase, public InputFileHandler virtual std::array::const_iterator beginclock() { return m_bclkarray.begin(); } virtual void KeepPackets() { m_KeepPacketsFlag = true; } virtual bool KeepMyPackets() const { return m_KeepPacketsFlag; } + virtual void KeepPacket(const int packetnum) { m_KeepPacketSet.insert(packetnum); } void topNode(PHCompositeNode *topNode) { m_topNode = topNode; } PHCompositeNode *topNode() { return m_topNode; } virtual void FakeProblemEvent(const int ievent) { m_ProblemEvent = ievent; } virtual int FemEventNrClockCheck(OfflinePacket *calopkt); void dumpdeque(); int checkfirstsebevent(); - virtual bool CheckFemDiffIdx(int pid, size_t index, const std::deque& events, uint64_t gl1diffidx); - virtual bool CheckPoolAlignment(int pid, const std::array& sebdiff, const std::array& gl1diff, std::vector& bad_indices, int& shift, bool& CurrentPoolLastDiffBad, bool PrevPoolLastDiffBad); - virtual bool FemClockAlignment(int pid, const std::deque& events, const std::array& gl1diff); + virtual bool CheckFemDiffIdx(int pid, size_t index, const std::deque &events, uint64_t gl1diffidx); + virtual bool CheckPoolAlignment(int pid, const std::array &sebdiff, const std::array &gl1diff, std::vector &bad_indices, int &shift, bool &CurrentPoolLastDiffBad, bool PrevPoolLastDiffBad); + virtual bool FemClockAlignment(int pid, const std::deque &events, const std::array &gl1diff); protected: PHCompositeNode *m_topNode{nullptr}; @@ -77,24 +78,22 @@ class SingleTriggeredInput : public Fun4AllBase, public InputFileHandler // the accompanying diff to the previous beam clock with this event, so any mismatch // gives us the event index in the deque which is off std::deque m_EventDeque; - std::map> m_PacketEventDeque; - std::map m_PacketEventBackup; + std::map> m_PacketEventDeque; + std::map m_PacketEventBackup; std::map m_PacketShiftOffset; std::array m_bclkarray{}; // keep the last bco from previous loop std::array m_bclkdiffarray{}; std::map> m_bclkarray_map; - std::map> m_bclkdiffarray_map; + std::map> m_bclkdiffarray_map; std::set m_PacketSet; static uint64_t ComputeClockDiff(uint64_t curr, uint64_t prev) { return (curr - prev) & 0xFFFFFFFF; } - private: Eventiterator *m_EventIterator{nullptr}; SingleTriggeredInput *m_Gl1Input{nullptr}; int m_AllDone{0}; uint64_t m_Event{0}; int m_EventNumber{0}; - int m_EventsThisFile{0}; int m_EventAlignmentProblem{0}; int m_FilesDone{0}; int m_LastEvent{std::numeric_limits::max()}; @@ -106,6 +105,7 @@ class SingleTriggeredInput : public Fun4AllBase, public InputFileHandler bool firstclockcheck{true}; bool m_KeepPacketsFlag{false}; bool m_packetclk_copy_runs{false}; + int64_t eventcounter{0}; std::set m_CorrectCopiedClockPackets; std::map> m_DitchPackets; std::set m_FEMEventNrSet; @@ -114,6 +114,7 @@ class SingleTriggeredInput : public Fun4AllBase, public InputFileHandler std::map m_PacketAlignmentProblem; std::map m_PrevPoolLastDiffBad; std::map m_PreviousValidBCOMap; + std::unordered_set m_KeepPacketSet; }; #endif diff --git a/offline/framework/fun4allraw/TpcTimeFrameBuilder.cc b/offline/framework/fun4allraw/TpcTimeFrameBuilder.cc index 8eeca60c88..e068899771 100644 --- a/offline/framework/fun4allraw/TpcTimeFrameBuilder.cc +++ b/offline/framework/fun4allraw/TpcTimeFrameBuilder.cc @@ -8,6 +8,9 @@ #include #include +#include +#include + #include // for PHTimer #include @@ -596,6 +599,12 @@ int TpcTimeFrameBuilder::ProcessPacket(Packet* packet) { unsigned int fee_id = dma_word_data.dma_header & 0xffU; + // for packet id 4XYZ ebdc is XY, endpoint is Z + if (m_maskedFEEs[((m_packet_id / 10) % 100)].contains(fee_id)) + { + continue; + } + if (fee_id < MAX_FEECOUNT) { for (const uint16_t& i : dma_word_data.data) @@ -713,7 +722,7 @@ int TpcTimeFrameBuilder::process_fee_data(unsigned int fee) } // valid packet - const uint16_t& pkt_length = data_buffer[0]; // this is indeed the number of 10-bit words + 5 in this packet + const uint16_t pkt_length = data_buffer[0]; // this is indeed the number of 10-bit words + 5 in this packet if (pkt_length > MAX_PACKET_LENGTH) { if (m_verbosity > 1) @@ -2056,3 +2065,27 @@ void TpcTimeFrameBuilder::BcoMatchingInformation::cleanup(uint64_t ref_bco) // clear orphans m_orphans.clear(); } + +void TpcTimeFrameBuilder::fillBadFeeMap() +{ + const std::string filename = CDBInterface::instance()->getUrl("TPC_DECODER_BAD_FEE"); + + if (filename.empty()) + { + if (m_verbosity > 0) + { + std::cout << "TpcTimeFrameBuilder::fillBadFeeMap - no file found for TPC_DECODER_BAD_FEE, not filling bad fee map" << std::endl; + } + return; + } + + CDBTTree cdbtree(filename); + cdbtree.LoadCalibrations(); + + const int nentries = cdbtree.GetSingleIntValue("N_MASKED_FEES"); + + for (int i = 0; i < nentries; i++) + { + m_maskedFEEs[cdbtree.GetIntValue(i, "EBDC")].insert(cdbtree.GetIntValue(i, "FEEID")); + } +} \ No newline at end of file diff --git a/offline/framework/fun4allraw/TpcTimeFrameBuilder.h b/offline/framework/fun4allraw/TpcTimeFrameBuilder.h index 553052b851..07e2921310 100644 --- a/offline/framework/fun4allraw/TpcTimeFrameBuilder.h +++ b/offline/framework/fun4allraw/TpcTimeFrameBuilder.h @@ -41,6 +41,8 @@ class TpcTimeFrameBuilder m_fastBCOSkip = fastBCOSkip; } + void fillBadFeeMap(); + // enable saving of digital current debug TTree with file name `name` void SaveDigitalCurrentDebugTTree(const std::string &name); @@ -50,7 +52,7 @@ class TpcTimeFrameBuilder static const uint16_t FEE_PACKET_MAGIC_KEY_1 = 0xfe; static const uint16_t FEE_PACKET_MAGIC_KEY_2 = 0xed; - static const uint16_t FEE_PACKET_MAGIC_KEY_3_DC = 0xdcdc; // Digital Current word[3] + static const uint16_t FEE_PACKET_MAGIC_KEY_3_DC = 0xdcdc; // Digital Current word[3] static const uint16_t FEE_MAGIC_KEY = 0xba00; static const uint16_t GTM_MAGIC_KEY = 0xbb00; @@ -81,8 +83,8 @@ class TpcTimeFrameBuilder int decode_gtm_data(const dma_word >m_word); int process_fee_data(unsigned int fee_id); - void process_fee_data_waveform(const unsigned int & fee_id, std::deque& data_buffer); - void process_fee_data_digital_current(const unsigned int & fee_id, std::deque& data_buffer); + void process_fee_data_waveform(const unsigned int &fee_id, std::deque &data_buffer); + void process_fee_data_digital_current(const unsigned int &fee_id, std::deque &data_buffer); struct gtm_payload { @@ -112,7 +114,7 @@ class TpcTimeFrameBuilder uint16_t data_crc = 0; uint16_t calc_crc = 0; - + uint16_t data_parity = 0; uint16_t calc_parity = 0; @@ -123,18 +125,18 @@ class TpcTimeFrameBuilder { static const int MAX_CHANNELS = 8; - uint64_t gtm_bco {std::numeric_limits::max()}; - uint32_t bx_timestamp_predicted {std::numeric_limits::max()}; + uint64_t gtm_bco{std::numeric_limits::max()}; + uint32_t bx_timestamp_predicted{std::numeric_limits::max()}; - uint16_t fee {std::numeric_limits::max()}; - uint16_t pkt_length {std::numeric_limits::max()}; - uint16_t channel {std::numeric_limits::max()}; + uint16_t fee{std::numeric_limits::max()}; + uint16_t pkt_length{std::numeric_limits::max()}; + uint16_t channel{std::numeric_limits::max()}; // uint16_t sampa_max_channel {std::numeric_limits::max()}; - uint16_t sampa_address {std::numeric_limits::max()}; - uint32_t bx_timestamp {0}; - uint32_t current[MAX_CHANNELS] {0}; - uint32_t nsamples[MAX_CHANNELS] {0}; - uint16_t data_crc {std::numeric_limits::max()}; + uint16_t sampa_address{std::numeric_limits::max()}; + uint32_t bx_timestamp{0}; + uint32_t current[MAX_CHANNELS]{0}; + uint32_t nsamples[MAX_CHANNELS]{0}; + uint16_t data_crc{std::numeric_limits::max()}; uint16_t calc_crc = {std::numeric_limits::max()}; // uint16_t type {std::numeric_limits::max()}; }; @@ -153,7 +155,7 @@ class TpcTimeFrameBuilder std::string m_name; TTree *m_tDigitalCurrent = nullptr; }; - DigitalCurrentDebugTTree * m_digitalCurrentDebugTTree = nullptr; + DigitalCurrentDebugTTree *m_digitalCurrentDebugTTree = nullptr; // ------------------------- // GTM Matcher @@ -371,6 +373,8 @@ class TpcTimeFrameBuilder private: std::vector> m_feeData; + std::map> m_maskedFEEs; + int m_verbosity = 0; int m_packet_id = 0; diff --git a/offline/framework/phool/PHIODataNode.h b/offline/framework/phool/PHIODataNode.h index 46be461793..3ee60a8e4c 100644 --- a/offline/framework/phool/PHIODataNode.h +++ b/offline/framework/phool/PHIODataNode.h @@ -23,6 +23,7 @@ class PHIODataNode : public PHDataNode T *operator*() { return this->getData(); } PHIODataNode(T *, const std::string &); PHIODataNode(T *, const std::string &, const std::string &); + PHIODataNode(T *, const int, const std::string &); virtual ~PHIODataNode() = default; typedef PHTypedNodeIterator iterator; void BufferSize(int size) { buffersize = size; } @@ -54,6 +55,16 @@ PHIODataNode::PHIODataNode(T *d, const std::string &n, this->objectclass = TO->GetName(); } +template +PHIODataNode::PHIODataNode(T *d, const int id, + const std::string &objtype) + : PHDataNode(d, std::to_string(id), objtype) +{ + this->type = "PHIODataNode"; + TObject *TO = static_cast(d); + this->objectclass = TO->GetName(); +} + template bool PHIODataNode::write(PHIOManager *IOManager, const std::string &path) { diff --git a/offline/framework/phool/RunnumberRange.h b/offline/framework/phool/RunnumberRange.h index a9a860e583..ab6593bff5 100644 --- a/offline/framework/phool/RunnumberRange.h +++ b/offline/framework/phool/RunnumberRange.h @@ -1,18 +1,36 @@ #ifndef PHOOL_RUNNUMBERRANGE_H #define PHOOL_RUNNUMBERRANGE_H -// first and last physics run +/** + * Defines run-number range constants and special run markers used to identify physics data-taking periods. + * + * Each constant names the first or last run number (or a special marker) for a given data-taking period. + * + * @var RUN2PP_FIRST First Run 2 proton-proton physics run. + * @var RUN2PP_LAST Last Run 2 proton-proton physics run. + * @var RUN2AUAU_FIRST First Run 2 Au+Au (heavy-ion) physics run. + * @var RUN2AUAU_LAST Last Run 2 Au+Au (heavy-ion) physics run. + * @var RUN3_TPCFW_CLOCK_CHANGE Run 3 marker for the TPC Forward clock change. + * @var RUN3AUAU_FIRST First Run 3 Au+Au (heavy-ion) physics run. + * @var RUN3AUAU_LAST Last Run 3 Au+Au (heavy-ion) physics run. + * @var RUN3PP_FIRST First Run 3 proton-proton (beam) physics run. + * @var RUN3PP_LAST Last Run 3 proton-proton physics run. + * @var RUN3OO_FIRST First Run 3 O+O physics run. + * @var RUN3OO_LAST Last Run 3 O+O physics run. + */ namespace RunnumberRange { - static const int RUN2PP_FIRST = 47286; - static const int RUN2PP_LAST = 53880; - static const int RUN2AUAU_FIRST = 54128; - static const int RUN2AUAU_LAST = 54974; - static const int RUN3_TPCFW_CLOCK_CHANGE = 58667; - static const int RUN3AUAU_FIRST = 66457; - static const int RUN3AUAU_LAST = 78954; - static const int RUN3PP_FIRST = 79146; // first beam data - static const int RUN3PP_LAST = 100000; + constexpr int RUN2PP_FIRST = 47286; + constexpr int RUN2PP_LAST = 53880; + constexpr int RUN2AUAU_FIRST = 54128; + constexpr int RUN2AUAU_LAST = 54974; + constexpr int RUN3_TPCFW_CLOCK_CHANGE = 58667; + constexpr int RUN3AUAU_FIRST = 66457; + constexpr int RUN3AUAU_LAST = 78954; + constexpr int RUN3PP_FIRST = 79146; // first beam data + constexpr int RUN3PP_LAST = 81668; + constexpr int RUN3OO_FIRST = 82388; // after trigger settled down (run 82374 excluded); + constexpr int RUN3OO_LAST = 82703; } #endif diff --git a/offline/packages/CaloBase/TowerInfo.h b/offline/packages/CaloBase/TowerInfo.h index 821da289d7..2ec6402f2b 100644 --- a/offline/packages/CaloBase/TowerInfo.h +++ b/offline/packages/CaloBase/TowerInfo.h @@ -30,8 +30,8 @@ class TowerInfo : public PHObject virtual float get_pedestal() { return std::numeric_limits::quiet_NaN(); } virtual void set_isHot(bool /*isHot*/) { return; } virtual bool get_isHot() const { return false; } - virtual void set_isBadTime(bool /*isBadTime*/) { return; } - virtual bool get_isBadTime() const { return false; } + virtual void set_FitStatus(bool /*fitstatus*/) { return; } + virtual bool get_FitStatus() const { return false; } virtual void set_isBadChi2(bool /*isBadChi2*/) { return; } virtual bool get_isBadChi2() const { return false; } virtual void set_isNotInstr(bool /*isNotInstr*/) { return; } diff --git a/offline/packages/CaloBase/TowerInfov2.h b/offline/packages/CaloBase/TowerInfov2.h index 8d064d840f..dd8889ff48 100644 --- a/offline/packages/CaloBase/TowerInfov2.h +++ b/offline/packages/CaloBase/TowerInfov2.h @@ -24,8 +24,8 @@ class TowerInfov2 : public TowerInfov1 void set_isHot(bool isHot) override { set_status_bit(0, isHot); } bool get_isHot() const override { return get_status_bit(0); } - void set_isBadTime(bool isBadTime) override { set_status_bit(1, isBadTime); } - bool get_isBadTime() const override { return get_status_bit(1); } + void set_FitStatus(bool fitstatus) override { set_status_bit(1, fitstatus); } + bool get_FitStatus() const override { return get_status_bit(1); } void set_isBadChi2(bool isBadChi2) override { set_status_bit(2, isBadChi2); } bool get_isBadChi2() const override { return get_status_bit(2); } @@ -45,7 +45,7 @@ class TowerInfov2 : public TowerInfov1 void set_isSaturated(bool isSaturated) override { set_status_bit(7, isSaturated); } bool get_isSaturated() const override { return get_status_bit(7); } - bool get_isGood() const override { return !(get_isHot() || get_isBadChi2() || get_isNoCalib()); } + bool get_isGood() const override { return !(get_isHot() || get_isBadChi2() || get_isNoCalib() || get_isNotInstr()); } uint8_t get_status() const override { return _status; } diff --git a/offline/packages/CaloBase/TowerInfov4.h b/offline/packages/CaloBase/TowerInfov4.h index 09bd986298..6a44ca385b 100644 --- a/offline/packages/CaloBase/TowerInfov4.h +++ b/offline/packages/CaloBase/TowerInfov4.h @@ -58,8 +58,8 @@ class TowerInfov4 : public TowerInfo void set_isHot(bool isHot) override { set_status_bit(0, isHot); } bool get_isHot() const override { return get_status_bit(0); } - void set_isBadTime(bool isBadTime) override { set_status_bit(1, isBadTime); } - bool get_isBadTime() const override { return get_status_bit(1); } + void set_FitStatus(bool fitstatus) override { set_status_bit(1, fitstatus); } + bool get_FitStatus() const override { return get_status_bit(1); } void set_isBadChi2(bool isBadChi2) override { set_status_bit(2, isBadChi2); } bool get_isBadChi2() const override { return get_status_bit(2); } @@ -79,7 +79,7 @@ class TowerInfov4 : public TowerInfo void set_isSaturated(bool isSaturated) override { set_status_bit(7, isSaturated); } bool get_isSaturated() const override { return get_status_bit(7); } - bool get_isGood() const override { return !(get_isHot() || get_isBadChi2() || get_isNoCalib()); } + bool get_isGood() const override { return !(get_isHot() || get_isBadChi2() || get_isNoCalib() || get_isNotInstr()); } uint8_t get_status() const override { return status; } diff --git a/offline/packages/CaloEmbedding/CombineTowerInfo.cc b/offline/packages/CaloEmbedding/CombineTowerInfo.cc new file mode 100644 index 0000000000..3e5150d194 --- /dev/null +++ b/offline/packages/CaloEmbedding/CombineTowerInfo.cc @@ -0,0 +1,99 @@ +#include "CombineTowerInfo.h" + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +//____________________________________________________________________________ +CombineTowerInfo::CombineTowerInfo(const std::string& name) + : SubsysReco(name) +{ +} + +//____________________________________________________________________________ +int CombineTowerInfo::InitRun(PHCompositeNode* topNode) +{ + if (m_inputNodeA.empty() || m_inputNodeB.empty() || m_outputNode.empty()) + { + throw std::runtime_error("CombineTowerInfo: input/output node names not set"); + } + + CreateNodes(topNode); + return Fun4AllReturnCodes::EVENT_OK; +} + +//____________________________________________________________________________ +void CombineTowerInfo::CreateNodes(PHCompositeNode* topNode) +{ + PHNodeIterator iter(topNode); + PHCompositeNode* dstNode = + dynamic_cast(iter.findFirst("PHCompositeNode", "DST")); + + if (!dstNode) + { + throw std::runtime_error("CombineTowerInfo: DST node not found"); + } + + PHCompositeNode *DetNode = dynamic_cast(iter.findFirst("PHCompositeNode", m_detector)); + + m_towersA = findNode::getClass(topNode, m_inputNodeA); + m_towersB = findNode::getClass(topNode, m_inputNodeB); + + if (!m_towersB) + { + std::cout << "CombineTowerInfo: " <(dstNode, m_outputNode); + if (!m_towersOut) + { + m_towersOut = + dynamic_cast(m_towersA->CloneMe()); + + auto* node = new PHIODataNode( + m_towersOut, m_outputNode, "PHObject"); + + DetNode->addNode(node); + } + + if (m_towersA->size() != m_towersB->size()) + { + throw std::runtime_error("CombineTowerInfo: input containers have different sizes"); + } +} + +//____________________________________________________________________________ +int CombineTowerInfo::process_event(PHCompositeNode* /*topNode*/) +{ + const unsigned int ntowers = m_towersA->size(); + + for (unsigned int ich = 0; ich < ntowers; ++ich) + { + TowerInfo* towerA = m_towersA->get_tower_at_channel(ich); + TowerInfo* towerB = m_towersB->get_tower_at_channel(ich); + TowerInfo* towerO = m_towersOut->get_tower_at_channel(ich); + + towerO->copy_tower(towerA); + + const float e_sum = towerA->get_energy() + towerB->get_energy(); + towerO->set_energy(e_sum); + } + + return Fun4AllReturnCodes::EVENT_OK; +} + diff --git a/offline/packages/CaloEmbedding/CombineTowerInfo.h b/offline/packages/CaloEmbedding/CombineTowerInfo.h new file mode 100644 index 0000000000..ab96a918e6 --- /dev/null +++ b/offline/packages/CaloEmbedding/CombineTowerInfo.h @@ -0,0 +1,39 @@ +#ifndef COMBINETOWERINFO_H +#define COMBINETOWERINFO_H + +#include + +#include + +class PHCompositeNode; +class TowerInfoContainer; + +class CombineTowerInfo : public SubsysReco +{ + public: + explicit CombineTowerInfo(const std::string& name = "CombineTowerInfo"); + ~CombineTowerInfo() override = default; + + int InitRun(PHCompositeNode* topNode) override; + int process_event(PHCompositeNode* topNode) override; + + void set_inputNodeA(const std::string& name) { m_inputNodeA = name; } + void set_inputNodeB(const std::string& name) { m_inputNodeB = name; } + void set_outputNode(const std::string& name) { m_outputNode = name; } + void set_detector(const std::string& name) { m_detector = name; } + + private: + void CreateNodes(PHCompositeNode* topNode); + + std::string m_inputNodeA; + std::string m_inputNodeB; + std::string m_outputNode; + std::string m_detector; + + TowerInfoContainer* m_towersA{nullptr}; + TowerInfoContainer* m_towersB{nullptr}; + TowerInfoContainer* m_towersOut{nullptr}; +}; + +#endif + diff --git a/offline/packages/CaloEmbedding/CopyIODataNodes.cc b/offline/packages/CaloEmbedding/CopyIODataNodes.cc index 0d4d4536ff..08428dccfe 100644 --- a/offline/packages/CaloEmbedding/CopyIODataNodes.cc +++ b/offline/packages/CaloEmbedding/CopyIODataNodes.cc @@ -7,6 +7,9 @@ #include +#include +#include + #include #include @@ -57,6 +60,10 @@ int CopyIODataNodes::InitRun(PHCompositeNode *topNode) { CreateSyncObject(topNode, se->topNode()); } + if (m_CopyTowerInfoFlag) + { + CreateTowerInfo(topNode, se->topNode()); + } return Fun4AllReturnCodes::EVENT_OK; } @@ -89,6 +96,10 @@ int CopyIODataNodes::process_event(PHCompositeNode *topNode) { CopySyncObject(topNode, se->topNode()); } + if (m_CopyTowerInfoFlag) + { + CopyTowerInfo(topNode, se->topNode()); + } return Fun4AllReturnCodes::EVENT_OK; } @@ -293,6 +304,29 @@ void CopyIODataNodes::CopyMinimumBiasInfo(PHCompositeNode *from_topNode, PHCompo return; } +void CopyIODataNodes::CopyTowerInfo(PHCompositeNode *from_topNode, PHCompositeNode *to_topNode) +{ + TowerInfoContainer *from_towerInfo = findNode::getClass(from_topNode, from_towerInfo_name); + TowerInfoContainer *to_towerInfo = findNode::getClass( to_topNode, to_towerInfo_name); + unsigned int ntowers = from_towerInfo->size(); + for (unsigned int ch = 0; ch < ntowers; ++ch) + { + TowerInfo *from_tow = from_towerInfo->get_tower_at_channel(ch); + to_towerInfo->get_tower_at_channel(ch)->copy_tower(from_tow); + } + + if (Verbosity() > 0) + { + std::cout << "From TowerInfoContainer identify()" << std::endl; + from_towerInfo->identify(); + std::cout << "To TowerInfoCOntainer identify()" << std::endl; + to_towerInfo->identify(); + } + + return; +} + + void CopyIODataNodes::CreateMbdOut(PHCompositeNode *from_topNode, PHCompositeNode *to_topNode) { @@ -330,6 +364,36 @@ void CopyIODataNodes::CreateMbdOut(PHCompositeNode *from_topNode, PHCompositeNod } +void CopyIODataNodes::CreateTowerInfo(PHCompositeNode *from_topNode, PHCompositeNode *to_topNode) +{ + std::cout << "copying tower info" << std::endl; + TowerInfoContainer *from_towerInfo = findNode::getClass(from_topNode, from_towerInfo_name); + if (!from_towerInfo) + { + std::cout << "Could not locate TowerInfoContainer on " << from_topNode->getName() << std::endl; + m_CopyTowerInfoFlag = false; + return; + } + TowerInfoContainer *to_towerInfo = findNode::getClass(to_topNode, to_towerInfo_name); + if (!to_towerInfo) + { + PHNodeIterator iter(to_topNode); + PHCompositeNode *dstNode = dynamic_cast(iter.findFirst("PHCompositeNode", "DST")); + if (!dstNode) + { + dstNode = new PHCompositeNode("DST"); + to_topNode->addNode(dstNode); + } + to_towerInfo = dynamic_cast(from_towerInfo->CloneMe()); + PHIODataNode *newNode = new PHIODataNode(to_towerInfo, to_towerInfo_name, "PHObject"); + dstNode->addNode(newNode); + } + return; +} + + + + void CopyIODataNodes::CopyMbdOut(PHCompositeNode *from_topNode, PHCompositeNode *to_topNode) { MbdOut *from_mbdout = findNode::getClass(from_topNode, "MbdOut"); diff --git a/offline/packages/CaloEmbedding/CopyIODataNodes.h b/offline/packages/CaloEmbedding/CopyIODataNodes.h index 08626bdafb..5045792a2d 100644 --- a/offline/packages/CaloEmbedding/CopyIODataNodes.h +++ b/offline/packages/CaloEmbedding/CopyIODataNodes.h @@ -35,6 +35,13 @@ class CopyIODataNodes : public SubsysReco void CopyMbdOut(bool flag = true) { m_CopyMbdOutFlag = flag; } void CopyRunHeader(bool flag = true) { m_CopyRunHeaderFlag = flag; } void CopySyncObject(bool flag = true) { m_CopySyncObjectFlag = flag; } + void set_CopyTowerInfo(const std::string& set_from_towerInfo_name,const std::string& set_to_towerInfo_name) + { + from_towerInfo_name = set_from_towerInfo_name; + to_towerInfo_name = set_to_towerInfo_name; + m_CopyTowerInfoFlag = true; + return; + } private: void CreateCentralityInfo(PHCompositeNode *from_topNode, PHCompositeNode *to_topNode); @@ -56,6 +63,8 @@ class CopyIODataNodes : public SubsysReco void CreateSyncObject(PHCompositeNode *from_topNode, PHCompositeNode *to_topNode); void CopySyncObject(PHCompositeNode *from_topNode, PHCompositeNode *to_topNode); + void CopyTowerInfo(PHCompositeNode *from_topNode, PHCompositeNode *to_topNode); + void CreateTowerInfo(PHCompositeNode *from_topNode, PHCompositeNode *to_topNode); bool m_CopyCentralityInfoFlag = true; bool m_CopyEventHeaderFlag = true; @@ -64,6 +73,10 @@ class CopyIODataNodes : public SubsysReco bool m_CopyMbdOutFlag = true; bool m_CopyRunHeaderFlag = true; bool m_CopySyncObjectFlag = true; + bool m_CopyTowerInfoFlag = false; + + std::string from_towerInfo_name = {}; + std::string to_towerInfo_name = {}; }; #endif // COPYIODATANODES_H diff --git a/offline/packages/CaloEmbedding/Makefile.am b/offline/packages/CaloEmbedding/Makefile.am index 9731b33cb8..f9dd1faa22 100644 --- a/offline/packages/CaloEmbedding/Makefile.am +++ b/offline/packages/CaloEmbedding/Makefile.am @@ -13,6 +13,7 @@ AM_LDFLAGS = \ pkginclude_HEADERS = \ caloTowerEmbed.h \ CopyIODataNodes.h \ + CombineTowerInfo.h \ HepMCCollisionVertex.h lib_LTLIBRARIES = \ @@ -21,6 +22,7 @@ lib_LTLIBRARIES = \ libCaloEmbedding_la_SOURCES = \ caloTowerEmbed.cc \ CopyIODataNodes.cc \ + CombineTowerInfo.cc \ HepMCCollisionVertex.cc libCaloEmbedding_la_LIBADD = \ diff --git a/offline/packages/CaloReco/CaloTowerBuilder.cc b/offline/packages/CaloReco/CaloTowerBuilder.cc index 632cd8161d..2d0f31a017 100644 --- a/offline/packages/CaloReco/CaloTowerBuilder.cc +++ b/offline/packages/CaloReco/CaloTowerBuilder.cc @@ -75,6 +75,14 @@ int CaloTowerBuilder::InitRun(PHCompositeNode *topNode) WaveformProcessing->set_bitFlipRecovery(m_dobitfliprecovery); } + // Set functional fit parameters + if (_processingtype == CaloWaveformProcessing::FUNCFIT) + { + WaveformProcessing->set_funcfit_type(m_funcfit_type); + WaveformProcessing->set_powerlaw_params(m_powerlaw_power, m_powerlaw_decay); + WaveformProcessing->set_doubleexp_params(m_doubleexp_power, m_doubleexp_peaktime1, m_doubleexp_peaktime2, m_doubleexp_ratio); + } + if (m_dettype == CaloTowerDefs::CEMC) { m_detector = "CEMC"; @@ -232,6 +240,7 @@ int CaloTowerBuilder::process_sim() { towerinfo->set_isRecovered(true); } + towerinfo->set_FitStatus(static_cast(processed_waveforms.at(i).at(5))); int n_samples = waveforms.at(i).size(); if (n_samples == m_nzerosuppsamples || SZS) { @@ -299,6 +308,25 @@ int CaloTowerBuilder::process_data(PHCompositeNode *topNode, std::vectoriValue(0, "CHANNELS"); unsigned int adc_skip_mask = 0; + if (nchannels == 0) // push back -1 and return for empty packets + { + for (int channel = 0; channel < m_nchannels; channel++) + { + if (skipChannel(channel, pid)) + { + continue; + } + std::vector waveform; + waveform.reserve(m_nzerosuppsamples); + for (int samp = 0; samp < m_nzerosuppsamples; samp++) + { + waveform.push_back(-1); + } + waveforms.push_back(waveform); + } + return Fun4AllReturnCodes::EVENT_OK; + } + if (m_dettype == CaloTowerDefs::CEMC) { adc_skip_mask = cdbttree->GetIntValue(pid, m_fieldname); @@ -398,7 +426,7 @@ int CaloTowerBuilder::process_data(PHCompositeNode *topNode, std::vectorset_pedestal(processed_waveforms.at(idx).at(2)); towerinfo->set_chi2(processed_waveforms.at(idx).at(3)); bool SZS = isSZS(processed_waveforms.at(idx).at(1), processed_waveforms.at(idx).at(3)); + if (processed_waveforms.at(idx).at(4) == 0) { towerinfo->set_isRecovered(false); @@ -484,10 +513,11 @@ int CaloTowerBuilder::process_event(PHCompositeNode *topNode) { towerinfo->set_isRecovered(true); } + towerinfo->set_FitStatus(static_cast(processed_waveforms.at(idx).at(5))); int n_samples = waveforms.at(idx).size(); if (n_samples == m_nzerosuppsamples || SZS) { - if (waveforms.at(idx).at(0) == 0) + if (waveforms.at(idx).at(0) == -1) { towerinfo->set_isNotInstr(true); } diff --git a/offline/packages/CaloReco/CaloTowerBuilder.h b/offline/packages/CaloReco/CaloTowerBuilder.h index cb22806903..c3b0bd2e8c 100644 --- a/offline/packages/CaloReco/CaloTowerBuilder.h +++ b/offline/packages/CaloReco/CaloTowerBuilder.h @@ -20,7 +20,7 @@ class TowerInfoContainerv3; class CaloTowerBuilder : public SubsysReco { - public: +public: explicit CaloTowerBuilder(const std::string &name = "CaloTowerBuilder"); ~CaloTowerBuilder() override; @@ -94,6 +94,26 @@ class CaloTowerBuilder : public SubsysReco m_dobitfliprecovery = dobitfliprecovery; } + // Functional fit options: 0 = PowerLawExp, 1 = PowerLawDoubleExp + void set_funcfit_type(int type) + { + m_funcfit_type = type; + } + + void set_powerlaw_params(double power, double decay) + { + m_powerlaw_power = power; + m_powerlaw_decay = decay; + } + + void set_doubleexp_params(double power, double peaktime1, double peaktime2, double ratio) + { + m_doubleexp_power = power; + m_doubleexp_peaktime1 = peaktime1; + m_doubleexp_peaktime2 = peaktime2; + m_doubleexp_ratio = ratio; + } + void set_tbt_softwarezerosuppression(const std::string &url) { m_zsURL = url; @@ -109,7 +129,7 @@ class CaloTowerBuilder : public SubsysReco CaloWaveformProcessing *get_WaveformProcessing() { return WaveformProcessing; } - private: +private: int process_sim(); bool skipChannel(int ich, int pid); static bool isSZS(float time, float chi2); @@ -150,6 +170,15 @@ class CaloTowerBuilder : public SubsysReco std::string m_directURL; std::string m_zsURL; std::string m_zs_fieldname{"zs_threshold"}; + + // Functional fit parameters + int m_funcfit_type{1}; // 0 = PowerLawExp, 1 = PowerLawDoubleExp + double m_powerlaw_power{4.0}; + double m_powerlaw_decay{1.5}; + double m_doubleexp_power{2.0}; + double m_doubleexp_peaktime1{5.0}; + double m_doubleexp_peaktime2{5.0}; + double m_doubleexp_ratio{0.3}; }; #endif // CALOTOWERBUILDER_H diff --git a/offline/packages/CaloReco/CaloTowerCalib.cc b/offline/packages/CaloReco/CaloTowerCalib.cc index cbd13ce4ed..ecc7da5157 100644 --- a/offline/packages/CaloReco/CaloTowerCalib.cc +++ b/offline/packages/CaloReco/CaloTowerCalib.cc @@ -114,6 +114,12 @@ int CaloTowerCalib::InitRun(PHCompositeNode *topNode) } else { + if (m_doAbortNoEnergyCalib) + { + std::cout << "CaloTowerCalib::InitRun: No energy calibration found for " << m_calibName << " and abort mode is set. Exiting." << std::endl; + gSystem->Exit(1); + } + calibdir = CDBInterface::instance()->getUrl(default_time_independent_calib); if (calibdir.empty()) @@ -151,6 +157,11 @@ int CaloTowerCalib::InitRun(PHCompositeNode *topNode) } else { + if (m_doAbortNoTimeCalib) + { + std::cout << "CaloTowerCalib::InitRun: No time calibration found for " << m_calibName_time << " and abort mode is set. Exiting." << std::endl; + gSystem->Exit(1); + } m_dotimecalib = false; if (Verbosity() > 0) { @@ -185,6 +196,11 @@ int CaloTowerCalib::InitRun(PHCompositeNode *topNode) } else { + if (m_doAbortNoZSCalib) + { + std::cout << "CaloTowerCalib::InitRun: No ZS cross calibration found for " << m_calibName_ZScrosscalib << " and abort mode is set. Exiting." << std::endl; + gSystem->Exit(1); + } m_doZScrosscalib = false; if (Verbosity() > 0) { diff --git a/offline/packages/CaloReco/CaloTowerCalib.h b/offline/packages/CaloReco/CaloTowerCalib.h index 06ae6148a1..10a3f2771f 100644 --- a/offline/packages/CaloReco/CaloTowerCalib.h +++ b/offline/packages/CaloReco/CaloTowerCalib.h @@ -92,6 +92,32 @@ class CaloTowerCalib : public SubsysReco } } + void set_doAbortNoEnergyCalib(bool doAbort = true) + { + m_doAbortNoEnergyCalib = doAbort; + return; + } + + void set_doAbortNoTimeCalib(bool doAbort = true) + { + m_doAbortNoTimeCalib = doAbort; + return; + } + + void set_doAbortNoZSCalib(bool doAbort = true) + { + m_doAbortNoZSCalib = doAbort; + return; + } + + void set_doAbortMissingCalib(bool doAbort = true) + { + m_doAbortNoEnergyCalib = doAbort; + m_doAbortNoTimeCalib = doAbort; + m_doAbortNoZSCalib = doAbort; + return; + } + void set_use_TowerInfov2(bool use) { m_use_TowerInfov2 = use; } private: @@ -125,6 +151,10 @@ class CaloTowerCalib : public SubsysReco std::string m_directURL_ZScrosscalib = ""; bool m_doZScrosscalib = true; + bool m_doAbortNoEnergyCalib{false}; + bool m_doAbortNoTimeCalib{false}; + bool m_doAbortNoZSCalib{false}; + CDBTTree *cdbttree = nullptr; CDBTTree *cdbttree_time = nullptr; CDBTTree *cdbttree_ZScrosscalib = nullptr; diff --git a/offline/packages/CaloReco/CaloTowerStatus.cc b/offline/packages/CaloReco/CaloTowerStatus.cc index c5401edb33..81013f9790 100644 --- a/offline/packages/CaloReco/CaloTowerStatus.cc +++ b/offline/packages/CaloReco/CaloTowerStatus.cc @@ -3,10 +3,6 @@ #include // for TowerInfo #include -#include -#include -#include -#include #include // for CDBTTree @@ -52,7 +48,6 @@ CaloTowerStatus::~CaloTowerStatus() std::cout << "CaloTowerStatus::~CaloTowerStatus() Calling dtor" << std::endl; } delete m_cdbttree_chi2; - delete m_cdbttree_time; delete m_cdbttree_hotMap; } @@ -105,6 +100,11 @@ int CaloTowerStatus::InitRun(PHCompositeNode *topNode) } else { + if (m_doAbortNoChi2) + { + std::cout << "CaloTowerStatus::InitRun: No chi2 calibration found for " << m_calibName_chi2 << " and abort mode is set. Exiting." << std::endl; + gSystem->Exit(1); + } m_doHotChi2 = false; if (Verbosity() > 0) { @@ -113,38 +113,8 @@ int CaloTowerStatus::InitRun(PHCompositeNode *topNode) } } - m_calibName_time = m_detector + "_meanTime"; - m_fieldname_time = "time"; - - calibdir = CDBInterface::instance()->getUrl(m_calibName_time); - if (!calibdir.empty()) - { - m_cdbttree_time = new CDBTTree(calibdir); - if (Verbosity() > 0) - { - std::cout << "CaloTowerStatus::InitRun Found " << m_calibName_time << " not Doing isBadTime" << std::endl; - } - } - else - { - if (use_directURL_time) - { - calibdir = m_directURL_time; - std::cout << "CaloTowerStatus::InitRun: Using default time " << calibdir << std::endl; - m_cdbttree_time = new CDBTTree(calibdir); - } - else - { - m_doTime = false; - if (Verbosity() > 1) - { - std::cout << "CaloTowerStatus::InitRun no timing info, " << m_calibName_time << " not found, not doing isBadTime" << std::endl; - } - } - } - m_calibName_hotMap = m_detector + "nome"; - if (m_dettype == CaloTowerDefs::CEMC) + if (m_dettype == CaloTowerDefs::CEMC || m_dettype == CaloTowerDefs::SEPD) { m_calibName_hotMap = m_detector + "_BadTowerMap"; } @@ -164,7 +134,7 @@ int CaloTowerStatus::InitRun(PHCompositeNode *topNode) { if (m_doAbortNoHotMap) { - std::cout << "CaloTowerStatus::InitRun: No hot map.. exiting" << std::endl; + std::cout << "CaloTowerStatus::InitRun: No hot map found for " << m_calibName_hotMap << " and abort mode is set. Exiting." << std::endl; gSystem->Exit(1); } if (use_directURL_hotMap) @@ -185,7 +155,7 @@ int CaloTowerStatus::InitRun(PHCompositeNode *topNode) if (Verbosity() > 0) { - std::cout << "CaloTowerStatus::Init " << m_detector << " doing time status =" << std::boolalpha << m_doTime << " doing hotBadChi2=" << std::boolalpha << m_doHotChi2 << " doing hot map=" << std::boolalpha << m_doHotMap << std::endl; + std::cout << "CaloTowerStatus::Init " << m_detector << " doing hotBadChi2=" << std::boolalpha << m_doHotChi2 << " doing hot map=" << std::boolalpha << m_doHotMap << std::endl; } PHNodeIterator iter(topNode); @@ -229,10 +199,6 @@ void CaloTowerStatus::LoadCalib() { m_cdbInfo_vec[channel].fraction_badChi2 = m_cdbttree_chi2->GetFloatValue(key, m_fieldname_chi2); } - if (m_doTime) - { - m_cdbInfo_vec[channel].mean_time = m_cdbttree_time->GetFloatValue(key, m_fieldname_time); - } if (m_doHotMap) { m_cdbInfo_vec[channel].hotMap_val = m_cdbttree_hotMap->GetIntValue(key, m_fieldname_hotMap); @@ -246,41 +212,30 @@ int CaloTowerStatus::process_event(PHCompositeNode * /*topNode*/) { unsigned int ntowers = m_raw_towers->size(); float fraction_badChi2 = 0; - float mean_time = 0; int hotMap_val = 0; float z_score = 0; for (unsigned int channel = 0; channel < ntowers; channel++) { // only reset what we will set m_raw_towers->get_tower_at_channel(channel)->set_isHot(false); - m_raw_towers->get_tower_at_channel(channel)->set_isBadTime(false); m_raw_towers->get_tower_at_channel(channel)->set_isBadChi2(false); if (m_doHotChi2) { fraction_badChi2 = m_cdbInfo_vec[channel].fraction_badChi2; } - if (m_doTime) - { - mean_time = m_cdbInfo_vec[channel].mean_time; - } if (m_doHotMap) { hotMap_val = m_cdbInfo_vec[channel].hotMap_val; z_score = m_cdbInfo_vec[channel].z_score; } float chi2 = m_raw_towers->get_tower_at_channel(channel)->get_chi2(); - float time = m_raw_towers->get_tower_at_channel(channel)->get_time(); float adc = m_raw_towers->get_tower_at_channel(channel)->get_energy(); if (fraction_badChi2 > fraction_badChi2_threshold && m_doHotChi2) { m_raw_towers->get_tower_at_channel(channel)->set_isHot(true); } - if (!m_raw_towers->get_tower_at_channel(channel)->get_isZS() && std::fabs(time - mean_time) > time_cut && m_doTime) - { - m_raw_towers->get_tower_at_channel(channel)->set_isBadTime(true); - } if (( hotMap_val == 1 || // dead std::fabs(z_score) > z_score_threshold || // hot or cold (hotMap_val == 3 && z_score >= -1 * z_score_threshold_default)) // cold part 2 @@ -299,6 +254,10 @@ int CaloTowerStatus::process_event(PHCompositeNode * /*topNode*/) void CaloTowerStatus::CreateNodeTree(PHCompositeNode *topNode) { std::string RawTowerNodeName = m_inputNodePrefix + m_detector; + if (!m_inputNode.empty()) + { + RawTowerNodeName = m_inputNode; + } m_raw_towers = findNode::getClass(topNode, RawTowerNodeName); if (!m_raw_towers) { diff --git a/offline/packages/CaloReco/CaloTowerStatus.h b/offline/packages/CaloReco/CaloTowerStatus.h index 8c6f20ecf6..1c50486281 100644 --- a/offline/packages/CaloReco/CaloTowerStatus.h +++ b/offline/packages/CaloReco/CaloTowerStatus.h @@ -38,6 +38,11 @@ class CaloTowerStatus : public SubsysReco m_inputNodePrefix = name; return; } + void set_inputNode(const std::string &name) + { + m_inputNode = name; + return; + } void set_badChi2_const_threshold(float threshold) { badChi2_treshold_const = threshold; @@ -63,23 +68,12 @@ class CaloTowerStatus : public SubsysReco z_score_threshold = threshold; return; } - void set_time_cut(float threshold) - { - time_cut = threshold; - return; - } void set_directURL_hotMap(const std::string &str) { m_directURL_hotMap = str; use_directURL_hotMap = true; return; } - void set_directURL_time(const std::string &str) - { - m_directURL_time = str; - use_directURL_time = true; - return; - } void set_directURL_chi2(const std::string &str) { m_directURL_chi2 = str; @@ -91,35 +85,42 @@ class CaloTowerStatus : public SubsysReco m_doAbortNoHotMap = status; return; } + void set_doAbortNoChi2(bool status = true) + { + m_doAbortNoChi2 = status; + return; + } + void set_doAbortMissingCalib(bool status = true) + { + m_doAbortNoHotMap = status; + m_doAbortNoChi2 = status; + return; + } private: TowerInfoContainer *m_raw_towers{nullptr}; CDBTTree *m_cdbttree_chi2{nullptr}; - CDBTTree *m_cdbttree_time{nullptr}; CDBTTree *m_cdbttree_hotMap{nullptr}; bool m_doHotChi2{true}; - bool m_doTime{true}; bool m_doHotMap{true}; bool m_doAbortNoHotMap{false}; + bool m_doAbortNoChi2{false}; CaloTowerDefs::DetectorSystem m_dettype{CaloTowerDefs::DETECTOR_INVALID}; std::string m_detector; - std::string m_fieldname_time; - std::string m_calibName_time; std::string m_fieldname_chi2; std::string m_calibName_chi2; std::string m_fieldname_hotMap; std::string m_fieldname_z_score; std::string m_calibName_hotMap; std::string m_inputNodePrefix{"TOWERS_"}; + std::string m_inputNode; - std::string m_directURL_time; std::string m_directURL_hotMap; std::string m_directURL_chi2; - bool use_directURL_time{false}; bool use_directURL_hotMap{false}; bool use_directURL_chi2{false}; @@ -129,14 +130,12 @@ class CaloTowerStatus : public SubsysReco float fraction_badChi2_threshold = {0.01}; float z_score_threshold = {5}; float z_score_threshold_default = {5}; - float time_cut = 2; // number of samples from the mean time for the channel in the run void LoadCalib(); struct CDBInfo { float fraction_badChi2{0}; - float mean_time{0}; float z_score{0}; int hotMap_val{0}; }; diff --git a/offline/packages/CaloReco/CaloWaveformFitting.cc b/offline/packages/CaloReco/CaloWaveformFitting.cc index f5163275a0..341860c754 100644 --- a/offline/packages/CaloReco/CaloWaveformFitting.cc +++ b/offline/packages/CaloReco/CaloWaveformFitting.cc @@ -2,8 +2,10 @@ #include #include +#include #include #include +#include #include #include @@ -21,7 +23,7 @@ #include #include -static ROOT::TThreadExecutor *t = new ROOT::TThreadExecutor(1);// NOLINT(misc-use-anonymous-namespace) +static ROOT::TThreadExecutor *t = new ROOT::TThreadExecutor(1); // NOLINT(misc-use-anonymous-namespace) double CaloWaveformFitting::template_function(double *x, double *par) { Double_t v1 = (par[0] * h_template->Interpolate(x[0] - par[1])) + par[2]; @@ -77,6 +79,7 @@ std::vector> CaloWaveformFitting::calo_processing_templatefit v.push_back(std::numeric_limits::quiet_NaN()); } v.push_back(0); + v.push_back(0); } else { @@ -118,6 +121,7 @@ std::vector> CaloWaveformFitting::calo_processing_templatefit v.push_back(std::numeric_limits::quiet_NaN()); } v.push_back(0); + v.push_back(0); } else { @@ -164,16 +168,17 @@ std::vector> CaloWaveformFitting::calo_processing_templatefit } fitter->FitFCN(*EPChi2, nullptr, data.Size(), true); ROOT::Fit::FitResult fitres = fitter->Result(); - // get the result status + // get the fit status code (0 means successful fit) + int validfit = fitres.Status(); /* - bool validfit = fitres.IsValid(); - if(!validfit) + if(validfit != 0) { - std::cout<<"invalid fit"<> CaloWaveformFitting::calo_processing_templatefit recoverFitter->Config().ParSettings(1).SetLimits(-1 * m_peakTimeTemp, size1 - m_peakTimeTemp); // set lim on time par recoverFitter->FitFCN(*recoverEPChi2, nullptr, recoverData.Size(), true); ROOT::Fit::FitResult recover_fitres = recoverFitter->Result(); + int recover_validfit = recover_fitres.Status(); double recover_chi2min = recover_fitres.MinFcnValue(); recover_chi2min /= size1 - 3; // divide by the number of dof if (recover_chi2min < _chi2lowthreshold && recover_f->GetParameter(2) < _bfr_highpedestalthreshold && recover_f->GetParameter(2) > _bfr_lowpedestalthreshold) @@ -253,6 +259,7 @@ std::vector> CaloWaveformFitting::calo_processing_templatefit } v.push_back(recover_chi2min); v.push_back(1); + v.push_back(recover_validfit); } else { @@ -262,6 +269,7 @@ std::vector> CaloWaveformFitting::calo_processing_templatefit } v.push_back(chi2min); v.push_back(0); + v.push_back(validfit); } recover_f->Delete(); delete recoverFitFunction; @@ -276,6 +284,7 @@ std::vector> CaloWaveformFitting::calo_processing_templatefit } v.push_back(chi2min); v.push_back(0); + v.push_back(validfit); } h->Delete(); f->Delete(); @@ -294,7 +303,7 @@ std::vector> CaloWaveformFitting::calo_processing_templatefit { const std::vector &tv = chnlvector.at(i); int size2 = tv.size(); - for (int q = 5; q > 0; q--) + for (int q = 6; q > 0; q--) { fit_params_tmp.push_back(tv.at(size2 - q)); } @@ -433,7 +442,7 @@ std::vector> CaloWaveformFitting::calo_processing_fast(const } } amp -= ped; - std::vector val = {amp, time, ped, chi2, 0}; + std::vector val = {amp, time, ped, chi2, 0, 0}; fit_values.push_back(val); val.clear(); } @@ -456,7 +465,7 @@ std::vector> CaloWaveformFitting::calo_processing_nyquist(con { chi2 = 1000000; } - fit_values.push_back({v.at(1) - v.at(0), std::numeric_limits::quiet_NaN(), v.at(0), chi2, 0}); + fit_values.push_back({v.at(1) - v.at(0), std::numeric_limits::quiet_NaN(), v.at(0), chi2, 0, 0}); continue; } @@ -531,7 +540,7 @@ std::vector CaloWaveformFitting::NyquistInterpolation(std::vector float diff = vec_signal_samples[i] - template_function(xval, par); chi2 += diff * diff; } - std::vector val = {max - pedestal, maxpos, pedestal, chi2, 0}; + std::vector val = {max - pedestal, maxpos, pedestal, chi2, 0, 0}; return val; } @@ -619,3 +628,331 @@ float CaloWaveformFitting::psinc(float time, std::vector &vec_signal_samp return sum; } + +double CaloWaveformFitting::SignalShape_PowerLawExp(double *x, double *par) +{ + // par[0]: Amplitude + // par[1]: Sample Start (t0) + // par[2]: Power + // par[3]: Decay + // par[4]: Pedestal + double pedestal = par[4]; + if (x[0] < par[1]) + { + return pedestal; + } + double signal = par[0] * pow((x[0] - par[1]), par[2]) * exp(-(x[0] - par[1]) * par[3]); + return pedestal + signal; +} + +double CaloWaveformFitting::SignalShape_PowerLawDoubleExp(double *x, double *par) +{ + // par[0]: Amplitude + // par[1]: Sample Start (t0) + // par[2]: Power + // par[3]: Peak Time 1 + // par[4]: Pedestal + // par[5]: Amplitude ratio + // par[6]: Peak Time 2 + double pedestal = par[4]; + if (x[0] < par[1]) + { + return pedestal; + } + double signal = par[0] * pow((x[0] - par[1]), par[2]) * + (((1.0 - par[5]) / pow(par[3], par[2]) * exp(par[2])) * + exp(-(x[0] - par[1]) * (par[2] / par[3])) + + (par[5] / pow(par[6], par[2]) * exp(par[2])) * + exp(-(x[0] - par[1]) * (par[2] / par[6]))); + return pedestal + signal; +} + +// chp: needs to be verified, but I can vaguely recall that making the args const fails in root +double CaloWaveformFitting::SignalShape_FermiExp(double *x, double *par) //NOLINT(readability-non-const-parameter) +{ + // par[0]: Amplitude + // par[1]: Midpoint (t0) + // par[2]: Rise width (w) + // par[3]: Decay time (tau) + // par[4]: Pedestal + + double tt = x[0]; + double A = par[0]; + double t0 = par[1]; + double w = par[2]; + double tau = par[3]; + double ped = par[4]; + + if (w <= 0 || tau <= 0) + { + return ped; + } + + double fermi = 1.0 / (1.0 + exp(-(tt - t0) / w)); + + double expo = exp(-(tt - t0) / tau); + + if (tt < t0) + { + expo = 1.0; + } + + double signal = A * fermi * expo; + + return ped + signal; +} + + +std::vector> CaloWaveformFitting::calo_processing_funcfit(const std::vector> &chnlvector) +{ + std::vector> fit_values; + int nchnls = chnlvector.size(); + + for (int m = 0; m < nchnls; m++) + { + const std::vector &v = chnlvector.at(m); + int nsamples = v.size(); + + float amp = 0; + float time = 0; + float ped = 0; + float chi2 = std::numeric_limits::quiet_NaN(); + + // Handle zero-suppressed samples (2-sample case) + if (nsamples == _nzerosuppresssamples) + { + amp = v.at(1) - v.at(0); + time = std::numeric_limits::quiet_NaN(); + ped = v.at(0); + if (v.at(0) != 0 && v.at(1) == 0) + { + chi2 = 1000000; + } + fit_values.push_back({amp, time, ped, chi2, 0, 0}); + continue; + } + + // Find peak position and estimate pedestal + float maxheight = 0; + int maxbin = 0; + for (int i = 0; i < nsamples; i++) + { + if (v.at(i) > maxheight) + { + maxheight = v.at(i); + maxbin = i; + } + } + + float pedestal = 1500; + if (maxbin > 4) + { + pedestal = 0.5 * (v.at(maxbin - 4) + v.at(maxbin - 5)); + } + else if (maxbin > 3) + { + pedestal = v.at(maxbin - 4); + } + else + { + pedestal = 0.5 * (v.at(nsamples - 3) + v.at(nsamples - 2)); + } + + // Software zero suppression check + if ((_bdosoftwarezerosuppression && v.at(6) - v.at(0) < _nsoftwarezerosuppression) || + (_maxsoftwarezerosuppression && maxheight - pedestal < _nsoftwarezerosuppression)) + { + amp = v.at(6) - v.at(0); + time = std::numeric_limits::quiet_NaN(); + ped = v.at(0); + if (v.at(0) != 0 && v.at(1) == 0) + { + chi2 = 1000000; + } + fit_values.push_back({amp, time, ped, chi2, 0, 0}); + continue; + } + + // Create histogram for fitting + TH1F h("h_funcfit", "", nsamples, -0.5, nsamples - 0.5); + int ndata = 0; + for (int i = 0; i < nsamples; ++i) + { + if ((v.at(i) == 16383) && _handleSaturation) + { + continue; + } + h.SetBinContent(i + 1, v.at(i)); + h.SetBinError(i + 1, 1); + ndata++; + } + + // If too many saturated, use all data + if (ndata < (nsamples - 4)) + { + ndata = nsamples; + for (int i = 0; i < nsamples; ++i) + { + h.SetBinContent(i + 1, v.at(i)); + h.SetBinError(i + 1, 1); + } + } + + double fit_amp = 0; + double fit_time = 0; + double fit_ped = 0; + double chi2val = 0; + int validfit = 0; + int npar = 0; + + if (m_funcfit_type == POWERLAWEXP) + { + // Create fit function with 5 parameters + TF1 f("f_powerlaw", SignalShape_PowerLawExp, 0, nsamples, 5); + npar = 5; + + // Set initial parameters + double risetime = m_powerlaw_power / m_powerlaw_decay; + double par[5]; + par[0] = maxheight - pedestal; // Amplitude + par[1] = maxbin - risetime; // t0 + par[1] = std::max(par[1], 0); + par[2] = m_powerlaw_power; // Power + par[3] = m_powerlaw_decay; // Decay + par[4] = pedestal; // Pedestal + + f.SetParameters(par); + f.SetParLimits(0, (maxheight - pedestal) * 0.5, (maxheight - pedestal) * 10); + f.SetParLimits(1, 0, nsamples); + f.SetParLimits(2, 0, 10.0); + f.SetParLimits(3, 0, 10.0); + f.SetParLimits(4, pedestal - std::abs(maxheight - pedestal), pedestal + std::abs(maxheight - pedestal)); + + // Perform fit + TFitResultPtr fitres = h.Fit(&f, "SQRN0W", "", 0, nsamples); + + // Calculate peak amplitude and time from fit parameters + // Peak height is (p0 * Power(p2/p3, p2)) / exp(p2) + fit_amp = (f.GetParameter(0) * pow(f.GetParameter(2) / f.GetParameter(3), f.GetParameter(2))) / exp(f.GetParameter(2)); + // Peak time is t0 + power/decay + fit_time = f.GetParameter(1) + f.GetParameter(2) / f.GetParameter(3); + fit_ped = f.GetParameter(4); + + // Calculate chi2 + for (int i = 0; i < nsamples; i++) + { + if (h.GetBinContent(i + 1) > 0) + { + double diff = h.GetBinContent(i + 1) - f.Eval(i); + chi2val += diff * diff; + } + } + if (fitres.Get()) { validfit = fitres.Get()->Status(); } + } + else if(m_funcfit_type == POWERLAWDOUBLEEXP) + { + // Create fit function with 7 parameters + TF1 f("f_doubleexp", SignalShape_PowerLawDoubleExp, 0, nsamples, 7); + npar = 7; + + // Set initial parameters + double risetime = 2.0; + double par[7]; + par[0] = (maxheight - pedestal) * 0.7; // Amplitude + par[1] = maxbin - risetime; // t0 + par[1] = std::max(par[1], 0); + par[2] = m_doubleexp_power; // Power + par[3] = m_doubleexp_peaktime1; // Peak Time 1 + par[4] = pedestal; // Pedestal + par[5] = m_doubleexp_ratio; // Amplitude ratio + par[6] = m_doubleexp_peaktime2; // Peak Time 2 + + f.SetParameters(par); + f.SetParLimits(0, (maxheight - pedestal) * -1.5, (maxheight - pedestal) * 1.5); + f.SetParLimits(1, maxbin - 3 * risetime, maxbin + risetime); + f.SetParLimits(2, 1, 5.0); + f.SetParLimits(3, risetime * 0.5, risetime * 4); + f.SetParLimits(4, pedestal - std::abs(maxheight - pedestal), pedestal + std::abs(maxheight - pedestal)); + f.SetParLimits(5, 0, 1); + f.SetParLimits(6, risetime * 0.5, risetime * 4); + + // Perform fit + TFitResultPtr fitres = h.Fit(&f, "SQRN0W", "", 0, nsamples); + + // Find peak by evaluating the function + double peakpos1 = f.GetParameter(3); + double peakpos2 = f.GetParameter(6); + double max_peakpos = f.GetParameter(1) + (peakpos1 > peakpos2 ? peakpos1 : peakpos2); + max_peakpos = std::min(max_peakpos, nsamples - 1); + + fit_time = f.GetMaximumX(f.GetParameter(1), max_peakpos); + fit_amp = f.Eval(fit_time) - f.GetParameter(4); + fit_ped = f.GetParameter(4); + + // Calculate chi2 + for (int i = 0; i < nsamples; i++) + { + if (h.GetBinContent(i + 1) > 0) + { + double diff = h.GetBinContent(i + 1) - f.Eval(i); + chi2val += diff * diff; + } + } + if (fitres.Get()) { validfit = fitres.Get()->Status(); } + } + else if(m_funcfit_type == FERMIEXP) + { + TF1 f("f_fermiexp", SignalShape_FermiExp, 0, nsamples, 5); + npar = 5; + + // Set initial parameters + double par[5]; + par[0] = maxheight - pedestal; // Amplitude + par[1] = maxbin ; // t0 + par[2] = 1.0; // width + par[3] = 2.0; // Peak Time 1 + par[4] = pedestal; // Pedestal + + f.SetParameters(par); + f.SetParLimits(0, maxheight-pedestal, 3*(maxheight-pedestal)); + f.SetParLimits(1, maxbin-1, maxbin); + f.SetParLimits(2, 0.025, 2.0); + f.SetParLimits(3, 0.5, 4.0); + f.SetParLimits(4, pedestal-500, pedestal+500); + + f.FixParameter(2, 0.1); + + TFitResultPtr fitres = h.Fit(&f, "SQRN0W", "", 0, nsamples); + + fit_time = f.GetParameter(1); + fit_amp = f.GetParameter(0); + fit_ped = f.GetParameter(4); + + // Calculate chi2 + for (int i = 0; i < nsamples; i++) + { + if (h.GetBinContent(i + 1) > 0) + { + double diff = h.GetBinContent(i + 1) - f.Eval(i); + chi2val += diff * diff; + } + } + if (fitres.Get()) { validfit = fitres.Get()->Status(); } + } + + int ndf = ndata - npar; + if (ndf > 0) + { + chi2val /= ndf; + } + else + { + chi2val = std::numeric_limits::quiet_NaN(); + } + + fit_values.push_back({static_cast(fit_amp), static_cast(fit_time), + static_cast(fit_ped), static_cast(chi2val), 0, static_cast(validfit)}); + } + + return fit_values; +} diff --git a/offline/packages/CaloReco/CaloWaveformFitting.h b/offline/packages/CaloReco/CaloWaveformFitting.h index 1a9f887305..1064dcd68e 100644 --- a/offline/packages/CaloReco/CaloWaveformFitting.h +++ b/offline/packages/CaloReco/CaloWaveformFitting.h @@ -9,6 +9,13 @@ class TProfile; class CaloWaveformFitting { public: + enum FuncFitType + { + POWERLAWEXP = 0, + POWERLAWDOUBLEEXP = 1, + FERMIEXP = 2, + }; + CaloWaveformFitting() = default; ~CaloWaveformFitting(); @@ -61,9 +68,35 @@ class CaloWaveformFitting std::vector> calo_processing_templatefit(std::vector> chnlvector); static std::vector> calo_processing_fast(const std::vector> &chnlvector); std::vector> calo_processing_nyquist(const std::vector> &chnlvector); + std::vector> calo_processing_funcfit(const std::vector> &chnlvector); void initialize_processing(const std::string &templatefile); + // Power-law fit function: amplitude * (x-t0)^power * exp(-(x-t0)*decay) + pedestal + static double SignalShape_PowerLawExp(double *x, double *par); + // Double exponential power-law fit function + static double SignalShape_PowerLawDoubleExp(double *x, double *par); + static double SignalShape_FermiExp(double *x, double *par); + + void set_funcfit_type(FuncFitType type) + { + m_funcfit_type = type; + } + + void set_powerlaw_params(double power, double decay) + { + m_powerlaw_power = power; + m_powerlaw_decay = decay; + } + + void set_doubleexp_params(double power, double peaktime1, double peaktime2, double ratio) + { + m_doubleexp_power = power; + m_doubleexp_peaktime1 = peaktime1; + m_doubleexp_peaktime2 = peaktime2; + m_doubleexp_ratio = ratio; + } + private: static void FastMax(float x0, float x1, float x2, float y0, float y1, float y2, float &xmax, float &ymax); std::vector NyquistInterpolation(std::vector &vec_signal_samples); @@ -97,5 +130,18 @@ class CaloWaveformFitting std::string url_template; std::string url_onnx; std::string m_model_name; + + // Functional fit type selector + FuncFitType m_funcfit_type{POWERLAWDOUBLEEXP}; + + // Power-law fit parameters + double m_powerlaw_power{4.0}; + double m_powerlaw_decay{1.5}; + + // Double exponential fit parameters + double m_doubleexp_power{2.0}; + double m_doubleexp_peaktime1{5.0}; + double m_doubleexp_peaktime2{5.0}; + double m_doubleexp_ratio{0.3}; }; #endif diff --git a/offline/packages/CaloReco/CaloWaveformProcessing.cc b/offline/packages/CaloReco/CaloWaveformProcessing.cc index 4e51f71f45..ad4993aca4 100644 --- a/offline/packages/CaloReco/CaloWaveformProcessing.cc +++ b/offline/packages/CaloReco/CaloWaveformProcessing.cc @@ -65,6 +65,19 @@ void CaloWaveformProcessing::initialize_processing() m_Fitter = new CaloWaveformFitting(); m_Fitter->initialize_processing(url_template); } + else if (m_processingtype == CaloWaveformProcessing::FUNCFIT) + { + m_Fitter = new CaloWaveformFitting(); + // Set functional fit type and parameters + m_Fitter->set_funcfit_type(static_cast(_funcfit_type)); + m_Fitter->set_powerlaw_params(_powerlaw_power, _powerlaw_decay); + m_Fitter->set_doubleexp_params(_doubleexp_power, _doubleexp_peaktime1, _doubleexp_peaktime2, _doubleexp_ratio); + if (_bdosoftwarezerosuppression) + { + m_Fitter->set_softwarezerosuppression(_bdosoftwarezerosuppression, _nsoftwarezerosuppression); + } + m_Fitter->set_handleSaturation(true); + } } std::vector> CaloWaveformProcessing::process_waveform(std::vector> waveformvector) @@ -91,6 +104,10 @@ std::vector> CaloWaveformProcessing::process_waveform(std::ve { fitresults = m_Fitter->calo_processing_nyquist(waveformvector); } + if (m_processingtype == CaloWaveformProcessing::FUNCFIT) + { + fitresults = m_Fitter->calo_processing_funcfit(waveformvector); + } return fitresults; } @@ -118,6 +135,7 @@ std::vector> CaloWaveformProcessing::calo_processing_ONNX(con val.push_back(std::numeric_limits::quiet_NaN()); } val.push_back(0); + val.push_back(0); fit_values.push_back(val); } else @@ -160,6 +178,7 @@ std::vector> CaloWaveformProcessing::calo_processing_ONNX(con val.push_back(std::numeric_limits::quiet_NaN()); } val.push_back(0); + val.push_back(0); fit_values.push_back(val); } else @@ -169,7 +188,7 @@ std::vector> CaloWaveformProcessing::calo_processing_ONNX(con { // downstream onnx does not have a static input vector API, // so we need to make a copy - std::vector vtmp(v); //NOLINT(performance-unnecessary-copy-initialization) + std::vector vtmp(v); // NOLINT(performance-unnecessary-copy-initialization) val = onnxInference(onnxmodule, vtmp, 1, onnxlib::n_input, onnxlib::n_output); unsigned int nvals = val.size(); for (unsigned int i = 0; i < nvals; i++) @@ -178,12 +197,13 @@ std::vector> CaloWaveformProcessing::calo_processing_ONNX(con } val.push_back(2000); val.push_back(0); + val.push_back(0); fit_values.push_back(val); } else { float v_diff = v[1] - v[0]; - std::vector val1{v_diff, std::numeric_limits::quiet_NaN(), v[1], std::numeric_limits::quiet_NaN(), 0}; + std::vector val1{v_diff, std::numeric_limits::quiet_NaN(), v[1], std::numeric_limits::quiet_NaN(), 0, 0}; fit_values.push_back(val1); } } diff --git a/offline/packages/CaloReco/CaloWaveformProcessing.h b/offline/packages/CaloReco/CaloWaveformProcessing.h index 8a5a5bbbe6..b657459d6c 100644 --- a/offline/packages/CaloReco/CaloWaveformProcessing.h +++ b/offline/packages/CaloReco/CaloWaveformProcessing.h @@ -20,6 +20,7 @@ class CaloWaveformProcessing : public SubsysReco FAST = 3, NYQUIST = 4, TEMPLATE_NOSAT = 5, + FUNCFIT = 6, }; CaloWaveformProcessing() = default; @@ -75,6 +76,26 @@ class CaloWaveformProcessing : public SubsysReco _dobitfliprecovery = dobitfliprecovery; } + // Functional fit options: 0 = PowerLawExp, 1 = PowerLawDoubleExp + void set_funcfit_type(int type) + { + _funcfit_type = type; + } + + void set_powerlaw_params(double power, double decay) + { + _powerlaw_power = power; + _powerlaw_decay = decay; + } + + void set_doubleexp_params(double power, double peaktime1, double peaktime2, double ratio) + { + _doubleexp_power = power; + _doubleexp_peaktime1 = peaktime1; + _doubleexp_peaktime2 = peaktime2; + _doubleexp_ratio = ratio; + } + std::vector> process_waveform(std::vector> waveformvector); std::vector> calo_processing_ONNX(const std::vector> &chnlvector); @@ -108,6 +129,15 @@ class CaloWaveformProcessing : public SubsysReco std::string m_model_name{"CEMC_ONNX"}; std::array m_Onnx_factor{std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; std::array m_Onnx_offset{std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; + + // Functional fit parameters + int _funcfit_type{1}; // 0 = PowerLawExp, 1 = PowerLawDoubleExp + double _powerlaw_power{4.0}; + double _powerlaw_decay{1.5}; + double _doubleexp_power{2.0}; + double _doubleexp_peaktime1{5.0}; + double _doubleexp_peaktime2{5.0}; + double _doubleexp_ratio{0.3}; }; #endif diff --git a/offline/packages/CaloReco/PhotonClusterBuilder.cc b/offline/packages/CaloReco/PhotonClusterBuilder.cc index 263ae04ef0..8171c2cbce 100644 --- a/offline/packages/CaloReco/PhotonClusterBuilder.cc +++ b/offline/packages/CaloReco/PhotonClusterBuilder.cc @@ -117,6 +117,19 @@ int PhotonClusterBuilder::InitRun(PHCompositeNode* topNode) return Fun4AllReturnCodes::ABORTRUN; } + if (m_do_subtracted_iso) + { + m_emc_sub1_tower_container = findNode::getClass(topNode, "TOWERINFO_CALIB_CEMC_RETOWER_SUB1"); + m_ihcal_sub1_tower_container = findNode::getClass(topNode, "TOWERINFO_CALIB_HCALIN_SUB1"); + m_ohcal_sub1_tower_container = findNode::getClass(topNode, "TOWERINFO_CALIB_HCALOUT_SUB1"); + + if (!m_emc_sub1_tower_container || !m_ihcal_sub1_tower_container || !m_ohcal_sub1_tower_container) + { + std::cout << Name() << ": subtracted isolation enabled but one or more SUB1 tower nodes are missing; " + << "iso_sub_* values will remain at " << m_subtracted_iso_defval << std::endl; + } + } + CreateNodes(topNode); return Fun4AllReturnCodes::EVENT_OK; } @@ -323,7 +336,7 @@ void PhotonClusterBuilder::calculate_shower_shapes(RawCluster* rc, PhotonCluster nsaturated++; } } - + int totalphibins = 256; auto dphiwrap = [totalphibins](int towerphi, int maxiphi_arg) { @@ -435,7 +448,7 @@ void PhotonClusterBuilder::calculate_shower_shapes(RawCluster* rc, PhotonCluster float e72 = 0; float detacog = std::abs(maxieta - avg_eta); float dphicog = std::abs(maxiphi - avg_phi); - float drad = std::sqrt(dphicog*dphicog + detacog*detacog); + float drad = std::sqrt(dphicog * dphicog + detacog * detacog); int signphi = (avg_phi - std::floor(avg_phi)) > 0.5 ? 1 : -1; @@ -566,6 +579,7 @@ void PhotonClusterBuilder::calculate_shower_shapes(RawCluster* rc, PhotonCluster photon->set_shower_shape_parameter("et3", showershape[2]); photon->set_shower_shape_parameter("et4", showershape[3]); photon->set_shower_shape_parameter("e11", e11); + photon->set_shower_shape_parameter("e22", showershape[8] + showershape[9] + showershape[10] + showershape[11]); photon->set_shower_shape_parameter("e33", e33); photon->set_shower_shape_parameter("e55", e55); photon->set_shower_shape_parameter("e77", e77); @@ -766,6 +780,41 @@ void PhotonClusterBuilder::calculate_shower_shapes(RawCluster* rc, PhotonCluster photon->set_shower_shape_parameter("iso_02_emcal", emcal_et_02 - ET); photon->set_shower_shape_parameter("iso_01_emcal", emcal_et_01 - ET); photon->set_shower_shape_parameter("iso_005_emcal", emcal_et_005 - ET); + + photon->set_shower_shape_parameter("iso_sub_04_emcal", m_subtracted_iso_defval); + photon->set_shower_shape_parameter("iso_sub_04_hcalin", m_subtracted_iso_defval); + photon->set_shower_shape_parameter("iso_sub_04_hcalout", m_subtracted_iso_defval); + photon->set_shower_shape_parameter("iso_sub_03_emcal", m_subtracted_iso_defval); + photon->set_shower_shape_parameter("iso_sub_03_hcalin", m_subtracted_iso_defval); + photon->set_shower_shape_parameter("iso_sub_03_hcalout", m_subtracted_iso_defval); + photon->set_shower_shape_parameter("iso_sub_02_emcal", m_subtracted_iso_defval); + photon->set_shower_shape_parameter("iso_sub_01_emcal", m_subtracted_iso_defval); + photon->set_shower_shape_parameter("iso_sub_005_emcal", m_subtracted_iso_defval); + + if (m_do_subtracted_iso && m_emc_sub1_tower_container && m_ihcal_sub1_tower_container && m_ohcal_sub1_tower_container) + { + const float sub_emcal_et_04 = calculate_layer_et(cluster_eta, cluster_phi, 0.4, m_emc_sub1_tower_container, m_geomIH, RawTowerDefs::CalorimeterId::HCALIN, m_vertex); + const float sub_ihcal_et_04 = calculate_layer_et(cluster_eta, cluster_phi, 0.4, m_ihcal_sub1_tower_container, m_geomIH, RawTowerDefs::CalorimeterId::HCALIN, m_vertex); + const float sub_ohcal_et_04 = calculate_layer_et(cluster_eta, cluster_phi, 0.4, m_ohcal_sub1_tower_container, m_geomOH, RawTowerDefs::CalorimeterId::HCALOUT, m_vertex); + + const float sub_emcal_et_03 = calculate_layer_et(cluster_eta, cluster_phi, 0.3, m_emc_sub1_tower_container, m_geomIH, RawTowerDefs::CalorimeterId::HCALIN, m_vertex); + const float sub_ihcal_et_03 = calculate_layer_et(cluster_eta, cluster_phi, 0.3, m_ihcal_sub1_tower_container, m_geomIH, RawTowerDefs::CalorimeterId::HCALIN, m_vertex); + const float sub_ohcal_et_03 = calculate_layer_et(cluster_eta, cluster_phi, 0.3, m_ohcal_sub1_tower_container, m_geomOH, RawTowerDefs::CalorimeterId::HCALOUT, m_vertex); + + const float sub_emcal_et_02 = calculate_layer_et(cluster_eta, cluster_phi, 0.2, m_emc_sub1_tower_container, m_geomIH, RawTowerDefs::CalorimeterId::HCALIN, m_vertex); + const float sub_emcal_et_01 = calculate_layer_et(cluster_eta, cluster_phi, 0.1, m_emc_sub1_tower_container, m_geomIH, RawTowerDefs::CalorimeterId::HCALIN, m_vertex); + const float sub_emcal_et_005 = calculate_layer_et(cluster_eta, cluster_phi, 0.05, m_emc_sub1_tower_container, m_geomIH, RawTowerDefs::CalorimeterId::HCALIN, m_vertex); + + photon->set_shower_shape_parameter("iso_sub_04_emcal", sub_emcal_et_04 - ET); + photon->set_shower_shape_parameter("iso_sub_04_hcalin", sub_ihcal_et_04); + photon->set_shower_shape_parameter("iso_sub_04_hcalout", sub_ohcal_et_04); + photon->set_shower_shape_parameter("iso_sub_03_emcal", sub_emcal_et_03 - ET); + photon->set_shower_shape_parameter("iso_sub_03_hcalin", sub_ihcal_et_03); + photon->set_shower_shape_parameter("iso_sub_03_hcalout", sub_ohcal_et_03); + photon->set_shower_shape_parameter("iso_sub_02_emcal", sub_emcal_et_02 - ET); + photon->set_shower_shape_parameter("iso_sub_01_emcal", sub_emcal_et_01 - ET); + photon->set_shower_shape_parameter("iso_sub_005_emcal", sub_emcal_et_005 - ET); + } } double PhotonClusterBuilder::getTowerEta(RawTowerGeom* tower_geom, double vx, double vy, double vz) diff --git a/offline/packages/CaloReco/PhotonClusterBuilder.h b/offline/packages/CaloReco/PhotonClusterBuilder.h index 1c987f9849..b9a9baed50 100644 --- a/offline/packages/CaloReco/PhotonClusterBuilder.h +++ b/offline/packages/CaloReco/PhotonClusterBuilder.h @@ -42,6 +42,7 @@ class PhotonClusterBuilder : public SubsysReco void set_bdt_model_file(const std::string& path) { m_bdt_model_file = path; } void set_bdt_feature_list(const std::vector& features) { m_bdt_feature_list = features; } void set_do_bdt(bool do_bdt) { m_do_bdt = do_bdt; } + void set_do_subtracted_iso(bool do_subtracted_iso) { m_do_subtracted_iso = do_subtracted_iso; } const std::vector& get_bdt_feature_list() const { return m_bdt_feature_list; } private: @@ -53,6 +54,7 @@ class PhotonClusterBuilder : public SubsysReco double deltaR(double eta1, double phi1, double eta2, double phi2); float calculate_layer_et(float seed_eta, float seed_phi, float radius, TowerInfoContainer* towerContainer, RawTowerGeomContainer* geomContainer, RawTowerDefs::CalorimeterId calo_id, float vertex_z); bool m_do_bdt{false}; + bool m_do_subtracted_iso{false}; std::string m_input_cluster_node{"CLUSTERINFO_CEMC"}; std::string m_output_photon_node{"PHOTONCLUSTER_CEMC"}; @@ -61,6 +63,7 @@ class PhotonClusterBuilder : public SubsysReco std::string m_bdt_model_file{"myBDT_5.root"}; std::vector m_bdt_feature_list; float m_vertex{std::numeric_limits::quiet_NaN()}; + float m_subtracted_iso_defval{-999}; RawClusterContainer* m_rawclusters{nullptr}; RawClusterContainer* m_photon_container{nullptr}; @@ -70,6 +73,9 @@ class PhotonClusterBuilder : public SubsysReco RawTowerGeomContainer* m_geomIH{nullptr}; TowerInfoContainer* m_ohcal_tower_container{nullptr}; RawTowerGeomContainer* m_geomOH{nullptr}; + TowerInfoContainer* m_emc_sub1_tower_container{nullptr}; + TowerInfoContainer* m_ihcal_sub1_tower_container{nullptr}; + TowerInfoContainer* m_ohcal_sub1_tower_container{nullptr}; std::unique_ptr m_bdt; }; diff --git a/offline/packages/HFTrackEfficiency/HFTrackEfficiency.cc b/offline/packages/HFTrackEfficiency/HFTrackEfficiency.cc index 01975c66f4..09de461fe9 100644 --- a/offline/packages/HFTrackEfficiency/HFTrackEfficiency.cc +++ b/offline/packages/HFTrackEfficiency/HFTrackEfficiency.cc @@ -38,6 +38,7 @@ #include #include + //____________________________________________________________________________.. HFTrackEfficiency::HFTrackEfficiency(const std::string &name) : SubsysReco(name) @@ -213,20 +214,33 @@ bool HFTrackEfficiency::findTracks(PHCompositeNode *topNode, Decay decay) m_true_mother_pT = mother->momentum().perp(); m_true_mother_p = std::sqrt(std::pow(mother->momentum().px(), 2) + std::pow(mother->momentum().py(), 2) + std::pow(mother->momentum().pz(), 2)); // Must have an old HepMC build, no mag function m_true_mother_eta = mother->momentum().eta(); + m_true_mother_phi = mother->momentum().phi(); HepMC::GenVertex *thisVtx = mother->production_vertex(); m_primary_vtx_x = thisVtx->point3d().x(); m_primary_vtx_y = thisVtx->point3d().y(); m_primary_vtx_z = thisVtx->point3d().z(); + + constexpr float epsilon = 1e-6F; + if (std::abs(m_primary_vtx_x) < epsilon && + std::abs(m_primary_vtx_y) < epsilon && + std::abs(m_primary_vtx_z) < epsilon) + { + m_is_primary = true; + } } + int index = -1; + for (unsigned int i = 1; i < decay.size(); ++i) { m_dst_track = nullptr; int truth_ID = -1; + if (std::find(std::begin(trackableParticles), std::end(trackableParticles), std::abs(decay[i].second)) != std::end(trackableParticles)) { + ++index; if (theEvent && decay[i].first.second > -1) { HepMC::GenParticle *daughterHepMC = theEvent->barcode_to_particle(decay[i].first.second); @@ -238,7 +252,7 @@ bool HFTrackEfficiency::findTracks(PHCompositeNode *topNode, Decay decay) daughterTrueLV->setVectM(CLHEP::Hep3Vector(daughterHepMC->momentum().px(), daughterHepMC->momentum().py(), daughterHepMC->momentum().pz()), getParticleMass(decay[i].second)); daughterSumTrueLV += *daughterTrueLV; - m_true_track_PID[i - 1] = daughterHepMC->pdg_id(); + m_true_track_PID[index] = daughterHepMC->pdg_id(); // Now get the decay vertex position HepMC::GenVertex *thisVtx = daughterHepMC->production_vertex(); @@ -290,11 +304,14 @@ bool HFTrackEfficiency::findTracks(PHCompositeNode *topNode, Decay decay) daughterG4->identify(); } + m_is_primary = m_truthInfo->is_sPHENIX_primary(motherG4); + CLHEP::Hep3Vector *mother3Vector = new CLHEP::Hep3Vector(motherG4->get_px(), motherG4->get_py(), motherG4->get_pz()); motherTrueLV->setVectM((*mother3Vector), getParticleMass(decay[0].second)); m_true_mother_pT = motherTrueLV->perp(); m_true_mother_p = mother3Vector->mag(); m_true_mother_eta = motherTrueLV->pseudoRapidity(); + m_true_mother_phi = motherTrueLV->phi(); PHG4VtxPoint *thisVtx = m_truthInfo->GetVtx(motherG4->get_vtx_id()); m_primary_vtx_x = thisVtx->get_x(); @@ -310,7 +327,7 @@ bool HFTrackEfficiency::findTracks(PHCompositeNode *topNode, Decay decay) m_secondary_vtx_y = thisVtx->get_y(); m_secondary_vtx_z = thisVtx->get_z(); - m_true_track_PID[i - 1] = daughterG4->get_pid(); + m_true_track_PID[index] = daughterG4->get_pid(); truth_ID = daughterG4->get_track_id(); delete mother3Vector; @@ -318,10 +335,11 @@ bool HFTrackEfficiency::findTracks(PHCompositeNode *topNode, Decay decay) } } - m_true_track_pT[i - 1] = (float) daughterTrueLV->perp(); - m_true_track_eta[i - 1] = (float) daughterTrueLV->pseudoRapidity(); - m_min_true_track_pT = std::min(m_true_track_pT[i - 1], m_min_true_track_pT); - m_max_true_track_pT = std::max(m_true_track_pT[i - 1], m_max_true_track_pT); + m_true_track_pT[index] = (float) daughterTrueLV->perp(); + m_true_track_eta[index] = (float) daughterTrueLV->pseudoRapidity(); + m_true_track_phi[index] = (float) daughterTrueLV->phi(); + m_min_true_track_pT = std::min(m_true_track_pT[index], m_min_true_track_pT); + m_max_true_track_pT = std::max(m_true_track_pT[index], m_max_true_track_pT); if (m_dst_truth_reco_map && truth_ID >= 0) { @@ -339,7 +357,7 @@ bool HFTrackEfficiency::findTracks(PHCompositeNode *topNode, Decay decay) m_dst_track = m_input_trackMap->get(best_reco_id); if (m_dst_track) { - m_used_truth_reco_map[i - 1] = true; + m_used_truth_reco_map[index] = true; recoTrackFound = true; } } @@ -367,24 +385,25 @@ bool HFTrackEfficiency::findTracks(PHCompositeNode *topNode, Decay decay) { m_dst_track->identify(); } - m_reco_track_exists[i - 1] = true; - m_reco_track_pT[i - 1] = m_dst_track->get_pt(); - m_reco_track_eta[i - 1] = m_dst_track->get_eta(); - m_reco_track_chi2nDoF[i - 1] = m_dst_track->get_chisq() / m_dst_track->get_ndf(); + m_reco_track_exists[index] = true; + m_reco_track_pT[index] = m_dst_track->get_pt(); + m_reco_track_eta[index] = m_dst_track->get_eta(); + m_reco_track_phi[index] = m_dst_track->get_phi(); + m_reco_track_chi2nDoF[index] = m_dst_track->get_chisq() / m_dst_track->get_ndf(); if (m_dst_track->get_silicon_seed()) { - m_reco_track_silicon_seeds[i - 1] = static_cast(m_dst_track->get_silicon_seed()->size_cluster_keys()); + m_reco_track_silicon_seeds[index] = static_cast(m_dst_track->get_silicon_seed()->size_cluster_keys()); } else { - m_reco_track_silicon_seeds[i - 1] = 0; + m_reco_track_silicon_seeds[index] = 0; } - m_reco_track_tpc_seeds[i - 1] = static_cast(m_dst_track->get_tpc_seed()->size_cluster_keys()); - m_min_reco_track_pT = std::min(m_reco_track_pT[i - 1], m_min_reco_track_pT); - m_max_reco_track_pT = std::max(m_reco_track_pT[i - 1], m_max_reco_track_pT); + m_reco_track_tpc_seeds[index] = static_cast(m_dst_track->get_tpc_seed()->size_cluster_keys()); + m_min_reco_track_pT = std::min(m_reco_track_pT[index], m_min_reco_track_pT); + m_max_reco_track_pT = std::max(m_reco_track_pT[index], m_max_reco_track_pT); CLHEP::HepLorentzVector *daughterRecoLV = new CLHEP::HepLorentzVector(); - daughterRecoLV->setVectM(CLHEP::Hep3Vector(m_dst_track->get_px(), m_dst_track->get_py(), m_dst_track->get_pz()), getParticleMass(m_true_track_PID[i - 1])); + daughterRecoLV->setVectM(CLHEP::Hep3Vector(m_dst_track->get_px(), m_dst_track->get_py(), m_dst_track->get_pz()), getParticleMass(m_true_track_PID[index])); motherRecoLV += *daughterRecoLV; delete daughterRecoLV; @@ -399,6 +418,7 @@ bool HFTrackEfficiency::findTracks(PHCompositeNode *topNode, Decay decay) if (selectedTracks.size() == m_nDaughters) { m_reco_mother_mass = motherRecoLV.m(); + m_reco_mother_pT = motherRecoLV.perp(); if (m_write_track_map) { m_output_trackMap = findNode::getClass(topNode, outputNodeName); @@ -429,11 +449,14 @@ void HFTrackEfficiency::initializeBranches() m_tree->SetAutoSave(-5e6); // Save the output file every 5MB m_tree->Branch("all_tracks_reconstructed", &m_all_tracks_reconstructed, "all_tracks_reconstructed/O"); + m_tree->Branch("is_primary", &m_is_primary, "is_primary/O"); m_tree->Branch("true_mother_mass", &m_true_mother_mass, "true_mother_mass/F"); m_tree->Branch("reco_mother_mass", &m_reco_mother_mass, "reco_mother_mass/F"); m_tree->Branch("true_mother_pT", &m_true_mother_pT, "true_mother_pT/F"); + m_tree->Branch("reco_mother_pT", &m_reco_mother_pT, "reco_mother_pT/F"); m_tree->Branch("true_mother_p", &m_true_mother_p, "true_mother_p/F"); m_tree->Branch("true_mother_eta", &m_true_mother_eta, "true_mother_eta/F"); + m_tree->Branch("true_mother_phi", &m_true_mother_phi, "true_mother_phi/F"); m_tree->Branch("min_true_track_pT", &m_min_true_track_pT, "min_true_track_pT/F"); m_tree->Branch("min_reco_track_pT", &m_min_reco_track_pT, "min_reco_track_pT/F"); m_tree->Branch("max_true_track_pT", &m_max_true_track_pT, "max_true_track_pT/F"); @@ -448,6 +471,8 @@ void HFTrackEfficiency::initializeBranches() m_tree->Branch("reco_" + TString(daughter_number) + "_pT", &m_reco_track_pT[iTrack], "reco_" + TString(daughter_number) + "_pT/F"); m_tree->Branch("true_" + TString(daughter_number) + "_eta", &m_true_track_eta[iTrack], "true_" + TString(daughter_number) + "_eta/F"); m_tree->Branch("reco_" + TString(daughter_number) + "_eta", &m_reco_track_eta[iTrack], "reco_" + TString(daughter_number) + "_eta/F"); + m_tree->Branch("true_" + TString(daughter_number) + "_phi", &m_true_track_phi[iTrack], "true_" + TString(daughter_number) + "_phi/F"); + m_tree->Branch("reco_" + TString(daughter_number) + "_phi", &m_reco_track_phi[iTrack], "reco_" + TString(daughter_number) + "_phi/F"); m_tree->Branch("true_" + TString(daughter_number) + "_PID", &m_true_track_PID[iTrack], "true_" + TString(daughter_number) + "_PID/F"); m_tree->Branch("reco_" + TString(daughter_number) + "_chi2nDoF", &m_reco_track_chi2nDoF[iTrack], "reco_" + TString(daughter_number) + "_chi2nDoF/F"); m_tree->Branch("reco_" + TString(daughter_number) + "_silicon_seeds", &m_reco_track_silicon_seeds[iTrack], "reco_" + TString(daughter_number) + "_silicon_seeds/I"); @@ -465,9 +490,11 @@ void HFTrackEfficiency::initializeBranches() void HFTrackEfficiency::resetBranches() { m_all_tracks_reconstructed = false; + m_is_primary = false; m_true_mother_mass = std::numeric_limits::quiet_NaN(); m_reco_mother_mass = std::numeric_limits::quiet_NaN(); m_true_mother_pT = std::numeric_limits::quiet_NaN(); + m_reco_mother_pT = std::numeric_limits::quiet_NaN(); m_true_mother_p = std::numeric_limits::quiet_NaN(); m_true_mother_eta = std::numeric_limits::quiet_NaN(); m_min_true_track_pT = std::numeric_limits::max(); @@ -482,6 +509,8 @@ void HFTrackEfficiency::resetBranches() m_reco_track_pT[iTrack] = std::numeric_limits::quiet_NaN(); m_true_track_eta[iTrack] = std::numeric_limits::quiet_NaN(); m_reco_track_eta[iTrack] = std::numeric_limits::quiet_NaN(); + m_true_track_phi[iTrack] = std::numeric_limits::quiet_NaN(); + m_reco_track_phi[iTrack] = std::numeric_limits::quiet_NaN(); m_true_track_PID[iTrack] = std::numeric_limits::quiet_NaN(); m_reco_track_chi2nDoF[iTrack] = std::numeric_limits::quiet_NaN(); m_reco_track_silicon_seeds[iTrack] = 0; diff --git a/offline/packages/HFTrackEfficiency/HFTrackEfficiency.h b/offline/packages/HFTrackEfficiency/HFTrackEfficiency.h index ddd346c7a4..f667c3bc27 100644 --- a/offline/packages/HFTrackEfficiency/HFTrackEfficiency.h +++ b/offline/packages/HFTrackEfficiency/HFTrackEfficiency.h @@ -89,11 +89,14 @@ class HFTrackEfficiency : public SubsysReco static const int m_maxTracks{5}; bool m_all_tracks_reconstructed{false}; + bool m_is_primary{false}; float m_true_mother_mass{std::numeric_limits::quiet_NaN()}; float m_reco_mother_mass{std::numeric_limits::quiet_NaN()}; float m_true_mother_pT{std::numeric_limits::quiet_NaN()}; + float m_reco_mother_pT{std::numeric_limits::quiet_NaN()}; float m_true_mother_p{std::numeric_limits::quiet_NaN()}; float m_true_mother_eta{std::numeric_limits::quiet_NaN()}; + float m_true_mother_phi{std::numeric_limits::quiet_NaN()}; float m_min_true_track_pT{std::numeric_limits::max()}; float m_min_reco_track_pT{std::numeric_limits::max()}; float m_max_true_track_pT{std::numeric_limits::min()}; // Apparently min() is still a +ve value @@ -104,6 +107,8 @@ class HFTrackEfficiency : public SubsysReco float m_reco_track_pT[m_maxTracks]{std::numeric_limits::quiet_NaN()}; float m_true_track_eta[m_maxTracks]{std::numeric_limits::quiet_NaN()}; float m_reco_track_eta[m_maxTracks]{std::numeric_limits::quiet_NaN()}; + float m_true_track_phi[m_maxTracks]{std::numeric_limits::quiet_NaN()}; + float m_reco_track_phi[m_maxTracks]{std::numeric_limits::quiet_NaN()}; float m_true_track_PID[m_maxTracks]{std::numeric_limits::quiet_NaN()}; float m_reco_track_chi2nDoF[m_maxTracks]{std::numeric_limits::quiet_NaN()}; int m_reco_track_silicon_seeds[m_maxTracks]{0}; diff --git a/offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc b/offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc index b319af5b56..9bb76608ee 100644 --- a/offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc +++ b/offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc @@ -1162,6 +1162,10 @@ float KFParticle_Tools::get_dEdx(PHCompositeNode *topNode, const KFParticle &dau { m_dst_trackmap = findNode::getClass(topNode, m_trk_map_node_name); m_cluster_map = findNode::getClass(topNode, "TRKR_CLUSTER"); + if (!m_cluster_map) + { + m_cluster_map = findNode::getClass(topNode, "TRKR_CLUSTER_SEED"); + } m_geom_container = findNode::getClass(topNode, "TPCGEOMCONTAINER"); auto *geometry = findNode::getClass(topNode, "ActsGeometry"); if (!m_cluster_map || !m_geom_container || !geometry) @@ -1184,7 +1188,18 @@ float KFParticle_Tools::get_dEdx(PHCompositeNode *topNode, const KFParticle &dau void KFParticle_Tools::init_dEdx_fits() { - std::string dedx_fitparams = CDBInterface::instance()->getUrl("TPC_DEDX_FITPARAM"); + std::string dedx_fitparams; + if (m_use_local_PID_file) + { + dedx_fitparams = m_local_PID_filename; + } + else + { + dedx_fitparams = CDBInterface::instance()->getUrl("TPC_DEDX_FITPARAM"); + } + + std::cout << PHWHERE << " opening " << dedx_fitparams << std::endl; + TFile *filefit = TFile::Open(dedx_fitparams.c_str()); if (!filefit->IsOpen()) @@ -1193,12 +1208,26 @@ void KFParticle_Tools::init_dEdx_fits() return; } - filefit->GetObject("f_piband", f_pion_plus); - filefit->GetObject("f_Kband", f_kaon_plus); - filefit->GetObject("f_pband", f_proton_plus); - filefit->GetObject("f_piminus_band", f_pion_minus); - filefit->GetObject("f_Kminus_band", f_kaon_minus); - filefit->GetObject("f_pbar_band", f_proton_minus); + if (m_use_local_PID_file) + { + std::cout << PHWHERE << " using local file " << m_local_PID_filename << std::endl; + // new method is independent of charge + filefit->GetObject("pi_band",f_pion_plus); + filefit->GetObject("K_band",f_kaon_plus); + filefit->GetObject("p_band",f_proton_plus); + filefit->GetObject("pi_band",f_pion_minus); + filefit->GetObject("K_band",f_kaon_minus); + filefit->GetObject("p_band",f_proton_minus); + } + else + { + filefit->GetObject("f_piband", f_pion_plus); + filefit->GetObject("f_Kband", f_kaon_plus); + filefit->GetObject("f_pband", f_proton_plus); + filefit->GetObject("f_piminus_band", f_pion_minus); + filefit->GetObject("f_Kminus_band", f_kaon_minus); + filefit->GetObject("f_pbar_band", f_proton_minus); + } pidMap.insert(std::pair(-11, f_pion_plus)); pidMap.insert(std::pair(211, f_pion_plus)); diff --git a/offline/packages/KFParticle_sPHENIX/KFParticle_Tools.h b/offline/packages/KFParticle_sPHENIX/KFParticle_Tools.h index 4e722a15db..feabd4aafc 100644 --- a/offline/packages/KFParticle_sPHENIX/KFParticle_Tools.h +++ b/offline/packages/KFParticle_sPHENIX/KFParticle_Tools.h @@ -27,6 +27,8 @@ #include #include +#include // included here so inline functions are defined on user end + #include #include @@ -149,6 +151,8 @@ class KFParticle_Tools : protected KFParticle_MVA std::vector m_intermediate_vertex_volume; bool m_use_PID{false}; + bool m_use_local_PID_file{false}; + std::string m_local_PID_filename = ""; float m_dEdx_band_width{0.2}; // Fraction of expected dE/dx TF1 *f_pion_plus{nullptr}; diff --git a/offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.cc b/offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.cc index 1770870bb3..b3b119e4f6 100644 --- a/offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.cc +++ b/offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.cc @@ -303,7 +303,9 @@ void KFParticle_nTuple::initializeBranches(PHCompositeNode* topNode) m_tree->Branch("runNumber", &m_runNumber, "runNumber/I"); m_tree->Branch("eventNumber", &m_evtNumber, "eventNumber/I"); - m_tree->Branch("BCO", &m_bco, "BCO/L"); + m_tree->Branch("event_bco", &m_event_bco, "event_bco/L"); //adding for the current event BCO, not shifted + m_tree->Branch("BCO", &m_bco, "BCO/L"); //already there, this is shifted BCO + m_tree->Branch("last_event_bco", &m_last_event_bco, "last_event_bco/L"); //BCO for the last event if (m_get_trigger_info) { @@ -663,20 +665,38 @@ void KFParticle_nTuple::fillBranch(PHCompositeNode* topNode, if (evtNode) { - EventHeader* evtHeader = findNode::getClass(topNode, "EventHeader"); - m_runNumber = evtHeader->get_RunNumber(); - m_evtNumber = evtHeader->get_EvtSequence(); - - auto* gl1packet = findNode::getClass(topNode, "GL1RAWHIT"); - if (!gl1packet) - { - gl1packet = findNode::getClass(topNode, "GL1Packet"); - } - m_bco = m_trigger_info_available ? gl1packet->lValue(0, "BCO") + m_calculated_daughter_bunch_crossing[0] : 0; + EventHeader* evtHeader = findNode::getClass(topNode, "EventHeader"); + if (evtHeader) + { + m_runNumber = evtHeader->get_RunNumber(); + m_evtNumber = evtHeader->get_EvtSequence(); + } + else + { + m_runNumber = -1; + m_evtNumber = -1; + } + + auto* gl1packet = findNode::getClass(topNode, "GL1RAWHIT"); + if (!gl1packet) + { + gl1packet = findNode::getClass(topNode, "GL1Packet"); + } + + if (gl1packet) + { + m_bco = gl1packet->lValue(0, "BCO") + m_calculated_daughter_bunch_crossing[0]; + } + else + { + m_bco = -1; + } } else { - m_runNumber = m_evtNumber = m_bco = -1; + m_runNumber = -1; + m_evtNumber = -1; + m_bco = -1; } if (m_trigger_info_available) @@ -741,4 +761,4 @@ bool KFParticle_nTuple::fillConditionMet() const // if requiring track-calo matching, the match result is returned return isTrackEMCalmatch; -} \ No newline at end of file +} diff --git a/offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.h b/offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.h index 4798e24942..45256fc1cc 100644 --- a/offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.h +++ b/offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.h @@ -9,6 +9,7 @@ #include #include // for string #include +#include // fixed width integer types used for BCO counters class PHCompositeNode; class TTree; @@ -35,6 +36,13 @@ class KFParticle_nTuple : public KFParticle_truthAndDetTools, public KFParticle_ std::vector daughters, std::vector intermediates); + // pass event-level BCO values from KFParticle_sPHENIX + void set_event_bcos(const int64_t this_bco, const int64_t last_bco) + { + m_event_bco = this_bco; + m_last_event_bco = last_bco; + } + float calc_secondary_vertex_mass_noPID(std::vector kfp_daughters); bool fillConditionMet() const; @@ -219,6 +227,8 @@ class KFParticle_nTuple : public KFParticle_truthAndDetTools, public KFParticle_ int m_runNumber{-1}; int m_evtNumber{-1}; int64_t m_bco{-1}; + uint64_t m_event_bco{0};//current event BCO + uint64_t m_last_event_bco{0}; //only keeping this, BCO for the last event bool m_trigger_info_available{false}; }; diff --git a/offline/packages/KFParticle_sPHENIX/KFParticle_sPHENIX.cc b/offline/packages/KFParticle_sPHENIX/KFParticle_sPHENIX.cc index 38b60d55ba..db46bffafe 100644 --- a/offline/packages/KFParticle_sPHENIX/KFParticle_sPHENIX.cc +++ b/offline/packages/KFParticle_sPHENIX/KFParticle_sPHENIX.cc @@ -29,6 +29,8 @@ #include #include +#include +#include #include #include @@ -135,49 +137,108 @@ int KFParticle_sPHENIX::InitRun(PHCompositeNode *topNode) int KFParticle_sPHENIX::process_event(PHCompositeNode *topNode) { - std::vector mother, vertex_kfparticle; - std::vector> daughters, intermediates; - int nPVs, multiplicity; + std::vector mother; + std::vector vertex_kfparticle; + std::vector> daughters; + std::vector> intermediates; + int nPVs; + int multiplicity; SvtxTrackMap *check_trackmap = findNode::getClass(topNode, m_trk_map_node_name); multiplicity = check_trackmap->size(); - if (check_trackmap->size() == 0) + if (check_trackmap->empty()) { if (Verbosity() >= VERBOSITY_SOME) { std::cout << "KFParticle: Event skipped as there are no tracks" << std::endl; } - return Fun4AllReturnCodes::ABORTEVENT; + return Fun4AllReturnCodes::EVENT_OK; } + + // Adding BCO Matching + auto* evtHeader = findNode::getClass(topNode, "EventHeader"); // event header node + auto* gl1packet = findNode::getClass(topNode, "GL1RAWHIT"); // gl1 packet node + if (!gl1packet) + { + gl1packet = findNode::getClass(topNode, "GL1Packet"); + } + + if (evtHeader && gl1packet) + { + const int64_t run = evtHeader->get_RunNumber(); + const int64_t evn = evtHeader->get_EvtSequence(); + m_this_event_bco = static_cast(gl1packet->lValue(0, "BCO")); + + if (Verbosity() >= VERBOSITY_SOME) + { + std::cout << "Event start | run: " << run << " event: " << evn << " this_event_bco: " << m_this_event_bco << std::endl; + } + + if (run != m_prev_runNumber || evn != m_prev_eventNumber) + { + + if (Verbosity() >= VERBOSITY_SOME) + { + std::cout << "New event detected" << std::endl; + std::cout << "Previous event BCO: " << m_prev_event_bco << std::endl; + } + //m_last_event_bco = m_prev_event_bco; + m_last_event_bco = (run == m_prev_runNumber) ? m_prev_event_bco : -1; + m_prev_event_bco = m_this_event_bco; + + m_prev_runNumber = run; + m_prev_eventNumber = evn; + + if (Verbosity() >= VERBOSITY_SOME) + { + std::cout << "Updated values | last_event_bco: " << m_last_event_bco + << " stored_prev_event_bco: " << m_prev_event_bco + << std::endl; + } + } + } + else + { + + if (Verbosity() >= VERBOSITY_SOME) + { + std::cout << "EventHeader or GL1 packet not found" << std::endl; + } + m_this_event_bco = -1; + m_last_event_bco = -1; + m_prev_event_bco = -1; + m_prev_runNumber = -1; + m_prev_eventNumber = -1; + } +// End BCO matching here if (!m_use_fake_pv) { if (m_use_mbd_vertex) { MbdVertexMap* check_vertexmap = findNode::getClass(topNode, "MbdVertexMap"); - if (check_vertexmap->size() == 0) + if (check_vertexmap->empty()) { if (Verbosity() >= VERBOSITY_SOME) { std::cout << "KFParticle: Event skipped as there are no vertices" << std::endl; } - return Fun4AllReturnCodes::ABORTEVENT; + return Fun4AllReturnCodes::EVENT_OK; } } else { SvtxVertexMap* check_vertexmap = findNode::getClass(topNode, m_vtx_map_node_name); - if (check_vertexmap->size() == 0) + if (check_vertexmap->empty()) { if (Verbosity() >= VERBOSITY_SOME) { std::cout << "KFParticle: Event skipped as there are no vertices" << std::endl; } - return Fun4AllReturnCodes::ABORTEVENT; + return Fun4AllReturnCodes::EVENT_OK; } } - } createDecay(topNode, mother, vertex_kfparticle, daughters, intermediates, nPVs); @@ -190,7 +251,7 @@ int KFParticle_sPHENIX::process_event(PHCompositeNode *topNode) vertex_kfparticle = mother; } - if (mother.size() != 0) + if (!mother.empty()) { for (unsigned int i = 0; i < mother.size(); ++i) { @@ -206,6 +267,7 @@ int KFParticle_sPHENIX::process_event(PHCompositeNode *topNode) if (m_save_output) { + set_event_bcos(m_this_event_bco, m_last_event_bco); //filling nTuple for BCO Matching fillBranch(topNode, mother[i], vertex_kfparticle[i], daughters[i], intermediates[i]); } if (m_save_dst) @@ -479,7 +541,7 @@ int KFParticle_sPHENIX::parseDecayDescriptor() setNumberOfTracks(nTracks); setDaughters(daughter_list); - if (intermediates_name.size() > 0) + if (!intermediates_name.empty()) { hasIntermediateStates(); setIntermediateStates(intermediate_list); @@ -495,15 +557,14 @@ int KFParticle_sPHENIX::parseDecayDescriptor() } return 0; } - else + + if (Verbosity() >= VERBOSITY_SOME) { - if (Verbosity() >= VERBOSITY_SOME) - { - std::cout << "KFParticle: Your decay descriptor, " << Name() << " cannot be parsed" - << "\nExiting!" << std::endl; - } - return Fun4AllReturnCodes::ABORTRUN; + std::cout << "KFParticle: Your decay descriptor, " << Name() << " cannot be parsed" + << "\nExiting!" << std::endl; } + return Fun4AllReturnCodes::ABORTRUN; + } void KFParticle_sPHENIX::getField() diff --git a/offline/packages/KFParticle_sPHENIX/KFParticle_sPHENIX.h b/offline/packages/KFParticle_sPHENIX/KFParticle_sPHENIX.h index 64fc3f37bb..0812ed8f14 100644 --- a/offline/packages/KFParticle_sPHENIX/KFParticle_sPHENIX.h +++ b/offline/packages/KFParticle_sPHENIX/KFParticle_sPHENIX.h @@ -44,6 +44,8 @@ #include #include // for pair #include // for vector +#include //include for new member added +#include // fixed width integer types used for BCO counters class PHCompositeNode; class TFile; @@ -394,6 +396,10 @@ class KFParticle_sPHENIX : public SubsysReco, public KFParticle_nTuple, public K void selectMotherByMassError(bool select = true) { m_select_by_mass_error = select; } void usePID(bool use = true){ m_use_PID = use; } + + void useLocalPIDFile(bool use = true){ m_use_local_PID_file = use; } + + void setLocalPIDFilename(const std::string &filename){ m_local_PID_filename = filename; } void setPIDacceptFraction(float frac = 0.2){ m_dEdx_band_width = frac; } @@ -418,6 +424,12 @@ class KFParticle_sPHENIX : public SubsysReco, public KFParticle_nTuple, public K bool m_save_dst; bool m_save_output; int candidateCounter = 0; + //Adding member variables for BCO matching + uint64_t m_this_event_bco{0}; + uint64_t m_last_event_bco{0}; + uint64_t m_prev_event_bco{0}; + int64_t m_prev_runNumber{-1}; + int64_t m_prev_eventNumber{-1}; //till here std::string m_outfile_name; TFile *m_outfile; std::string m_decayDescriptor; diff --git a/offline/packages/KFParticle_sPHENIX/KFParticle_truthAndDetTools.cc b/offline/packages/KFParticle_sPHENIX/KFParticle_truthAndDetTools.cc index f8373c9e6f..14b353ff43 100644 --- a/offline/packages/KFParticle_sPHENIX/KFParticle_truthAndDetTools.cc +++ b/offline/packages/KFParticle_sPHENIX/KFParticle_truthAndDetTools.cc @@ -1299,7 +1299,11 @@ void KFParticle_truthAndDetTools::fillDetectorBranch(PHCompositeNode *topNode, dst_clustermap = findNode::getClass(topNode, "TRKR_CLUSTER"); if (!dst_clustermap) { - std::cout << "KFParticle detector info: TRKR_CLUSTER does not exist" << std::endl; + dst_clustermap = findNode::getClass(topNode, "TRKR_CLUSTER_SEED"); + if (!dst_clustermap) + { + std::cout << "KFParticle detector info: TRKR_CLUSTER does not exist" << std::endl; + } } track = getTrack(daughter.Id(), dst_trackmap); diff --git a/offline/packages/NodeDump/DumpTowerInfoContainer.cc b/offline/packages/NodeDump/DumpTowerInfoContainer.cc index 21f8c99c19..7ae0ae0230 100644 --- a/offline/packages/NodeDump/DumpTowerInfoContainer.cc +++ b/offline/packages/NodeDump/DumpTowerInfoContainer.cc @@ -41,7 +41,6 @@ int DumpTowerInfoContainer::process_Node(PHNode *myNode) *fout << "chi2: " << rawtwr->get_chi2() << std::endl; *fout << "pedestal: " << rawtwr->get_pedestal() << std::endl; *fout << "isHot: " << rawtwr->get_isHot() << std::endl; - *fout << "isBadTime: " << rawtwr->get_isBadTime() << std::endl; *fout << "isNotInstr: " << rawtwr->get_isNotInstr() << std::endl; *fout << "isGood: " << rawtwr->get_isGood() << std::endl; *fout << "status: " << static_cast(rawtwr->get_status()) << std::endl; diff --git a/offline/packages/PHGenFitPkg/PHGenFit/Fitter.cc b/offline/packages/PHGenFitPkg/PHGenFit/Fitter.cc index 8fe89b5019..aeb01dee62 100644 --- a/offline/packages/PHGenFitPkg/PHGenFit/Fitter.cc +++ b/offline/packages/PHGenFitPkg/PHGenFit/Fitter.cc @@ -51,9 +51,9 @@ namespace PHGenFit const std::string& /*track_rep_choice*/, const bool doEventDisplay) : verbosity(1000) + , _tgeo_manager(new TGeoManager("Default", "Geane geometry")) , _doEventDisplay(doEventDisplay) { - _tgeo_manager = new TGeoManager("Default", "Geane geometry"); TGeoManager::Import(tgeo_file_name.data()); assert(field); @@ -73,26 +73,24 @@ namespace PHGenFit } // init fitter - if (fitter_choice.compare("KalmanFitterRefTrack") == 0) + if (fitter_choice == "KalmanFitterRefTrack") { _fitter = new genfit::KalmanFitterRefTrack(); } - else if (fitter_choice.compare("KalmanFitter") == 0) -// NOLINTNEXTLINE(bugprone-branch-clone) - { + else if (fitter_choice == "KalmanFitter") + { // NOLINT(bugprone-branch-clone) _fitter = new genfit::KalmanFitter(); } - else if (fitter_choice.compare("DafSimple") == 0) + else if (fitter_choice == "DafSimple") { _fitter = new genfit::DAF(false); } - else if (fitter_choice.compare("DafRef") == 0) + else if (fitter_choice == "DafRef") { _fitter = new genfit::DAF(true); } else -// NOLINTNEXTLINE(bugprone-branch-clone) - { + { // NOLINT(bugprone-branch-clone) _fitter = new genfit::KalmanFitter(); } @@ -235,7 +233,7 @@ namespace PHGenFit { _fitter = new genfit::KalmanFitterRefTrack(); } - if (fitter_choice == PHGenFit::Fitter::DafSimple) + else if (fitter_choice == PHGenFit::Fitter::DafSimple) { _fitter = new genfit::DAF(false); } @@ -289,19 +287,19 @@ namespace PHGenFit } // init fitter - if (fitter_choice.compare("KalmanFitterRefTrack") == 0) + if (fitter_choice == "KalmanFitterRefTrack") { _fitter = new genfit::KalmanFitterRefTrack(); } - else if (fitter_choice.compare("KalmanFitter") == 0) + else if (fitter_choice == "KalmanFitter") { _fitter = new genfit::KalmanFitter(); } - else if (fitter_choice.compare("DafSimple") == 0) + else if (fitter_choice == "DafSimple") { _fitter = new genfit::DAF(false); } - else if (fitter_choice.compare("DafRef") == 0) + else if (fitter_choice == "DafRef") { _fitter = new genfit::DAF(true); } diff --git a/offline/packages/PHGenFitPkg/PHGenFit/Track.cc b/offline/packages/PHGenFitPkg/PHGenFit/Track.cc index b1643e8cd0..0e06f15984 100644 --- a/offline/packages/PHGenFitPkg/PHGenFit/Track.cc +++ b/offline/packages/PHGenFitPkg/PHGenFit/Track.cc @@ -48,8 +48,8 @@ #define WILD_DOUBLE (-999999) -//#define _DEBUG_ -//#define _PRINT_MATRIX_ +// #define _DEBUG_ +// #define _PRINT_MATRIX_ #ifdef _DEBUG_ #include @@ -60,11 +60,10 @@ ofstream fout_matrix("matrix.txt"); namespace PHGenFit { Track::Track(genfit::AbsTrackRep* rep, const TVector3& seed_pos, const TVector3& seed_mom, const TMatrixDSym& seed_cov, const int v) + : verbosity(v) { // TODO Add input param check - verbosity = v; - genfit::MeasuredStateOnPlane seedMSoP(rep); seedMSoP.setPosMomCov(seed_pos, seed_mom, seed_cov); // const genfit::StateOnPlane seedSoP(seedMSoP); @@ -78,12 +77,12 @@ namespace PHGenFit } Track::Track(const PHGenFit::Track& t) + : verbosity(t.verbosity) + , _track(new genfit::Track(*(t.getGenFitTrack()))) + , _clusterIDs(t.get_cluster_IDs()) + , _clusterkeys(t.get_cluster_keys()) + , _vertex_id(t.get_vertex_id()) { - _track = new genfit::Track(*(t.getGenFitTrack())); - verbosity = t.verbosity; - _clusterIDs = t.get_cluster_IDs(); - _clusterkeys = t.get_cluster_keys(); - _vertex_id = t.get_vertex_id(); } int Track::addMeasurement(PHGenFit::Measurement* measurement) @@ -191,10 +190,8 @@ namespace PHGenFit delete state; return nullptr; } - else - { - return state; - } + + return state; } double Track::extrapolateToLine(genfit::MeasuredStateOnPlane& state, const TVector3& line_point, const TVector3& line_direction, const int tr_point_id) const @@ -240,10 +237,8 @@ namespace PHGenFit delete state; return nullptr; } - else - { - return state; - } + + return state; } double Track::extrapolateToCylinder(genfit::MeasuredStateOnPlane& state, double radius, const TVector3& line_point, const TVector3& line_direction, const int tr_point_id, const int direction) const @@ -361,10 +356,8 @@ namespace PHGenFit delete state; return nullptr; } - else - { - return state; - } + + return state; } int Track::updateOneMeasurementKalman( @@ -385,7 +378,7 @@ namespace PHGenFit << std::endl; #endif - if (measurements.size() == 0) + if (measurements.empty()) { return -1; } @@ -437,11 +430,11 @@ namespace PHGenFit #endif continue; } - //#ifdef _DEBUG_ + // #ifdef _DEBUG_ // std::cout << __LINE__ << "\n ###################################################################"<Print(); // std::cout << __LINE__ << "\n ###################################################################"<getFittedState(true)); @@ -579,7 +572,7 @@ namespace PHGenFit // std::cout << err_phi << "\t" << err_z << "\t"; } #endif - for (auto rawMeasurement : rawMeasurements) + for (auto* rawMeasurement : rawMeasurements) { fi->addMeasurementsOnPlane( rawMeasurement->constructMeasurementsOnPlane(*state)); @@ -598,7 +591,7 @@ namespace PHGenFit << ": size of fi's MeasurementsOnPlane: " << measurements_on_plane.size() << std::endl; #endif - for (auto it : measurements_on_plane) + for (auto* it : measurements_on_plane) { const genfit::MeasurementOnPlane& mOnPlane = *it; // const double weight = mOnPlane.getWeight(); @@ -769,10 +762,7 @@ namespace PHGenFit delete state; return nullptr; } - else - { - return state; - } + return state; } double Track::get_chi2() const diff --git a/offline/packages/Skimmers/CaloStatusSkimmer/CaloStatusSkimmer.cc b/offline/packages/Skimmers/CaloStatusSkimmer/CaloStatusSkimmer.cc new file mode 100644 index 0000000000..73dce5e912 --- /dev/null +++ b/offline/packages/Skimmers/CaloStatusSkimmer/CaloStatusSkimmer.cc @@ -0,0 +1,194 @@ +#include "CaloStatusSkimmer.h" + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +//____________________________________________________________________________.. +CaloStatusSkimmer::CaloStatusSkimmer(const std::string &name) + : SubsysReco(name) +{ + std::cout << "CaloStatusSkimmer::CaloStatusSkimmer(const std::string &name) ""Calling ctor" << std::endl; +} + +//____________________________________________________________________________.. +int CaloStatusSkimmer::process_event(PHCompositeNode *topNode) +{ + n_eventcounter++; + if (m_EMC_skim_threshold > 0) + { + TowerInfoContainer *towers = + findNode::getClass(topNode, "TOWERS_CEMC"); + if (!towers) + { + n_notowernodecounter++; + if (Verbosity() > 0) + { + std::cout << PHWHERE << "calostatuscheck::process_event: missing TOWERS_CEMC" << std::endl; + } + return Fun4AllReturnCodes::ABORTEVENT; + } + const uint32_t ntowers = towers->size(); + uint16_t notinstr_count = 0; + for (uint32_t ch = 0; ch < ntowers; ++ch) + { + TowerInfo *tower = towers->get_tower_at_channel(ch); + if (tower->get_isNotInstr()) + { + ++notinstr_count; + } + } + if (Verbosity() > 9) + { + std::cout << "CaloStatusSkimmer::process_event: event " << n_eventcounter << ", ntowers in EMCal = " << ntowers << ", not-instrumented(empty/missing pckt) towers in EMCal = " << notinstr_count << std::endl; + } + + if (notinstr_count >= m_EMC_skim_threshold) + { + n_skimcounter++; + return Fun4AllReturnCodes::ABORTEVENT; + } + } + + if (m_HCal_skim_threshold > 0) + { + TowerInfoContainer *hcalin_towers = findNode::getClass(topNode, "TOWERS_HCALIN"); + TowerInfoContainer *hcalout_towers = findNode::getClass(topNode, "TOWERS_HCALOUT"); + if (!hcalin_towers || !hcalout_towers) + { + n_notowernodecounter++; + if (Verbosity() > 0) + { + std::cout << PHWHERE << "calostatuscheck::process_event: missing TOWERS_HCALIN or TOWERS_HCALOUT" << std::endl; + } + return Fun4AllReturnCodes::ABORTEVENT; + } + + const uint32_t ntowers_hcalin = hcalin_towers->size(); + uint16_t notinstr_count_hcalin = 0; + for (uint32_t ch = 0; ch < ntowers_hcalin; ++ch) + { + TowerInfo *tower_in = hcalin_towers->get_tower_at_channel(ch); + if (tower_in->get_isNotInstr()) + { + ++notinstr_count_hcalin; + } + } + + const uint32_t ntowers_hcalout = hcalout_towers->size(); + uint16_t notinstr_count_hcalout = 0; + for (uint32_t ch = 0; ch < ntowers_hcalout; ++ch) + { + TowerInfo *tower_out = hcalout_towers->get_tower_at_channel(ch); + if (tower_out->get_isNotInstr()) + { + ++notinstr_count_hcalout; + } + } + + if (Verbosity() > 9) + { + std::cout << "CaloStatusSkimmer::process_event: event " << n_eventcounter << ", ntowers in HCalIn = " << ntowers_hcalin << ", not-instrumented(empty/missing pckt) towers in HCalIn = " << notinstr_count_hcalin << ", ntowers in HCalOut = " << ntowers_hcalout << ", not-instrumented(empty/missing pckt) towers in HCalOut = " << notinstr_count_hcalout << std::endl; + } + + if (notinstr_count_hcalin >= m_HCal_skim_threshold || + notinstr_count_hcalout >= m_HCal_skim_threshold) + { + n_skimcounter++; + return Fun4AllReturnCodes::ABORTEVENT; + } + } + + if (m_sEPD_skim_threshold > 0) + { + TowerInfoContainer *sepd_towers = + findNode::getClass(topNode, "TOWERS_SEPD"); + if (!sepd_towers) + { + n_notowernodecounter++; + if (Verbosity() > 0) + { + std::cout << PHWHERE << "calostatuscheck::process_event: missing TOWERS_SEPD" << std::endl; + } + return Fun4AllReturnCodes::ABORTEVENT; + } + const uint32_t ntowers = sepd_towers->size(); + uint16_t notinstr_count = 0; + for (uint32_t ch = 0; ch < ntowers; ++ch) + { + TowerInfo *tower = sepd_towers->get_tower_at_channel(ch); + if (tower->get_isNotInstr()) + { + ++notinstr_count; + } + } + + if (Verbosity() > 9) + { + std::cout << "CaloStatusSkimmer::process_event: event " << n_eventcounter << ", ntowers in sEPD = " << ntowers << ", not-instrumented(empty/missing pckt) towers in sEPD = " << notinstr_count << std::endl; + } + + if (notinstr_count >= m_sEPD_skim_threshold) + { + n_skimcounter++; + return Fun4AllReturnCodes::ABORTEVENT; + } + } + + if (m_ZDC_skim_threshold > 0) + { + TowerInfoContainer *zdc_towers = + findNode::getClass(topNode, "TOWERS_ZDC"); + if (!zdc_towers) + { + n_notowernodecounter++; + if (Verbosity() > 0) + { + std::cout << PHWHERE << "calostatuscheck::process_event: missing TOWERS_ZDC" << std::endl; + } + return Fun4AllReturnCodes::ABORTEVENT; + } + const uint32_t ntowers = zdc_towers->size(); + uint16_t notinstr_count = 0; + for (uint32_t ch = 0; ch < ntowers; ++ch) + { + TowerInfo *tower = zdc_towers->get_tower_at_channel(ch); + if (tower->get_isNotInstr()) + { + ++notinstr_count; + } + } + + if (Verbosity() > 9) + { + std::cout << "CaloStatusSkimmer::process_event: event " << n_eventcounter << ", ntowers in ZDC = " << ntowers << ", not-instrumented(empty/missing pckt) towers in ZDC = " << notinstr_count << std::endl; + } + + if (notinstr_count >= m_ZDC_skim_threshold) + { + n_skimcounter++; + return Fun4AllReturnCodes::ABORTEVENT; + } + } + + return Fun4AllReturnCodes::EVENT_OK; +} + +//____________________________________________________________________________.. +int CaloStatusSkimmer::End([[maybe_unused]] PHCompositeNode *topNode) +{ + std::cout << "CaloStatusSkimmer::End(PHCompositeNode *topNode) This is the End..." << std::endl; + std::cout << "Total events processed: " << n_eventcounter << std::endl; + std::cout << "Total events skimmed: " << n_skimcounter << std::endl; + std::cout << "Total events with missing tower nodes: " << n_notowernodecounter << std::endl; + + return Fun4AllReturnCodes::EVENT_OK; +} diff --git a/offline/packages/Skimmers/CaloStatusSkimmer/CaloStatusSkimmer.h b/offline/packages/Skimmers/CaloStatusSkimmer/CaloStatusSkimmer.h new file mode 100644 index 0000000000..433b8d08c0 --- /dev/null +++ b/offline/packages/Skimmers/CaloStatusSkimmer/CaloStatusSkimmer.h @@ -0,0 +1,64 @@ +// Tell emacs that this is a C++ source +// -*- C++ -*-. +#ifndef CALOSTATUSSKIMMER_H +#define CALOSTATUSSKIMMER_H + +#include + +#include +#include +#include +#include + +class PHCompositeNode; + +class CaloStatusSkimmer : public SubsysReco { +public: + CaloStatusSkimmer(const std::string &name = "CaloStatusSkimmer"); + + ~CaloStatusSkimmer() override = default; + + /** Called for each event. + This is where you do the real work. + */ + int process_event(PHCompositeNode *topNode) override; + + /// Called at the end of all processing. + int End(PHCompositeNode *topNode) override; + + void do_skim_EMCal( uint16_t threshold) { + m_EMC_skim_threshold = threshold; + } + + void do_skim_HCal( uint16_t threshold) { + m_HCal_skim_threshold = threshold; + } + + void do_skim_sEPD( uint16_t threshold) { + m_sEPD_skim_threshold = threshold; + } + + void do_skim_ZDC( uint16_t threshold) { + m_ZDC_skim_threshold = threshold; + } + +private: + uint32_t n_eventcounter{0}; + uint32_t n_skimcounter{0}; + uint32_t n_notowernodecounter{0}; + + // If the threshold is set to 0, then the skimming for that subsystem is disabled. If threshold is > 0, then the event is skimmed if nchannels >= threshold not-instrumented (empty/missing packet) channels in that subsystem. + uint16_t m_EMC_skim_threshold{192}; + // skim if nchannels >= this many not-instrumented (empty/missing packet) channels in EMCal + + uint16_t m_HCal_skim_threshold{192}; + // skim if nchannels >= this many not-instrumented (empty/missing packet) channels in HCal + + uint16_t m_sEPD_skim_threshold{1}; + // skim if nchannels >= this many not-instrumented (empty/missing packet) channels in sEPD + + uint16_t m_ZDC_skim_threshold{1}; + // skim if nchannels >= this many not-instrumented (empty/missing packet) channels in ZDC +}; + +#endif // CALOSTATUSSKIMMER_H diff --git a/offline/packages/Skimmers/CaloStatusSkimmer/Makefile.am b/offline/packages/Skimmers/CaloStatusSkimmer/Makefile.am new file mode 100644 index 0000000000..9f496c8587 --- /dev/null +++ b/offline/packages/Skimmers/CaloStatusSkimmer/Makefile.am @@ -0,0 +1,43 @@ +AUTOMAKE_OPTIONS = foreign + +AM_CPPFLAGS = \ + -I$(includedir) \ + -I$(OFFLINE_MAIN)/include \ + -isystem$(ROOTSYS)/include + +AM_LDFLAGS = \ + -L$(libdir) \ + -L$(OFFLINE_MAIN)/lib \ + -L$(OFFLINE_MAIN)/lib64 + +pkginclude_HEADERS = \ + CaloStatusSkimmer.h + +lib_LTLIBRARIES = \ + libCaloStatusSkimmer.la + +libCaloStatusSkimmer_la_SOURCES = \ + CaloStatusSkimmer.cc + +libCaloStatusSkimmer_la_LIBADD = \ + -lphool \ + -lSubsysReco \ + -lcalo_io + +BUILT_SOURCES = testexternals.cc + +noinst_PROGRAMS = \ + testexternals + +testexternals_SOURCES = testexternals.cc +testexternals_LDADD = libCaloStatusSkimmer.la + +testexternals.cc: + echo "//*** this is a generated file. Do not commit, do not edit" > $@ + echo "int main()" >> $@ + echo "{" >> $@ + echo " return 0;" >> $@ + echo "}" >> $@ + +clean-local: + rm -f $(BUILT_SOURCES) diff --git a/offline/packages/Skimmers/CaloStatusSkimmer/autogen.sh b/offline/packages/Skimmers/CaloStatusSkimmer/autogen.sh new file mode 100755 index 0000000000..dea267bbfd --- /dev/null +++ b/offline/packages/Skimmers/CaloStatusSkimmer/autogen.sh @@ -0,0 +1,8 @@ +#!/bin/sh +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +(cd $srcdir; aclocal -I ${OFFLINE_MAIN}/share;\ +libtoolize --force; automake -a --add-missing; autoconf) + +$srcdir/configure "$@" diff --git a/offline/packages/Skimmers/CaloStatusSkimmer/configure.ac b/offline/packages/Skimmers/CaloStatusSkimmer/configure.ac new file mode 100644 index 0000000000..d31173586b --- /dev/null +++ b/offline/packages/Skimmers/CaloStatusSkimmer/configure.ac @@ -0,0 +1,16 @@ +AC_INIT(calostatusskimmer,[1.00]) +AC_CONFIG_SRCDIR([configure.ac]) + +AM_INIT_AUTOMAKE +AC_PROG_CXX(CC g++) + +LT_INIT([disable-static]) + +dnl no point in suppressing warnings people should +dnl at least see them, so here we go for g++: -Wall +if test $ac_cv_prog_gxx = yes; then + CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wshadow -Werror" +fi + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/offline/packages/Skimmers/Trigger/TriggerDSTSkimmer.cc b/offline/packages/Skimmers/Trigger/TriggerDSTSkimmer.cc index b519fd472e..224d172a24 100644 --- a/offline/packages/Skimmers/Trigger/TriggerDSTSkimmer.cc +++ b/offline/packages/Skimmers/Trigger/TriggerDSTSkimmer.cc @@ -20,6 +20,12 @@ TriggerDSTSkimmer::TriggerDSTSkimmer(const std::string &name) //____________________________________________________________________________.. int TriggerDSTSkimmer::process_event(PHCompositeNode *topNode) { + + if ((accepted_events >= max_accept) && use_max_accept) + { + return Fun4AllReturnCodes::ABORTEVENT; + } + if (Verbosity() > 0) { if (ievent % 1000 == 0) @@ -45,7 +51,7 @@ int TriggerDSTSkimmer::process_event(PHCompositeNode *topNode) if (n_trigger_index != 0) { bool trigger_fired = false; - Gl1Packet *_gl1PacketInfo = findNode::getClass(topNode, "GL1Packet"); + Gl1Packet *_gl1PacketInfo = findNode::getClass(topNode, 14001); int gl1_trigger_vector_scaled[64] = {0}; if (_gl1PacketInfo) { @@ -61,6 +67,7 @@ int TriggerDSTSkimmer::process_event(PHCompositeNode *topNode) std::cout << "TriggerDSTSkimmer::process_event - Error - Can't find Trigger Node Gl1Packet therefore no selection can be made" << std::endl; return Fun4AllReturnCodes::ABORTEVENT; } + for (int it = 0; it < n_trigger_index; ++it) { if (gl1_trigger_vector_scaled[m_trigger_index[it]] == 1) @@ -74,5 +81,8 @@ int TriggerDSTSkimmer::process_event(PHCompositeNode *topNode) return Fun4AllReturnCodes::ABORTEVENT; } } + + accepted_events++; + return Fun4AllReturnCodes::EVENT_OK; } diff --git a/offline/packages/Skimmers/Trigger/TriggerDSTSkimmer.h b/offline/packages/Skimmers/Trigger/TriggerDSTSkimmer.h index dfb2c47a7c..9919df06b7 100644 --- a/offline/packages/Skimmers/Trigger/TriggerDSTSkimmer.h +++ b/offline/packages/Skimmers/Trigger/TriggerDSTSkimmer.h @@ -22,10 +22,22 @@ class TriggerDSTSkimmer : public SubsysReco void SetTrigger(std::vector &trigger_vector) {m_trigger_index = trigger_vector;} + void set_accept_max(int max_events) + { + use_max_accept = true; + max_accept = max_events; + return; + } + private: std::vector m_trigger_index{10}; int ievent{0}; + + int accepted_events{0}; + int max_accept{0}; + bool use_max_accept{false}; + }; #endif // JETDSTSKIMMER_H diff --git a/offline/packages/TrackingDiagnostics/KshortReconstruction.cc b/offline/packages/TrackingDiagnostics/KshortReconstruction.cc index f92bfc9581..6efbebf100 100644 --- a/offline/packages/TrackingDiagnostics/KshortReconstruction.cc +++ b/offline/packages/TrackingDiagnostics/KshortReconstruction.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -24,6 +25,7 @@ #include #pragma GCC diagnostic pop +#include #include #include #include @@ -56,11 +58,57 @@ int KshortReconstruction::process_event(PHCompositeNode* topNode) m_runNumber = m_evtNumber = -1; } + //Truth matching setup. Setting IDs and getting nodes + if (m_truth_match) + { + if (m_used_string) + { + m_mother_id = getMotherPDG(); + } + + m_truthinfo = findNode::getClass(topNode, "G4TruthInfo"); + + if (!m_truthinfo) //Missing truth info container. Disable truth matching + { + m_truth_match = false; + } + + } + + // Loop over tracks and check for close DCA match with all other tracks for (auto tr1_it = m_svtxTrackMap->begin(); tr1_it != m_svtxTrackMap->end(); ++tr1_it) { + auto id1 = tr1_it->first; auto *tr1 = tr1_it->second; + + //Truth matching. Let's see if this track came from the right mother + if (m_truth_match) + { + truth_particle_1 = getTruthTrack(tr1, topNode); + + if (truth_particle_1 == nullptr) + { + continue; + } + + int parent_id = truth_particle_1->get_parent_id(); + if (parent_id == 0) //Particle is primary. Trying to access its parent returns nullptr + { + continue; + } + + PHG4Particle *g4mother = m_truthinfo->GetParticle(parent_id); + + if (g4mother == nullptr || (abs(g4mother->get_pid()) != abs(m_mother_id))) //PID check + { + continue; + } + + truth_mother_id_particle_1 = g4mother->get_barcode(); + } + if (tr1->get_quality() > _qual_cut) { continue; @@ -92,8 +140,6 @@ int KshortReconstruction::process_event(PHCompositeNode* topNode) std::vector nstates1 = getTrackStates(tr1); unsigned int track1_mvtx_state_size = nstates1[0]; unsigned int track1_intt_state_size = nstates1[1]; - // unsigned int track1_tpc_state_size = nstates1[2]; - // unsigned int track1_mms_state_size = nstates1[3]; unsigned int track1_silicon_cluster_size = std::numeric_limits::quiet_NaN(); if (siliconseed) @@ -125,20 +171,56 @@ int KshortReconstruction::process_event(PHCompositeNode* topNode) Acts::Vector3 pos1(tr1->get_x(), tr1->get_y(), tr1->get_z()); Acts::Vector3 mom1(tr1->get_px(), tr1->get_py(), tr1->get_pz()); Acts::Vector3 dcaVals1 = calculateDca(tr1, mom1, pos1); - // first dca cuts if (fabs(dcaVals1(0)) < this_dca_cut || fabs(dcaVals1(1)) < this_dca_cut) - { - continue; - } - + { + // std::cout << " tr1 failed dca cuts " << std::endl; + continue; + } // look for close DCA matches with all other such tracks for (auto tr2_it = std::next(tr1_it); tr2_it != m_svtxTrackMap->end(); ++tr2_it) { auto id2 = tr2_it->first; auto *tr2 = tr2_it->second; + + //Truth matching. Let's see if this track came from the right mother + if (m_truth_match) + { + truth_particle_2 = getTruthTrack(tr2, topNode); + + if (truth_particle_2 == nullptr) + { + continue; + } + + int parent_id = truth_particle_2->get_parent_id(); + if (parent_id == 0) //Particle is primary. Trying to access its parent returns nullptr + { + continue; + } + PHG4Particle *g4mother = m_truthinfo->GetParticle(parent_id); + + if (g4mother == nullptr || (abs(g4mother->get_pid()) != abs(m_mother_id))) //PID check + { + continue; + } + + truth_mother_id_particle_2 = g4mother->get_barcode(); + + //Check that the two tracks came from the same mother + if (truth_mother_id_particle_1 != truth_mother_id_particle_2) + { + continue; + } + } + + // dca xy and dca z cut here compare to track dca cut + Acts::Vector3 pos2(tr2->get_x(), tr2->get_y(), tr2->get_z()); + Acts::Vector3 mom2(tr2->get_px(), tr2->get_py(), tr2->get_pz()); + Acts::Vector3 dcaVals2 = calculateDca(tr2, mom2, pos2); + if (tr2->get_quality() > _qual_cut) { - continue; + continue; } if (tr2->get_pt() < track_pt_cut) { @@ -161,15 +243,13 @@ int KshortReconstruction::process_event(PHCompositeNode* topNode) } if (_require_mvtx) { - continue; - } + continue; + } } std::vector nstates2 = getTrackStates(tr2); unsigned int track2_mvtx_state_size = nstates2[0]; unsigned int track2_intt_state_size = nstates2[1]; - // unsigned int track2_tpc_state_size = nstates2[2]; - // unsigned int track2_mms_state_size = nstates2[3]; unsigned int track2_silicon_cluster_size = std::numeric_limits::quiet_NaN(); if (siliconseed2) @@ -198,20 +278,16 @@ int KshortReconstruction::process_event(PHCompositeNode* topNode) } } - // dca xy and dca z cut here compare to track dca cut - Acts::Vector3 pos2(tr2->get_x(), tr2->get_y(), tr2->get_z()); - Acts::Vector3 mom2(tr2->get_px(), tr2->get_py(), tr2->get_pz()); - Acts::Vector3 dcaVals2 = calculateDca(tr2, mom2, pos2); - + if (fabs(dcaVals2(0)) < this_dca_cut2 || fabs(dcaVals2(1)) < this_dca_cut2) { continue; } - // find DCA of these two tracks + // find pair DCA of these two tracks if (Verbosity() > 3) { - std::cout << "Check DCA for tracks " << id1 << " and " << id2 << std::endl; + std::cout << "Check pair DCA for tracks " << id1 << " and " << id2 << std::endl; } if (tr1->get_charge() == tr2->get_charge()) @@ -233,7 +309,6 @@ int KshortReconstruction::process_event(PHCompositeNode* topNode) // This presently assumes straight line tracks to get a rough answer // Should update to use circles instead? findPcaTwoTracks(pos1, pos2, mom1, mom2, pca_rel1, pca_rel2, pair_dca); - // tracks with small relative pca are k short candidates if (abs(pair_dca) < pair_dca_cut) { @@ -260,36 +335,57 @@ int KshortReconstruction::process_event(PHCompositeNode* topNode) // if(pair_dca_proj > pair_dca_cut) continue; - // invariant mass is calculated in this method - fillHistogram(projected_mom1, projected_mom2, recomass, invariantMass, invariantPt, invariantPhi, rapidity, pseudorapidity); - fillNtp(tr1, tr2, dcaVals1, dcaVals2, pca_rel1, pca_rel2, pair_dca, invariantMass, invariantPt, invariantPhi, rapidity, pseudorapidity, projected_pos1, projected_pos2, projected_mom1, projected_mom2, pca_rel1_proj, pca_rel2_proj, pair_dca_proj, track1_silicon_cluster_size, track2_silicon_cluster_size, track1_mvtx_cluster_size, track1_mvtx_state_size, track1_intt_cluster_size, track1_intt_state_size, track2_mvtx_cluster_size, track2_mvtx_state_size, track2_intt_cluster_size, track2_intt_state_size, m_runNumber, m_evtNumber); - - if (Verbosity() > 1) - { - std::cout << " Accepted Track Pair" << std::endl; - std::cout << " id1 " << id1 << " id2 " << id2 << std::endl; - std::cout << " crossing1 " << crossing1 << " crossing2 " << crossing2 << std::endl; - std::cout << " invariant mass: " << invariantMass << std::endl; - std::cout << " track1 dca_cut: " << this_dca_cut << " track2 dca_cut: " << this_dca_cut2 << std::endl; - std::cout << " dca3dxy1,dca3dz1,phi1: " << dcaVals1 << std::endl; - std::cout << " dca3dxy2,dca3dz2,phi2: " << dcaVals2 << std::endl; - std::cout << "Initial: pca_rel1: " << pca_rel1 << " pca_rel2: " << pca_rel2 << std::endl; - std::cout << " Initial: mom1: " << mom1 << " mom2: " << mom2 << std::endl; - std::cout << "Proj_pca_rel: proj_pos1: " << projected_pos1 << " proj_pos2: " << projected_pos2 << " proj_mom1: " << projected_mom1 << " proj_mom2: " << projected_mom2 << std::endl; - std::cout << " Relative PCA = " << abs(pair_dca) << " pca_cut = " << pair_dca_cut << std::endl; - std::cout << " charge 1: " << tr1->get_charge() << " charge2: " << tr2->get_charge() << std::endl; - std::cout << "found viable projection" << std::endl; - std::cout << "Final: pca_rel1_proj: " << pca_rel1_proj << " pca_rel2_proj: " << pca_rel2_proj << " mom1: " << projected_mom1 << " mom2: " << projected_mom2 << std::endl - << std::endl; - } - + // calculate both ways if decaymass1 and decaymass2 are different + int ncombinations = 1; + if(decaymass1 != decaymass2) + { + ncombinations = 2; + } + for(int icomb=0;icomb < ncombinations; ++icomb) + { + float decaymassa = decaymass1; + float decaymassb = decaymass2; + if(icomb == 1) + { + decaymassa = decaymass2; + decaymassb = decaymass1; + } + + // invariant mass is calculated in this method + fillHistogram(projected_mom1, projected_mom2, recomass, invariantMass, invariantPt, invariantPhi, rapidity, pseudorapidity,decaymassa, decaymassb); + fillNtp(tr1, tr2, decaymassa, decaymassb, dcaVals1, dcaVals2, pca_rel1, pca_rel2, pair_dca, invariantMass, invariantPt, invariantPhi, rapidity, pseudorapidity, projected_pos1, projected_pos2, projected_mom1, projected_mom2, pca_rel1_proj, pca_rel2_proj, pair_dca_proj, track1_silicon_cluster_size, track2_silicon_cluster_size, track1_mvtx_cluster_size, track1_mvtx_state_size, track1_intt_cluster_size, track1_intt_state_size, track2_mvtx_cluster_size, track2_mvtx_state_size, track2_intt_cluster_size, track2_intt_state_size, m_runNumber, m_evtNumber); + + if (Verbosity() > 1) + { + std::cout << "Accepted Track Pair" << " id1 " << id1 << " id2 " << id2 << " crossing1 " << crossing1 << " crossing2 " << crossing2 << std::endl; + std::cout << " invariant mass: " << invariantMass << " decaymassa " << decaymassa << " decaymassb " << decaymassb << std::endl; + std::cout << " track1 dca_cut: " << this_dca_cut << " track2 dca_cut: " << this_dca_cut2 << std::endl; + std::cout << " dca3dxy1,dca3dz1,phi1: " << dcaVals1(0) << " " << dcaVals1(1) << " " << dcaVals1(2) << std::endl; + std::cout << " dca3dxy2,dca3dz2,phi2: " << dcaVals2(0) << " " << dcaVals2(1) << " " << dcaVals2(2) << std::endl; + std::cout << " Initial: pca_rel1: " << pca_rel1(0) << " " << pca_rel1(1) << " " << pca_rel1(2) << std::endl; + std::cout << " Initial: pca_rel2: " << pca_rel2(0) << " " << pca_rel2(1) << " " << pca_rel2(2) << std::endl; + std::cout << " Initial: mom1: " << mom1(0) << " " << mom1(1) << " " << mom1(2) << std::endl; + std::cout << " Initial: mom2: " << mom2(0) << " " << mom2(1) << " " << mom2(2) << std::endl; + std::cout << " Proj_pca_rel: proj_pos1: " << projected_pos1(0) << " " << projected_pos1(1) << " " << projected_pos1(2) << std::endl; + std::cout << " Proj_pca_rel: proj_pos2: " << projected_pos2(0) << " " << projected_pos2(1) << " " << projected_pos2(2) << std::endl; + std::cout << " proj_mom1: " << projected_mom1(0) << " " << projected_mom1(1) << " " << projected_mom1(2) << std::endl; + std::cout << " proj_mom2: " << projected_mom2(0) << " " << projected_mom2(1) << " " << projected_mom2(2) << std::endl; + std::cout << " Relative PCA = " << abs(pair_dca) << " pca_cut = " << pair_dca_cut << std::endl; + std::cout << " charge 1: " << tr1->get_charge() << " charge2: " << tr2->get_charge() << std::endl; + std::cout << " found viable projection" << std::endl; + std::cout << " Final: pca_rel1_proj: " << pca_rel1_proj(0) << " " << pca_rel1_proj(1) << " " << pca_rel1_proj(2) << std::endl; + std::cout << " Final: pca_rel2_proj: " << pca_rel2_proj(0) << " " << pca_rel2_proj(1) << " " << pca_rel2_proj(2) << std::endl; + std::cout << " Final: mom1: " << projected_mom1(0) << " " << projected_mom1(1) << " " << projected_mom1(2) << std::endl; + std::cout << " Final: mom2: " << projected_mom2(0) << " " << projected_mom2(1) << " " << projected_mom2(2) << std::endl; + } + } if (m_save_tracks) - { - m_output_trackMap = findNode::getClass(topNode, m_output_trackMap_node_name); - m_output_trackMap->insertWithKey(tr1, tr1->get_id()); - m_output_trackMap->insertWithKey(tr2, tr2->get_id()); - } - + { + m_output_trackMap = findNode::getClass(topNode, m_output_trackMap_node_name); + m_output_trackMap->insertWithKey(tr1, tr1->get_id()); + m_output_trackMap->insertWithKey(tr2, tr2->get_id()); + } + } } } @@ -327,9 +423,7 @@ std::vector KshortReconstruction::getTrackStates(SvtxTrack *track) nmmsstate++; break; default: - std::cout << PHWHERE << " unknown key " << stateckey << std::endl; - gSystem->Exit(1); - exit(1); + break; } } nstates.push_back(nmapsstate); @@ -340,6 +434,53 @@ std::vector KshortReconstruction::getTrackStates(SvtxTrack *track) return nstates; } +void KshortReconstruction::fillNtp(SvtxTrack* track1, SvtxTrack* track2, float mass1, float mass2, Acts::Vector3 dcavals1, Acts::Vector3 dcavals2, Acts::Vector3 pca_rel1, Acts::Vector3 pca_rel2, double pair_dca, double invariantMass, double invariantPt, float invariantPhi, float rapidity, float pseudorapidity, Eigen::Vector3d projected_pos1, Eigen::Vector3d projected_pos2, Eigen::Vector3d projected_mom1, Eigen::Vector3d projected_mom2, Acts::Vector3 pca_rel1_proj, Acts::Vector3 pca_rel2_proj, double pair_dca_proj, unsigned int track1_silicon_cluster_size, unsigned int track2_silicon_cluster_size, unsigned int track1_mvtx_cluster_size, unsigned int track1_mvtx_state_size, unsigned int track1_intt_cluster_size, unsigned int track1_intt_state_size, unsigned int track2_mvtx_cluster_size, unsigned int track2_mvtx_state_size, unsigned int track2_intt_cluster_size, unsigned int track2_intt_state_size, int runNumber, int eventNumber) +{ + double px1 = track1->get_px(); + double py1 = track1->get_py(); + double pz1 = track1->get_pz(); + auto *tpcSeed1 = track1->get_tpc_seed(); + size_t tpcClusters1 = tpcSeed1->size_cluster_keys(); + double eta1 = asinh(pz1 / sqrt(pow(px1, 2) + pow(py1, 2))); + + double px2 = track2->get_px(); + double py2 = track2->get_py(); + double pz2 = track2->get_pz(); + auto *tpcSeed2 = track2->get_tpc_seed(); + size_t tpcClusters2 = tpcSeed2->size_cluster_keys(); + double eta2 = asinh(pz2 / sqrt(pow(px2, 2) + pow(py2, 2))); + + auto vtxid = track1->get_vertex_id(); + + int ntracks_vertex = 0; + Acts::Vector3 vertex(0, 0, track1->get_z()); // fake primary vertex + auto *svtxVertex = m_vertexMap->get(vtxid); + if (svtxVertex) + { + vertex(0) = svtxVertex->get_x(); + vertex(1) = svtxVertex->get_y(); + vertex(2) = svtxVertex->get_z(); + ntracks_vertex = svtxVertex->size_tracks(); + } + + Acts::Vector3 pathLength = (pca_rel1 + pca_rel2) * 0.5 - vertex; + Acts::Vector3 pathLength_proj = (pca_rel1_proj + pca_rel2_proj) * 0.5 - vertex; + + float mag_pathLength = sqrt(pow(pathLength(0), 2) + pow(pathLength(1), 2) + pow(pathLength(2), 2)); + float mag_pathLength_proj = sqrt(pow(pathLength_proj(0), 2) + pow(pathLength_proj(1), 2) + pow(pathLength_proj(2), 2)); + + Acts::Vector3 projected_momentum = projected_mom1 + projected_mom2; + float cos_theta_reco = pathLength_proj.dot(projected_momentum) / (projected_momentum.norm() * pathLength_proj.norm()); + + + float reco_info[] = {(float) track1->get_id(), mass1, (float) track1->get_crossing(), track1->get_x(), track1->get_y(), track1->get_z(), track1->get_px(), track1->get_py(), track1->get_pz(), (float) dcavals1(0), (float) dcavals1(1), (float) dcavals1(2), (float) pca_rel1(0), (float) pca_rel1(1), (float) pca_rel1(2), (float) eta1, (float) track1->get_charge(), (float) tpcClusters1, (float) track2->get_id(), mass2, (float) track2->get_crossing(), track2->get_x(), track2->get_y(), track2->get_z(), track2->get_px(), track2->get_py(), track2->get_pz(), (float) dcavals2(0), (float) dcavals2(1), (float) dcavals2(2), (float) pca_rel2(0), (float) pca_rel2(1), (float) pca_rel2(2), (float) eta2, (float) track2->get_charge(), (float) tpcClusters2, (float) ntracks_vertex, (float) vertex(0), (float) vertex(1), (float) vertex(2), (float) pair_dca, (float) invariantMass, (float) invariantPt, invariantPhi, (float) pathLength(0), (float) pathLength(1), (float) pathLength(2), mag_pathLength, rapidity, pseudorapidity, (float) projected_pos1(0), (float) projected_pos1(1), (float) projected_pos1(2), (float) projected_pos2(0), (float) projected_pos2(1), (float) projected_pos2(2), (float) projected_mom1(0), (float) projected_mom1(1), (float) projected_mom1(2), (float) projected_mom2(0), (float) projected_mom2(1), (float) projected_mom2(2), (float) pca_rel1_proj(0), (float) pca_rel1_proj(1), (float) pca_rel1_proj(2), (float) pca_rel2_proj(0), (float) pca_rel2_proj(1), (float) pca_rel2_proj(2), (float) pair_dca_proj, (float) pathLength_proj(0), (float) pathLength_proj(1), (float) pathLength_proj(2), mag_pathLength_proj, track1->get_quality(), track2->get_quality(), cos_theta_reco, (float) track1_silicon_cluster_size, (float) track2_silicon_cluster_size, (float) track1_mvtx_cluster_size, (float) track1_mvtx_state_size, (float) track1_intt_cluster_size, (float) track1_intt_state_size, (float) track2_mvtx_cluster_size, (float) track2_mvtx_state_size, (float) track2_intt_cluster_size, (float) track2_intt_state_size, (float) runNumber, (float) eventNumber}; + + ntp_reco_info->Fill(reco_info); +} + + + +/* void KshortReconstruction::fillNtp(SvtxTrack* track1, SvtxTrack* track2, Acts::Vector3 dcavals1, Acts::Vector3 dcavals2, Acts::Vector3 pca_rel1, Acts::Vector3 pca_rel2, double pair_dca, double invariantMass, double invariantPt, float invariantPhi, float rapidity, float pseudorapidity, Eigen::Vector3d projected_pos1, Eigen::Vector3d projected_pos2, Eigen::Vector3d projected_mom1, Eigen::Vector3d projected_mom2, Acts::Vector3 pca_rel1_proj, Acts::Vector3 pca_rel2_proj, double pair_dca_proj, unsigned int track1_silicon_cluster_size, unsigned int track2_silicon_cluster_size, unsigned int track1_mvtx_cluster_size, unsigned int track1_mvtx_state_size, unsigned int track1_intt_cluster_size, unsigned int track1_intt_state_size, unsigned int track2_mvtx_cluster_size, unsigned int track2_mvtx_state_size, unsigned int track2_intt_cluster_size, unsigned int track2_intt_state_size, int runNumber, int eventNumber) { double px1 = track1->get_px(); @@ -381,36 +522,37 @@ void KshortReconstruction::fillNtp(SvtxTrack* track1, SvtxTrack* track2, Acts::V ntp_reco_info->Fill(reco_info); } +*/ -void KshortReconstruction::fillHistogram(Eigen::Vector3d mom1, Eigen::Vector3d mom2, TH1* massreco, double& invariantMass, double& invariantPt, float& invariantPhi, float& rapidity, float& pseudorapidity) +void KshortReconstruction::fillHistogram(Eigen::Vector3d mom1, Eigen::Vector3d mom2, TH1* massreco, double& invariantMass, double& invariantPt, float& invariantPhi, float& rapidity, float& pseudorapidity, float &decaymassa, float &decaymassb) { - double E1 = sqrt(pow(mom1(0), 2) + pow(mom1(1), 2) + pow(mom1(2), 2) + pow(decaymass, 2)); - double E2 = sqrt(pow(mom2(0), 2) + pow(mom2(1), 2) + pow(mom2(2), 2) + pow(decaymass, 2)); - + double E1 = sqrt(pow(mom1(0), 2) + pow(mom1(1), 2) + pow(mom1(2), 2) + pow(decaymassa, 2)); + double E2 = sqrt(pow(mom2(0), 2) + pow(mom2(1), 2) + pow(mom2(2), 2) + pow(decaymassb, 2)); + TLorentzVector v1(mom1(0), mom1(1), mom1(2), E1); TLorentzVector v2(mom2(0), mom2(1), mom2(2), E2); - + TLorentzVector tsum; tsum = v1 + v2; - + rapidity = tsum.Rapidity(); pseudorapidity = tsum.Eta(); invariantMass = tsum.M(); invariantPt = tsum.Pt(); invariantPhi = tsum.Phi(); - - if (Verbosity() > 2) - { - std::cout << "px1: " << mom1(0) << " py1: " << mom1(1) << " pz1: " << mom1(2) << " E1: " << E1 << std::endl; - std::cout << "px2: " << mom2(0) << " py2: " << mom2(1) << " pz2: " << mom2(2) << " E2: " << E2 << std::endl; - std::cout << "tsum: " << tsum(0) << " " << tsum(1) << " " << tsum(2) << " " << tsum(3) << std::endl; - std::cout << "invariant mass: " << invariantMass << " invariant Pt: " << invariantPt << " invariantPhi: " << invariantPhi << std::endl; - } - + + if (Verbosity() > 1) + { + std::cout << "px1: " << mom1(0) << " py1: " << mom1(1) << " pz1: " << mom1(2) << " mass " << decaymassa << " E1: " << E1 << std::endl; + std::cout << "px2: " << mom2(0) << " py2: " << mom2(1) << " pz2: " << mom2(2) << " mass2 " << decaymassb << " E2: " << E2 << std::endl; + std::cout << "tsum: " << tsum(0) << " " << tsum(1) << " " << tsum(2) << " " << tsum(3) << std::endl; + std::cout << "invariant mass: " << invariantMass << " invariant Pt: " << invariantPt << " invariantPhi: " << invariantPhi << std::endl; + } + if (invariantPt > invariant_pt_cut) - { - massreco->Fill(invariantMass); - } + { + massreco->Fill(invariantMass); + } } bool KshortReconstruction::projectTrackToPoint(SvtxTrack* track, Eigen::Vector3d PCA, Eigen::Vector3d& pos, Eigen::Vector3d& mom) @@ -529,6 +671,72 @@ Acts::Vector3 KshortReconstruction::getVertex(SvtxTrack* track) return vertex; } +void KshortReconstruction::findPcaTwoTracks(const Acts::Vector3& pos1, const Acts::Vector3& pos2, Acts::Vector3 mom1, Acts::Vector3 mom2, Acts::Vector3& pca1, Acts::Vector3& pca2, double& dca) const +{ + TLorentzVector v1; + TLorentzVector v2; + + double px1 = mom1(0); + double py1 = mom1(1); + double pz1 = mom1(2); + double px2 = mom2(0); + double py2 = mom2(1); + double pz2 = mom2(2); + + // calculate lorentz vector + const Eigen::Vector3d& a1 = pos1; + const Eigen::Vector3d& a2 = pos2; + + Eigen::Vector3d b1(px1, py1, pz1); + Eigen::Vector3d b2(px2, py2, pz2); + + // The shortest distance between two skew lines described by + // a1 + c * b1 + // a2 + d * b2 + // where a1, a2, are vectors representing points on the lines, b1, b2 are direction vectors, and c and d are scalars + // dca = (b1 x b2) .(a2-a1) / |b1 x b2| + + // bcrossb/mag_bcrossb is a unit vector perpendicular to both direction vectors b1 and b2 + auto bcrossb = b1.cross(b2); + auto mag_bcrossb = bcrossb.norm(); + // a2-a1 is the vector joining any arbitrary points on the two lines + auto aminusa = a2 - a1; + + // The DCA of these two lines is the projection of a2-a1 along the direction of the perpendicular to both + // remember that a2-a1 is longer than (or equal to) the dca by definition + dca = 999; + if (mag_bcrossb != 0) + { + dca = bcrossb.dot(aminusa) / mag_bcrossb; + } + else + { + return; // same track, skip combination + } + + // get the points at which the normal to the lines intersect the lines, where the lines are perpendicular + + // coderabbit suggestion + const double b1b1 = b1.dot(b1); + const double b2b2 = b2.dot(b2); + const double b1b2 = b1.dot(b2); + const double denom = b1b1 * b2b2 - b1b2 * b1b2; + if (std::abs(denom) < 1e-12) + { + return; + } + const Eigen::Vector3d w0 = a1 - a2; + const double c = (b1b2 * b2.dot(w0) - b2b2 * b1.dot(w0)) / denom; + const double d = (b1b1 * b2.dot(w0) - b1b2 * b1.dot(w0)) / denom; + + // then the points of closest approach are: + pca1 = a1 + c * b1; + pca2 = a2 + d * b2; + + return; +} + +/* void KshortReconstruction::findPcaTwoTracks(const Acts::Vector3& pos1, const Acts::Vector3& pos2, Acts::Vector3 mom1, Acts::Vector3 mom2, Acts::Vector3& pca1, Acts::Vector3& pca2, double& dca) const { TLorentzVector v1; @@ -593,6 +801,7 @@ void KshortReconstruction::findPcaTwoTracks(const Acts::Vector3& pos1, const Act return; } +*/ KshortReconstruction::KshortReconstruction(const std::string& name) : SubsysReco(name) @@ -603,7 +812,7 @@ Acts::Vector3 KshortReconstruction::calculateDca(SvtxTrack* track, const Acts::V { // For the purposes of this module, we set default values to prevent this track from being rejected if the dca calc fails Acts::Vector3 r = momentum.cross(Acts::Vector3(0., 0., 1.)); - float phi = atan2(r(1), r(0)); + float phi = std::atan2(r(1), r(0)); Acts::Vector3 outVals(track_dca_cut*1.1, track_dca_cut*1.1, phi); auto vtxid = track->get_vertex_id(); if (!m_vertexMap) @@ -638,7 +847,7 @@ Acts::Vector3 KshortReconstruction::calculateDca(SvtxTrack* track, const Acts::V outVals(0) = abs(dca3dxy); outVals(1) = abs(dca3dz); outVals(2) = phi; - + if (Verbosity() > 4) { std::cout << " pre-position: " << position << std::endl; @@ -653,7 +862,8 @@ int KshortReconstruction::InitRun(PHCompositeNode* topNode) { const char* cfilepath = filepath.c_str(); fout = new TFile(cfilepath, "recreate"); - ntp_reco_info = new TNtuple("ntp_reco_info", "decay_pairs", "id1:crossing1:x1:y1:z1:px1:py1:pz1:dca3dxy1:dca3dz1:phi1:pca_rel1_x:pca_rel1_y:pca_rel1_z:eta1:charge1:tpcClusters_1:id2:crossing2:x2:y2:z2:px2:py2:pz2:dca3dxy2:dca3dz2:phi2:pca_rel2_x:pca_rel2_y:pca_rel2_z:eta2:charge2:tpcClusters_2:vertex_x:vertex_y:vertex_z:pair_dca:invariant_mass:invariant_pt:invariantPhi:pathlength_x:pathlength_y:pathlength_z:pathlength:rapidity:pseudorapidity:projected_pos1_x:projected_pos1_y:projected_pos1_z:projected_pos2_x:projected_pos2_y:projected_pos2_z:projected_mom1_x:projected_mom1_y:projected_mom1_z:projected_mom2_x:projected_mom2_y:projected_mom2_z:projected_pca_rel1_x:projected_pca_rel1_y:projected_pca_rel1_z:projected_pca_rel2_x:projected_pca_rel2_y:projected_pca_rel2_z:projected_pair_dca:projected_pathlength_x:projected_pathlength_y:projected_pathlength_z:projected_pathlength:quality1:quality2:cosThetaReco:track1_silicon_clusters:track2_silicon_clusters:track1_mvtx_clusters:track1_mvtx_states:track1_intt_clusters:track1_intt_states:track2_mvtx_clusters:track2_mvtx_states:track2_intt_clusters:track2_intt_states:runNumber:eventNumber"); + +ntp_reco_info = new TNtuple("ntp_reco_info", "decay_pairs", "id1:mass1:crossing1:x1:y1:z1:px1:py1:pz1:dca3dxy1:dca3dz1:phi1:pca_rel1_x:pca_rel1_y:pca_rel1_z:eta1:charge1:tpcClusters_1:id2:mass2:crossing2:x2:y2:z2:px2:py2:pz2:dca3dxy2:dca3dz2:phi2:pca_rel2_x:pca_rel2_y:pca_rel2_z:eta2:charge2:tpcClusters_2:ntracks_vertex:vertex_x:vertex_y:vertex_z:pair_dca:invariant_mass:invariant_pt:invariantPhi:pathlength_x:pathlength_y:pathlength_z:pathlength:rapidity:pseudorapidity:projected_pos1_x:projected_pos1_y:projected_pos1_z:projected_pos2_x:projected_pos2_y:projected_pos2_z:projected_mom1_x:projected_mom1_y:projected_mom1_z:projected_mom2_x:projected_mom2_y:projected_mom2_z:projected_pca_rel1_x:projected_pca_rel1_y:projected_pca_rel1_z:projected_pca_rel2_x:projected_pca_rel2_y:projected_pca_rel2_z:projected_pair_dca:projected_pathlength_x:projected_pathlength_y:projected_pathlength_z:projected_pathlength:quality1:quality2:cosThetaReco:track1_silicon_clusters:track2_silicon_clusters:track1_mvtx_clusters:track1_mvtx_states:track1_intt_clusters:track1_intt_states:track2_mvtx_clusters:track2_mvtx_states:track2_intt_clusters:track2_intt_states:runNumber:eventNumber"); getNodes(topNode); @@ -716,3 +926,55 @@ int KshortReconstruction::getNodes(PHCompositeNode* topNode) return Fun4AllReturnCodes::EVENT_OK; } + +int KshortReconstruction::getMotherPDG() +{ + TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(m_mother_name.c_str()); + if (!particle) + { + if (Verbosity() > 2) + { + std::cout << "Error: Unknown particle name '" << m_mother_name << "'" << std::endl; + } + return -1; // or throw exception + } + return particle->PdgCode(); +} + +PHG4Particle *KshortReconstruction::getTruthTrack(SvtxTrack *thisTrack, PHCompositeNode *topNode) +{ + /* + * There are two methods for getting the truth rack from the reco track + * 1. (recommended) Use the reco -> truth tables (requires SvtxPHG4ParticleMap). Introduced Summer of 2022 + * 2. Get truth track via nClusters. Older method and will work with older DSTs + */ + + PHG4Particle *particle = nullptr; + + SvtxPHG4ParticleMap *dst_reco_truth_map = findNode::getClass(topNode, "SvtxPHG4ParticleMap"); + if (dst_reco_truth_map && dst_reco_truth_map->processed()) + { + std::map> truth_set = dst_reco_truth_map->get(thisTrack->get_id()); + if (!truth_set.empty()) + { + std::pair> best_weight = *truth_set.rbegin(); + int best_truth_id = *best_weight.second.rbegin(); + particle = m_truthinfo->GetParticle(best_truth_id); + } + } + else + { + if (!m_svtx_evalstack) + { + m_svtx_evalstack = new SvtxEvalStack(topNode); + trackeval = m_svtx_evalstack->get_track_eval(); + //trutheval = m_svtx_evalstack->get_truth_eval(); + //vertexeval = m_svtx_evalstack->get_vertex_eval(); + } + + m_svtx_evalstack->next_event(topNode); + + particle = trackeval->max_truth_particle_by_nclusters(thisTrack); + } + return particle; +} diff --git a/offline/packages/TrackingDiagnostics/KshortReconstruction.h b/offline/packages/TrackingDiagnostics/KshortReconstruction.h index 3ff1ae3501..27d6e3f601 100644 --- a/offline/packages/TrackingDiagnostics/KshortReconstruction.h +++ b/offline/packages/TrackingDiagnostics/KshortReconstruction.h @@ -5,6 +5,11 @@ #include +#include +#include +#include +#include + #include class TFile; @@ -33,14 +38,25 @@ class KshortReconstruction : public SubsysReco void setPairDCACut(double cut) { pair_dca_cut = cut; } void setTrackDCACut(double cut) { track_dca_cut = cut; } void setRequireMVTX(bool set) { _require_mvtx = set; } - void setDecayMass(float decayMassSet) { decaymass = decayMassSet; } //(muons decaymass = 0.1057) (pions = 0.13957) (electron = 0.000511) + void setDecayMass1(float decayMassSet) { decaymass1 = decayMassSet; } //(muons decaymass = 0.1057) (pions = 0.13957) (electron = 0.000511) + void setDecayMass2(float decayMassSet) { decaymass2 = decayMassSet; } //(muons decaymass = 0.1057) (pions = 0.13957) (electron = 0.000511) + // void setDecayMass(float decayMassSet) { decaymass = decayMassSet; } //(muons decaymass = 0.1057) (pions = 0.13957) (electron = 0.000511) void set_output_file(const std::string& outputfile) { filepath = outputfile; } void save_tracks(bool save = true) { m_save_tracks = save; } + //Truth matching code + void truthMatch(bool match = true) { m_truth_match = match; } + void setMotherID(const std::string &id = "K_S0") { m_mother_name = id; m_used_string = true; } + void setMotherID(int id = 310) { m_mother_id = id; m_used_string = false; } + private: - void fillNtp(SvtxTrack* track1, SvtxTrack* track2, Acts::Vector3 dcavals1, Acts::Vector3 dcavals2, Acts::Vector3 pca_rel1, Acts::Vector3 pca_rel2, double pair_dca, double invariantMass, double invariantPt, float invariantPhi, float rapidity, float pseudorapidity, Eigen::Vector3d projected_pos1, Eigen::Vector3d projected_pos2, Eigen::Vector3d projected_mom1, Eigen::Vector3d projected_mom2, Acts::Vector3 pca_rel1_proj, Acts::Vector3 pca_rel2_proj, double pair_dca_proj,unsigned int track1_silicon_cluster_size, unsigned int track2_silicon_cluster_size, unsigned int track1_mvtx_cluster_size, unsigned int track1_mvtx_state_size, unsigned int track1_intt_cluster_size, unsigned int track1_intt_state_size, unsigned int track2_mvtx_cluster_size, unsigned int track2_mvtx_state_size, unsigned int track2_intt_cluster_size, unsigned int track2_intt_state_size, int runNumber, int eventNumber); + void fillNtp(SvtxTrack* track1, SvtxTrack* track2, float mass1, float mass2, Acts::Vector3 dcavals1, Acts::Vector3 dcavals2, Acts::Vector3 pca_rel1, Acts::Vector3 pca_rel2, double pair_dca, double invariantMass, double invariantPt, float invariantPhi, float rapidity, float pseudorapidity, Eigen::Vector3d projected_pos1, Eigen::Vector3d projected_pos2, Eigen::Vector3d projected_mom1, Eigen::Vector3d projected_mom2, Acts::Vector3 pca_rel1_proj, Acts::Vector3 pca_rel2_proj, double pair_dca_proj,unsigned int track1_silicon_cluster_size, unsigned int track2_silicon_cluster_size, unsigned int track1_mvtx_cluster_size, unsigned int track1_mvtx_state_size, unsigned int track1_intt_cluster_size, unsigned int track1_intt_state_size, unsigned int track2_mvtx_cluster_size, unsigned int track2_mvtx_state_size, unsigned int track2_intt_cluster_size, unsigned int track2_intt_state_size, int runNumber, int eventNumber); - void fillHistogram(Eigen::Vector3d mom1, Eigen::Vector3d mom2, TH1* massreco, double& invariantMass, double& invariantPt, float& invariantPhi, float& rapidity, float& pseudorapidity); + // void fillNtp(SvtxTrack* track1, SvtxTrack* track2, Acts::Vector3 dcavals1, Acts::Vector3 dcavals2, Acts::Vector3 pca_rel1, Acts::Vector3 pca_rel2, double pair_dca, double invariantMass, double invariantPt, float invariantPhi, float rapidity, float pseudorapidity, Eigen::Vector3d projected_pos1, Eigen::Vector3d projected_pos2, Eigen::Vector3d projected_mom1, Eigen::Vector3d projected_mom2, Acts::Vector3 pca_rel1_proj, Acts::Vector3 pca_rel2_proj, double pair_dca_proj,unsigned int track1_silicon_cluster_size, unsigned int track2_silicon_cluster_size, unsigned int track1_mvtx_cluster_size, unsigned int track1_mvtx_state_size, unsigned int track1_intt_cluster_size, unsigned int track1_intt_state_size, unsigned int track2_mvtx_cluster_size, unsigned int track2_mvtx_state_size, unsigned int track2_intt_cluster_size, unsigned int track2_intt_state_size, int runNumber, int eventNumber); + + void fillHistogram(Eigen::Vector3d mom1, Eigen::Vector3d mom2, TH1* massreco, double& invariantMass, double& invariantPt, float& invariantPhi, float& rapidity, float& pseudorapidity, float& decaymassa, float& decaymassb); + + // void fillHistogram(Eigen::Vector3d mom1, Eigen::Vector3d mom2, TH1* massreco, double& invariantMass, double& invariantPt, float& invariantPhi, float& rapidity, float& pseudorapidity); // void findPcaTwoTracks(SvtxTrack *track1, SvtxTrack *track2, Acts::Vector3& pca1, Acts::Vector3& pca2, double& dca); void findPcaTwoTracks(const Acts::Vector3& pos1, const Acts::Vector3& pos2, Acts::Vector3 mom1, Acts::Vector3 mom2, Acts::Vector3& pca1, Acts::Vector3& pca2, double& dca) const; @@ -61,7 +77,10 @@ class KshortReconstruction : public SubsysReco SvtxVertexMap* m_vertexMap {nullptr}; std::string filepath {""}; - float decaymass {0.13957}; // pion decay mass + float decaymass1 = 0.13957; // pion decay mass + float decaymass2 = 0.13957; // pion decay mass + + //float decaymass {0.13957}; // pion decay mass bool _require_mvtx {true}; double _qual_cut {1000.0}; double pair_dca_cut {0.05}; // kshort relative cut 500 microns @@ -74,6 +93,25 @@ class KshortReconstruction : public SubsysReco bool m_save_tracks {false}; SvtxTrackMap *m_output_trackMap {nullptr}; std::string m_output_trackMap_node_name {"KshortReconstruction_SvtxTrackMap"}; + + //Truth matching code + bool m_truth_match {false}; + bool m_used_string {false}; + std::string m_mother_name {"K_S0"}; + int m_mother_id {310}; + + PHG4Particle *truth_particle_1 {nullptr}; + PHG4Particle *truth_particle_2 {nullptr}; + int truth_mother_id_particle_1 {0}; + int truth_mother_id_particle_2 {0}; + + PHG4TruthInfoContainer *m_truthinfo {nullptr}; + SvtxEvalStack *m_svtx_evalstack {nullptr}; + SvtxTrackEval *trackeval {nullptr}; + + int getMotherPDG(); + PHG4Particle *getTruthTrack(SvtxTrack *thisTrack, PHCompositeNode *topNode); + }; #endif // KSHORTRECONSTRUCTION_H diff --git a/offline/packages/TrackingDiagnostics/TrackResiduals.cc b/offline/packages/TrackingDiagnostics/TrackResiduals.cc index 894dfb4d3c..d029ded711 100644 --- a/offline/packages/TrackingDiagnostics/TrackResiduals.cc +++ b/offline/packages/TrackingDiagnostics/TrackResiduals.cc @@ -1728,6 +1728,7 @@ void TrackResiduals::createBranches() m_clustree->Branch("timebucket", &m_timebucket, "m_timebucket/I"); m_clustree->Branch("segtype", &m_segtype, "m_segtype/I"); m_clustree->Branch("tile", &m_tileid, "m_tileid/I"); + m_clustree->Branch("layer", &m_scluslayer, "m_scluslayer/I"); m_tree = new TTree("residualtree", "A tree with track, cluster, and state info"); m_tree->Branch("run", &m_runnumber, "m_runnumber/I"); diff --git a/offline/packages/TrackingDiagnostics/TrackSeedTrackMapConverter.cc b/offline/packages/TrackingDiagnostics/TrackSeedTrackMapConverter.cc index 02a10baea3..969e746c82 100644 --- a/offline/packages/TrackingDiagnostics/TrackSeedTrackMapConverter.cc +++ b/offline/packages/TrackingDiagnostics/TrackSeedTrackMapConverter.cc @@ -588,10 +588,11 @@ int TrackSeedTrackMapConverter::getNodes(PHCompositeNode* topNode) std::cout << PHWHERE << "WARNING, TrackSeedTrackMapConverter may seg fault depending on what seeding algorithm this is run after" << std::endl; } - m_clusters = findNode::getClass(topNode, "TRKR_CLUSTER"); + m_clusters = findNode::getClass(topNode, m_clusterMapName); if (!m_clusters) { - std::cout << PHWHERE << " Can't find cluster container, can't continue." + std::cout << PHWHERE << " Can't find cluster container " << m_clusterMapName + << ", can't continue." << std::endl; return Fun4AllReturnCodes::ABORTEVENT; } diff --git a/offline/packages/TrackingDiagnostics/TrackSeedTrackMapConverter.h b/offline/packages/TrackingDiagnostics/TrackSeedTrackMapConverter.h index 1cff3281d7..ef9c48766e 100644 --- a/offline/packages/TrackingDiagnostics/TrackSeedTrackMapConverter.h +++ b/offline/packages/TrackingDiagnostics/TrackSeedTrackMapConverter.h @@ -29,6 +29,7 @@ class TrackSeedTrackMapConverter : public SubsysReco void setFieldMap(const std::string &name) { m_fieldMap = name; } void setTrackMapName(const std::string &name) { m_trackMapName = name; } void setTrackSeedName(const std::string &name) { m_trackSeedName = name; } + void setClusterMapName(const std::string& name) {m_clusterMapName = name; } void cosmics() { m_cosmics = true; } void constField() { m_ConstField = true; } @@ -56,6 +57,7 @@ class TrackSeedTrackMapConverter : public SubsysReco std::string m_fieldMap; std::string m_trackMapName{"SvtxTrackMap"}; std::string m_trackSeedName{"TpcTrackSeedContainer"}; + std::string m_clusterMapName{"TRKR_CLUSTER"}; }; #endif // TRACKSEEDTRACKMAPCONVERTER_H diff --git a/offline/packages/TrackingDiagnostics/TrkrNtuplizer.cc b/offline/packages/TrackingDiagnostics/TrkrNtuplizer.cc index 6ee6d35395..abc91cbf52 100644 --- a/offline/packages/TrackingDiagnostics/TrkrNtuplizer.cc +++ b/offline/packages/TrackingDiagnostics/TrkrNtuplizer.cc @@ -31,10 +31,15 @@ #include #include +#include + +#include + #include #include #include +#include #include @@ -158,6 +163,7 @@ enum n_hit // NOLINT(readability-enum-initial-value, performance-enum-size) nhitcellID, nhitecell, nhitphibin, + nhitzbin, nhittbin, nhitphi, nhitr, @@ -330,7 +336,7 @@ int TrkrNtuplizer::Init(PHCompositeNode* /*unused*/) std::string str_vertex = {"vertexID:vx:vy:vz:ntracks:chi2:ndof"}; std::string str_event = {"event:seed:run:seg:job"}; - std::string str_hit = {"hitID:e:adc:layer:phielem:zelem:cellID:ecell:phibin:tbin:phi:r:x:y:z"}; + std::string str_hit = {"hitID:e:adc:layer:phielem:zelem:cellID:ecell:phibin:zbin:tbin:phi:r:x:y:z"}; std::string str_cluster = {"locx:locy:x:y:z:r:phi:eta:theta:phibin:tbin:fee:chan:sampa:ex:ey:ez:ephi:pez:pephi:e:adc:maxadc:thick:afac:bfac:dcal:layer:phielem:zelem:size:phisize:zsize:pedge:redge:ovlp:trackID:niter"}; std::string str_seed = {"seedID:siter:spt:sptot:seta:sphi:syxint:srzint:sxyslope:srzslope:sX0:sY0:sdZ0:sR0:scharge:sdedx:spidedx:skdedx:sprdedx:sn1pix:snsil:sntpc:snhits"}; std::string str_residual = {"alpha:beta:resphio:resphi:resz"}; @@ -560,6 +566,13 @@ int TrkrNtuplizer::InitRun(PHCompositeNode* topNode) } AdcClockPeriod = geom->GetFirstLayerCellGeom()->get_zstep(); + _inttGeom = findNode::getClass(topNode, "CYLINDERGEOM_INTT"); + if (_do_hit_eval && !_inttGeom) + { + std::cout << PHWHERE << "ERROR: Can't find node CYLINDERGEOM_INTT" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + // Create Fee Map auto* geom_container = findNode::getClass(topNode, "TPCGEOMCONTAINER"); { @@ -1464,6 +1477,11 @@ void TrkrNtuplizer::fillOutputNtuples(PHCompositeNode* topNode) fx_hit[n_hit::nhitphielem] = -666; fx_hit[n_hit::nhitzelem] = -666; + if (layer_local < 3) + { + fx_hit[n_hit::nhitphielem] = MvtxDefs::getStaveId(hitset_key); + fx_hit[n_hit::nhitzelem] = MvtxDefs::getChipId(hitset_key); + } if (layer_local >= 3 && layer_local < 7) { fx_hit[n_hit::nhitphielem] = InttDefs::getLadderPhiId(hitset_key); @@ -1485,18 +1503,65 @@ void TrkrNtuplizer::fillOutputNtuples(PHCompositeNode* topNode) } } */ - fx_hit[n_hit::nhitphielem] = TpcDefs::getSectorId(hitset_key); - fx_hit[n_hit::nhitzelem] = TpcDefs::getSide(hitset_key); + //fx_hit[n_hit::nhitphielem] = TpcDefs::getSectorId(hitset_key); + //fx_hit[n_hit::nhitzelem] = TpcDefs::getSide(hitset_key); fx_hit[n_hit::nhitcellID] = 0; fx_hit[n_hit::nhitecell] = hit->getAdc(); fx_hit[n_hit::nhitphibin] = std::numeric_limits::quiet_NaN(); fx_hit[n_hit::nhittbin] = std::numeric_limits::quiet_NaN(); + fx_hit[n_hit::nhitzbin] = std::numeric_limits::quiet_NaN(); fx_hit[n_hit::nhitphi] = std::numeric_limits::quiet_NaN(); fx_hit[n_hit::nhitr] = std::numeric_limits::quiet_NaN(); fx_hit[n_hit::nhitx] = std::numeric_limits::quiet_NaN(); fx_hit[n_hit::nhity] = std::numeric_limits::quiet_NaN(); fx_hit[n_hit::nhitz] = std::numeric_limits::quiet_NaN(); + if (layer_local < _nlayers_maps) + { + int row = MvtxDefs::getRow(hit_key); + int col = MvtxDefs::getCol(hit_key); + + float localX = std::numeric_limits::quiet_NaN(); + float localZ = std::numeric_limits::quiet_NaN(); + SegmentationAlpide::detectorToLocal(row,col,localX,localZ); + Acts::Vector2 local(localX * Acts::UnitConstants::cm, localZ * Acts::UnitConstants::cm); + + const auto& surface = m_tGeometry->maps().getSiliconSurface(hitset_key); + auto glob = surface->localToGlobal(m_tGeometry->geometry().getGeoContext(), local, Acts::Vector3()); + + fx_hit[n_hit::nhitphibin] = row; + fx_hit[n_hit::nhitzbin] = col; + fx_hit[n_hit::nhittbin] = MvtxDefs::getStrobeId(hitset_key); + fx_hit[n_hit::nhitx] = glob.x() / Acts::UnitConstants::cm; + fx_hit[n_hit::nhity] = glob.y() / Acts::UnitConstants::cm; + fx_hit[n_hit::nhitz] = glob.z() / Acts::UnitConstants::cm; + fx_hit[n_hit::nhitr] = sqrt(glob.x()*glob.x()+glob.y()*glob.y()) / Acts::UnitConstants::cm; + fx_hit[n_hit::nhitphi] = atan2(glob.y(),glob.x()); + } + + if (layer_local >= _nlayers_maps && layer_local < _nlayers_intt) + { + int row = InttDefs::getRow(hit_key); + int col = InttDefs::getCol(hit_key); + + CylinderGeomIntt* intt_cylinder = dynamic_cast(_inttGeom->GetLayerGeom(layer_local)); + double localcoords[3]; + intt_cylinder->find_strip_center_localcoords(InttDefs::getLadderZId(hitset_key),row,col,localcoords); + + Acts::Vector2 local(localcoords[1]*Acts::UnitConstants::cm,localcoords[2]*Acts::UnitConstants::cm); + const auto& surface = m_tGeometry->maps().getSiliconSurface(hitset_key); + auto glob = surface->localToGlobal(m_tGeometry->geometry().getGeoContext(), local, Acts::Vector3()); + + fx_hit[n_hit::nhitphibin] = row; + fx_hit[n_hit::nhitzbin] = col; + fx_hit[n_hit::nhittbin] = InttDefs::getTimeBucketId(hitset_key); + fx_hit[n_hit::nhitx] = glob.x() / Acts::UnitConstants::cm; + fx_hit[n_hit::nhity] = glob.y() / Acts::UnitConstants::cm; + fx_hit[n_hit::nhitz] = glob.z() / Acts::UnitConstants::cm; + fx_hit[n_hit::nhitr] = sqrt(glob.x()*glob.x()+glob.y()*glob.y()) / Acts::UnitConstants::cm; + fx_hit[n_hit::nhitphi] = atan2(glob.y(),glob.x()); + } + if (layer_local >= _nlayers_maps + _nlayers_intt && layer_local < _nlayers_maps + _nlayers_intt + _nlayers_tpc) { PHG4TpcGeom* GeoLayer_local = _geom_container->GetLayerCellGeom(layer_local); @@ -1618,7 +1683,7 @@ void TrkrNtuplizer::fillOutputNtuples(PHCompositeNode* topNode) } TrackSeedContainer* _tpc_seeds = findNode::getClass(topNode, "TpcTrackSeedContainer"); - if (!_tpc_seeds) + if (!_tpc_seeds && _do_tpcseed_eval) { std::cout << PHWHERE << " ERROR: Can't find " << "TpcTrackSeedContainer" << std::endl; @@ -1737,9 +1802,9 @@ void TrkrNtuplizer::fillOutputNtuples(PHCompositeNode* topNode) } else { - pidedx = f_pion_minus->Eval(tptot); - kdedx = f_kaon_minus->Eval(tptot); - prdedx = f_proton_plus->Eval(tptot); + pidedx = f_pion_minus->Eval(-tptot); + kdedx = f_kaon_minus->Eval(-tptot); + prdedx = f_proton_minus->Eval(-tptot); } float n1pix = get_n1pix(tpcseed); float fx_seed[n_seed::seedsize] = {(float) trackID, 0, tpt, tptot, teta, tphi, xyint, rzint, xyslope, rzslope, tX0, tY0, tZ0, R0, charge, dedx, pidedx, kdedx, prdedx, n1pix, nsil_local, ntpc_local, nhits_local}; @@ -1933,9 +1998,9 @@ void TrkrNtuplizer::FillTrack(float fX[50], SvtxTrack* track, GlobalVertexMap* v } else { - fX[n_track::ntrknpidedx] = f_pion_minus->Eval(trptot); - fX[n_track::ntrknkdedx] = f_kaon_minus->Eval(trptot); - fX[n_track::ntrknprdedx] = f_proton_minus->Eval(trptot); + fX[n_track::ntrknpidedx] = f_pion_minus->Eval(-trptot); + fX[n_track::ntrknkdedx] = f_kaon_minus->Eval(-trptot); + fX[n_track::ntrknprdedx] = f_proton_minus->Eval(-trptot); } for (SvtxTrack::ConstClusterKeyIter iter_local = tpcseed->begin_cluster_keys(); diff --git a/offline/packages/TrackingDiagnostics/TrkrNtuplizer.h b/offline/packages/TrackingDiagnostics/TrkrNtuplizer.h index 4e9df30628..ac341f1a45 100644 --- a/offline/packages/TrackingDiagnostics/TrkrNtuplizer.h +++ b/offline/packages/TrackingDiagnostics/TrkrNtuplizer.h @@ -35,6 +35,7 @@ class SvtxVertexMap; class TrkrClusterContainer; class ActsGeometry; class PHG4TpcGeomContainer; +class PHG4CylinderGeomContainer; class GlobalVertexMap; // class ClusterErrorPara; @@ -157,6 +158,7 @@ class TrkrNtuplizer : public SubsysReco SvtxTrackMap *_trackmap{nullptr}; ActsGeometry *_tgeometry{nullptr}; PHG4TpcGeomContainer *_geom_container{nullptr}; + PHG4CylinderGeomContainer *_inttGeom{nullptr}; float m_ZDC_coincidence{0}; float m_mbd_rate{0}; float m_rawzdc{0}; diff --git a/offline/packages/bcolumicount/BcoInfo.cc b/offline/packages/bcolumicount/BcoInfo.cc new file mode 100644 index 0000000000..3fc672a599 --- /dev/null +++ b/offline/packages/bcolumicount/BcoInfo.cc @@ -0,0 +1,23 @@ +#include "BcoInfo.h" + +#include + +#include + +void BcoInfo::Reset() +{ + std::cout << PHWHERE << "ERROR Reset() not implemented by daughter class" << std::endl; + return; +} + +void BcoInfo::identify(std::ostream& os) const +{ + os << "identify yourself: virtual BcoInfo Object" << std::endl; + return; +} + +int BcoInfo::isValid() const +{ + std::cout << PHWHERE << "isValid not implemented by daughter class" << std::endl; + return 0; +} diff --git a/offline/packages/bcolumicount/BcoInfo.h b/offline/packages/bcolumicount/BcoInfo.h new file mode 100644 index 0000000000..46548d48f4 --- /dev/null +++ b/offline/packages/bcolumicount/BcoInfo.h @@ -0,0 +1,50 @@ +// Tell emacs that this is a C++ source +// -*- C++ -*-. +#ifndef BCOLLUMICOUNT_BCOINFO_H +#define BCOLLUMICOUNT_BCOINFO_H + +#include + +#include +#include + +/// +class BcoInfo : public PHObject +{ + public: + /// ctor - daughter class copy ctor needs this + BcoInfo() = default; + /// dtor + ~BcoInfo() override = default; + /// Clear Sync + void Reset() override; + + /** identify Function from PHObject + @param os Output Stream + */ + void identify(std::ostream& os = std::cout) const override; + + /// isValid returns non zero if object contains valid data + int isValid() const override; + + virtual uint64_t get_previous_bco() const { return 0; } + virtual uint64_t get_current_bco() const { return 0; } + virtual uint64_t get_future_bco() const { return 0; } + + virtual void set_previous_bco(uint64_t /*val*/) { return; } + virtual void set_current_bco(uint64_t /*val*/) { return; } + virtual void set_future_bco(uint64_t /*val*/) { return; } + + virtual int get_previous_evtno() const { return 0; } + virtual int get_current_evtno() const { return 0; } + virtual int get_future_evtno() const { return 0; } + + virtual void set_previous_evtno(int /*val*/) { return; } + virtual void set_current_evtno(int /*val*/) { return; } + virtual void set_future_evtno(int /*val*/) { return; } + + private: + ClassDefOverride(BcoInfo, 1) +}; + +#endif diff --git a/offline/packages/bcolumicount/BcoInfoLinkDef.h b/offline/packages/bcolumicount/BcoInfoLinkDef.h new file mode 100644 index 0000000000..54907ed5fe --- /dev/null +++ b/offline/packages/bcolumicount/BcoInfoLinkDef.h @@ -0,0 +1,5 @@ +#ifdef __CINT__ + +#pragma link C++ class BcoInfo + ; + +#endif diff --git a/offline/packages/bcolumicount/BcoInfov1.cc b/offline/packages/bcolumicount/BcoInfov1.cc new file mode 100644 index 0000000000..28e206413f --- /dev/null +++ b/offline/packages/bcolumicount/BcoInfov1.cc @@ -0,0 +1,28 @@ +#include "BcoInfov1.h" + +void BcoInfov1::Reset() +{ + bco.fill(0); + evtno.fill(0); + return; +} + +void BcoInfov1::identify(std::ostream& out) const +{ + out << "identify yourself: I am an BcoInfov1 Object\n"; + out << "previous event: " << get_previous_evtno() << std::hex + << " bco: 0x" << get_previous_bco() << "\n" + << std::dec + << "current event: " << get_current_evtno() << std::hex + << " bco: 0x" << get_current_bco() << "\n" + << std::dec + << "future event: " << get_future_evtno() << std::hex + << " bco: 0x" << get_future_bco() << std::dec + << std::endl; + return; +} + +int BcoInfov1::isValid() const +{ + return (bco[2] ? 1 : 0); // return 1 if future bco is not zero +} diff --git a/offline/packages/bcolumicount/BcoInfov1.h b/offline/packages/bcolumicount/BcoInfov1.h new file mode 100644 index 0000000000..78b2a3f348 --- /dev/null +++ b/offline/packages/bcolumicount/BcoInfov1.h @@ -0,0 +1,54 @@ +// Tell emacs that this is a C++ source +// -*- C++ -*-. +#ifndef BCOLUMICOUNT_BCOINFOV1_H +#define BCOLUMICOUNT_BCOINFOV1_H + +#include "BcoInfo.h" + +#include +#include + +class BcoInfov1 : public BcoInfo +{ + public: + /// ctor + BcoInfov1() = default; + + /// dtor + ~BcoInfov1() override = default; + + /// Clear Event + void Reset() override; + + /** identify Function from PHObject + @param os Output Stream + */ + void identify(std::ostream& out = std::cout) const override; + + /// isValid returns non zero if object contains valid data + int isValid() const override; + + uint64_t get_previous_bco() const override { return bco[0]; } + uint64_t get_current_bco() const override { return bco[1]; } + uint64_t get_future_bco() const override { return bco[2]; } + + void set_previous_bco(uint64_t val) override { bco[0] = val; } + void set_current_bco(uint64_t val) override { bco[1] = val; } + void set_future_bco(uint64_t val) override { bco[2] = val; } + + int get_previous_evtno() const override { return evtno[0]; } + int get_current_evtno() const override { return evtno[1]; } + int get_future_evtno() const override { return evtno[2]; } + + void set_previous_evtno(int val) override { evtno[0] = val; } + void set_current_evtno(int val) override { evtno[1] = val; } + void set_future_evtno(int val) override { evtno[2] = val; } + + private: + std::array bco{0}; + std::array evtno{0}; + + ClassDefOverride(BcoInfov1, 1) +}; + +#endif diff --git a/offline/packages/bcolumicount/BcoInfov1LinkDef.h b/offline/packages/bcolumicount/BcoInfov1LinkDef.h new file mode 100644 index 0000000000..41672f57b9 --- /dev/null +++ b/offline/packages/bcolumicount/BcoInfov1LinkDef.h @@ -0,0 +1,5 @@ +#ifdef __CINT__ + +#pragma link C++ class BcoInfov1 + ; + +#endif diff --git a/offline/packages/bcolumicount/BcoLumiCheck.cc b/offline/packages/bcolumicount/BcoLumiCheck.cc new file mode 100644 index 0000000000..3ba12f1776 --- /dev/null +++ b/offline/packages/bcolumicount/BcoLumiCheck.cc @@ -0,0 +1,71 @@ +#include "BcoLumiCheck.h" + +#include "BcoInfo.h" + +#include +#include + +#include + +#include +#include // for SubsysReco + +#include +#include // for PHNode +#include // for PHNodeIterator +#include +#include // for PHWHERE + +#include + +BcoLumiCheck::BcoLumiCheck(const std::string &name) + : SubsysReco(name) +{ + return; +} + +int BcoLumiCheck::Init(PHCompositeNode *topNode) +{ + int iret = CreateNodeTree(topNode); + return iret; +} + +int BcoLumiCheck::InitRun(PHCompositeNode * /*topNode*/) +{ + return Fun4AllReturnCodes::EVENT_OK; +} + +int BcoLumiCheck::CreateNodeTree(PHCompositeNode *topNode) +{ + PHNodeIterator iter(topNode); + PHCompositeNode *dstNode; + dstNode = dynamic_cast(iter.findFirst("PHCompositeNode", "DST")); + if (!dstNode) + { + std::cout << PHWHERE << " DST Node is missing doing nothing" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + return Fun4AllReturnCodes::EVENT_OK; +} + +int BcoLumiCheck::process_event(PHCompositeNode *topNode) +{ + BcoInfo *bcoinfo = findNode::getClass(topNode, "BCOINFO"); + SyncObject *syncobject = findNode::getClass(topNode, syncdefs::SYNCNODENAME); + Gl1Packet *gl1packet = findNode::getClass(topNode, 14001); + if (gl1packet) + { + std::cout << "Event No: " << syncobject->EventNumber() << std::hex + << " gl1: bco 0x" << gl1packet->lValue(0, "BCO") << std::dec << std::endl; + if (bcoinfo) + { + std::cout << "prev event: " << bcoinfo->get_previous_evtno() << std::hex + << " bco: 0x" << bcoinfo->get_previous_bco() << std::dec << std::endl; + std::cout << "curr event: " << bcoinfo->get_current_evtno() << std::hex + << " bco: 0x" << bcoinfo->get_current_bco() << std::dec << std::endl; + std::cout << "futu event: " << bcoinfo->get_future_evtno() << std::hex + << " bco: 0x" << bcoinfo->get_future_bco() << std::dec << std::endl; + } + } + return Fun4AllReturnCodes::EVENT_OK; +} diff --git a/offline/packages/bcolumicount/BcoLumiCheck.h b/offline/packages/bcolumicount/BcoLumiCheck.h new file mode 100644 index 0000000000..75477dea98 --- /dev/null +++ b/offline/packages/bcolumicount/BcoLumiCheck.h @@ -0,0 +1,22 @@ +#ifndef BCOLUMICOUNT_BCOLUMICHECK_H +#define BCOLUMICOUNT_BCOLUMICHECK_H + +#include + +#include + +class BcoLumiCheck : public SubsysReco +{ + public: + BcoLumiCheck(const std::string &name = "BCOLUMICHECK"); + ~BcoLumiCheck() override = default; + + int Init(PHCompositeNode *topNode) override; + int InitRun(PHCompositeNode *topNode) override; + int process_event(PHCompositeNode *topNode) override; + + private: + static int CreateNodeTree(PHCompositeNode *topNode); +}; + +#endif // BCOLUMICOUNT_BCOLUMICHECK_H diff --git a/offline/packages/bcolumicount/BcoLumiReco.cc b/offline/packages/bcolumicount/BcoLumiReco.cc new file mode 100644 index 0000000000..bf8ea87224 --- /dev/null +++ b/offline/packages/bcolumicount/BcoLumiReco.cc @@ -0,0 +1,144 @@ +#include "BcoLumiReco.h" + +#include "BcoInfo.h" +#include "BcoInfov1.h" + +#include +#include + +#include +#include // for SubsysReco + +#include +#include +#include // for PHNode +#include // for PHNodeIterator +#include // for PHObject +#include +#include // for PHWHERE + +#include +#include +#include // for Packet +# +#include + +BcoLumiReco::BcoLumiReco(const std::string &name) + : SubsysReco(name) +{ + return; +} + +BcoLumiReco::~BcoLumiReco() +{ + delete m_synccopy; + delete m_tmpsync; +} + +int BcoLumiReco::Init(PHCompositeNode *topNode) +{ + int iret = CreateNodeTree(topNode); + return iret; +} + +int BcoLumiReco::CreateNodeTree(PHCompositeNode *topNode) +{ + PHNodeIterator iter(topNode); + PHCompositeNode *dstNode; + dstNode = dynamic_cast(iter.findFirst("PHCompositeNode", "DST")); + if (!dstNode) + { + std::cout << PHWHERE << " DST Node is missing doing nothing" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + BcoInfo *bcoinfo = findNode::getClass(topNode, "BCOINFO"); + if (!bcoinfo) + { + bcoinfo = new BcoInfov1(); + PHIODataNode *newnode = new PHIODataNode(bcoinfo, "BCOINFO", "PHObject"); + dstNode->addNode(newnode); + } + return Fun4AllReturnCodes::EVENT_OK; +} + +int BcoLumiReco::process_event(PHCompositeNode *topNode) +{ + static bool ifirst = true; + SyncObject *syncobject = findNode::getClass(topNode, syncdefs::SYNCNODENAME); + Event *evt = findNode::getClass(topNode, "PRDF"); + if (evt) + { + if (Verbosity() > 1) + { + evt->identify(); + } + if (evt->getEvtType() != DATAEVENT) + { + return Fun4AllReturnCodes::ABORTEVENT; + } + Packet *packet = evt->getPacket(14001); + uint64_t gtm_bco = packet->lValue(0, "BCO"); + if (Verbosity() > 1) + { + std::cout << std::hex << "packet ival: 0x" << packet->lValue(0, "BCO") + << " uint64_t: 0x" << gtm_bco << std::dec << std::endl; + } + push_bco(gtm_bco); + delete packet; + } + if (syncobject) + { + push_evtno(syncobject->EventNumber()); + } + if (ifirst) // abort first event since it does not have a previous bco + { + ifirst = false; + return Fun4AllReturnCodes::ABORTEVENT; + } + if (!m_synccopy) + { + m_synccopy = dynamic_cast(syncobject->CloneMe()); // clone for second event + m_tmpsync = dynamic_cast(m_synccopy->CloneMe()); // just to create this object + return Fun4AllReturnCodes::ABORTEVENT; // and abort + } + BcoInfo *bcoinfo = findNode::getClass(topNode, "BCOINFO"); + + if (Verbosity() > 0) + { + std::cout << "current event is: " << syncobject->EventNumber() << "\n"; + std::cout << "saving as event: " << m_synccopy->EventNumber() << "\n"; + } + // here we store the current sync object and overwrite its content with the cached copy + *m_tmpsync = *syncobject; // save current version in tmp + *syncobject = *m_synccopy; // copy previously cached version + *m_synccopy = *m_tmpsync; // cache current version + if (Verbosity() > 0) + { + std::cout << std::hex; + std::cout << "previous bco: " << get_previous_bco() << "\n"; + std::cout << "current bco: " << get_current_bco() << "\n"; + std::cout << "future bco: " << get_future_bco() << std::endl; + std::cout << std::dec; + } + bcoinfo->set_previous_bco(get_previous_bco()); + bcoinfo->set_current_bco(get_current_bco()); + bcoinfo->set_future_bco(get_future_bco()); + bcoinfo->set_previous_evtno(get_previous_evtno()); + bcoinfo->set_current_evtno(get_current_evtno()); + bcoinfo->set_future_evtno(get_future_evtno()); + return Fun4AllReturnCodes::EVENT_OK; +} + +void BcoLumiReco::push_bco(uint64_t value) +{ + m_bco[0] = m_bco[1]; + m_bco[1] = m_bco[2]; + m_bco[2] = value; +} + +void BcoLumiReco::push_evtno(int value) +{ + m_evtno[0] = m_evtno[1]; + m_evtno[1] = m_evtno[2]; + m_evtno[2] = value; +} diff --git a/offline/packages/bcolumicount/BcoLumiReco.h b/offline/packages/bcolumicount/BcoLumiReco.h new file mode 100644 index 0000000000..c0c0ab6a3a --- /dev/null +++ b/offline/packages/bcolumicount/BcoLumiReco.h @@ -0,0 +1,40 @@ +#ifndef BCOLUMICOUNT_BCOLUMIRECO_H +#define BCOLUMICOUNT_BCOLUMIRECO_H + +#include + +#include +#include +#include + +class PHCompositeNode; +class SyncObject; + +class BcoLumiReco : public SubsysReco +{ + public: + BcoLumiReco(const std::string &name = "BCOLUMIRECO"); + ~BcoLumiReco() override; + + int Init(PHCompositeNode *topNode) override; + int process_event(PHCompositeNode *topNode) override; + + void push_bco(uint64_t value); + uint64_t get_previous_bco() { return m_bco[0]; } + uint64_t get_current_bco() const { return m_bco[1]; } + uint64_t get_future_bco() const { return m_bco[2]; } + + void push_evtno(int value); + int get_previous_evtno() { return m_evtno[0]; } + int get_current_evtno() const { return m_evtno[1]; } + int get_future_evtno() const { return m_evtno[2]; } + + private: + static int CreateNodeTree(PHCompositeNode *topNode); + SyncObject *m_synccopy{nullptr}; + SyncObject *m_tmpsync{nullptr}; + std::array m_bco{0}; + std::array m_evtno{0}; +}; + +#endif // BCOLUMICOUNT_BCOLUMIRECO_H diff --git a/offline/packages/bcolumicount/Makefile.am b/offline/packages/bcolumicount/Makefile.am new file mode 100644 index 0000000000..70afc9b224 --- /dev/null +++ b/offline/packages/bcolumicount/Makefile.am @@ -0,0 +1,82 @@ +AUTOMAKE_OPTIONS = foreign + +lib_LTLIBRARIES = \ + libbcolumicount_io.la \ + libbcolumicount.la + +AM_CPPFLAGS = \ + -I$(includedir) \ + -isystem$(OFFLINE_MAIN)/include \ + -isystem$(ROOTSYS)/include + +AM_LDFLAGS = \ + -L$(libdir) \ + -L$(OFFLINE_MAIN)/lib \ + -L$(OFFLINE_MAIN)/lib64 + +libbcolumicount_io_la_LIBADD = \ + -lphool + +libbcolumicount_la_LIBADD = \ + libbcolumicount_io.la \ + -lffaobjects \ + -lffarawobjects \ + -lSubsysReco + +ROOTDICTS = \ + BcoInfo_Dict.cc \ + BcoInfov1_Dict.cc + +pcmdir = $(libdir) +# more elegant way to create pcm files (without listing them) +nobase_dist_pcm_DATA = $(ROOTDICTS:.cc=_rdict.pcm) + +pkginclude_HEADERS = \ + BcoInfo.h \ + BcoInfov1.h \ + BcoLumiCheck.h \ + BcoLumiReco.h + + +libbcolumicount_io_la_SOURCES = \ + $(ROOTDICTS) \ + BcoInfo.cc \ + BcoInfov1.cc + +libbcolumicount_la_SOURCES = \ + BcoLumiCheck.cc \ + BcoLumiReco.cc + +BUILT_SOURCES = testexternals.cc + +noinst_PROGRAMS = \ + testexternals \ + testexternals_io + +testexternals_SOURCES = \ + testexternals.cc + +testexternals_LDADD = \ + libbcolumicount.la + +testexternals_io_SOURCES = \ + testexternals.cc + +testexternals_io_LDADD = \ + libbcolumicount_io.la + +testexternals.cc: + echo "//*** this is a generated file. Do not commit, do not edit" > $@ + echo "int main()" >> $@ + echo "{" >> $@ + echo " return 0;" >> $@ + echo "}" >> $@ + +%_Dict.cc: %.h %LinkDef.h + rootcint -f $@ @CINTDEFS@ $(DEFAULT_INCLUDES) $(AM_CPPFLAGS) $^ + +#just to get the dependency +%_Dict_rdict.pcm: %_Dict.cc ; + +clean-local: + rm -f $(BUILT_SOURCES) diff --git a/offline/packages/bcolumicount/autogen.sh b/offline/packages/bcolumicount/autogen.sh new file mode 100755 index 0000000000..dea267bbfd --- /dev/null +++ b/offline/packages/bcolumicount/autogen.sh @@ -0,0 +1,8 @@ +#!/bin/sh +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +(cd $srcdir; aclocal -I ${OFFLINE_MAIN}/share;\ +libtoolize --force; automake -a --add-missing; autoconf) + +$srcdir/configure "$@" diff --git a/offline/packages/bcolumicount/configure.ac b/offline/packages/bcolumicount/configure.ac new file mode 100644 index 0000000000..ea3c13cc92 --- /dev/null +++ b/offline/packages/bcolumicount/configure.ac @@ -0,0 +1,20 @@ +AC_INIT(bcolumicount,[1.0]) +AC_CONFIG_SRCDIR([configure.ac]) + +AM_INIT_AUTOMAKE + +LT_INIT([disable-static]) + +AC_PROG_CXX(CC g++) + +dnl no point in suppressing warnings people should +dnl at least see them, so here we go for g++: -Wall +if test $ac_cv_prog_gxx = yes; then + CXXFLAGS="$CXXFLAGS -Wall -Werror -Wextra -Wshadow" +fi + +CINTDEFS=" -noIncludePaths -inlineInputHeader " +AC_SUBST(CINTDEFS) + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/offline/packages/decayfinder/DecayFinder.cc b/offline/packages/decayfinder/DecayFinder.cc index 1593387592..a3521df780 100644 --- a/offline/packages/decayfinder/DecayFinder.cc +++ b/offline/packages/decayfinder/DecayFinder.cc @@ -361,6 +361,9 @@ bool DecayFinder::findDecay(PHCompositeNode* topNode) exit(1); } + // correct mother PID to search for match + const int mother_id_to_match = m_getChargeConjugate ? std::abs(m_mother_ID) : m_mother_ID; + if (m_truthinfo && !m_geneventmap) // This should use the truth info container if we have no HepMC record { if (Verbosity() >= VERBOSITY_SOME) @@ -374,7 +377,7 @@ bool DecayFinder::findDecay(PHCompositeNode* topNode) { PHG4Particle* g4particle = iter->second; int this_pid = m_getChargeConjugate ? abs(g4particle->get_pid()) : g4particle->get_pid(); - if (this_pid == m_mother_ID) + if (this_pid == mother_id_to_match) { if (Verbosity() >= VERBOSITY_MAX) { @@ -455,7 +458,7 @@ bool DecayFinder::findDecay(PHCompositeNode* topNode) for (HepMC::GenEvent::particle_const_iterator p = theEvent->particles_begin(); p != theEvent->particles_end(); ++p) { int this_pid = m_getChargeConjugate ? abs((*p)->pdg_id()) : (*p)->pdg_id(); - if (this_pid == m_mother_ID) + if (this_pid == mother_id_to_match) { if (Verbosity() >= VERBOSITY_MAX) { diff --git a/offline/packages/eventplaneinfo/EventPlaneCalibration.cc b/offline/packages/eventplaneinfo/EventPlaneCalibration.cc deleted file mode 100644 index 5e5fb01264..0000000000 --- a/offline/packages/eventplaneinfo/EventPlaneCalibration.cc +++ /dev/null @@ -1,840 +0,0 @@ -#include "EventPlaneCalibration.h" - -#include "Eventplaneinfo.h" -#include "EventplaneinfoMap.h" -#include "EventplaneinfoMapv1.h" -#include "Eventplaneinfov1.h" - -#include -#include -#include - -//#include - -//#include - -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#include -#include // for SubsysReco - -#include -#include -#include // for PHNode -#include -#include // for PHObject -#include -#include // for PHWHERE -#include - -#include -#include - -#include -#include -#include -#include // for exit -#include -#include -#include // for _Rb_tree_const_iterator -#include // for pair -#include // for vector - -EventPlaneCalibration::EventPlaneCalibration(const std::string &name) : SubsysReco(name) { - south_q.resize(m_MaxOrder); - north_q.resize(m_MaxOrder); - northsouth_q.resize(m_MaxOrder); - south_q_subtract.resize(m_MaxOrder); - north_q_subtract.resize(m_MaxOrder); - northsouth_q_subtract.resize(m_MaxOrder); - shift_north.resize(m_MaxOrder); - shift_south.resize(m_MaxOrder); - shift_northsouth.resize(m_MaxOrder); - tmp_south_psi.resize(m_MaxOrder); - tmp_north_psi.resize(m_MaxOrder); - tmp_northsouth_psi.resize(m_MaxOrder); - - for (auto &vec : south_q) { - vec.resize(2); - } - - for (auto &vec : north_q) { - vec.resize(2); - } - - for (auto &vec : northsouth_q) { - vec.resize(2); - } - - for (auto &vec : south_q_subtract) { - vec.resize(2); - } - - for (auto &vec : north_q_subtract) { - vec.resize(2); - } - - for (auto &vec : northsouth_q_subtract) { - vec.resize(2); - } -} - -int EventPlaneCalibration::InitRun(PHCompositeNode *topNode) { - - if (_isSim) { - m_runNo = 0; - } - if (!_default_calib) { - recoConsts *rc = recoConsts::instance(); - m_runNo = rc->get_IntFlag("RUNNUMBER"); - } - - if (Verbosity() > 0) { - std::cout << "======================= EventPlaneCalibration:InitRun() " - "=======================" - << std::endl; - std::cout << PHWHERE << "RUNNUMBER " << m_runNo << std::endl; - } - - if (OutFileName.empty()) - { - OutFileName = std::format("eventplane_correction_histograms_run_{}.root",m_runNo); - } - cdbhistosOut = new CDBHistos(OutFileName); - - //-----------------------------------load calibration - //histograms-----------------------------------------// - // Create and register recentering histograms - for (unsigned int order = 0; order < m_MaxOrder; order++) { - - tprof_mean_cos_south_epd[order] = new TProfile2D( - std::format("tprof_mean_cos_south_epd_order_{}", order).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - tprof_mean_sin_south_epd[order] = new TProfile2D( - std::format("tprof_mean_sin_south_epd_order_{}", order).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - tprof_mean_cos_north_epd[order] = new TProfile2D( - std::format("tprof_mean_cos_north_epd_order_{}", order).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - tprof_mean_sin_north_epd[order] = new TProfile2D( - std::format("tprof_mean_sin_north_epd_order_{}", order).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - - tprof_mean_cos_northsouth_epd[order] = new TProfile2D( - std::format("tprof_mean_cos_northsouth_epd_order_{}", order).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - tprof_mean_sin_northsouth_epd[order] = new TProfile2D( - std::format("tprof_mean_sin_northsouth_epd_order_{}", order).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - - cdbhistosOut->registerHisto(tprof_mean_cos_south_epd[order]); - cdbhistosOut->registerHisto(tprof_mean_sin_south_epd[order]); - cdbhistosOut->registerHisto(tprof_mean_cos_north_epd[order]); - cdbhistosOut->registerHisto(tprof_mean_sin_north_epd[order]); - cdbhistosOut->registerHisto(tprof_mean_cos_northsouth_epd[order]); - cdbhistosOut->registerHisto(tprof_mean_sin_northsouth_epd[order]); - } - - CDBHistos *cdbhistosIn = new CDBHistos(OutFileName); - cdbhistosIn->LoadCalibrations(); - - // Create and register shifting histograms - for (unsigned int order = 0; order < m_MaxOrder; order++) { - for (int p = 0; p < _imax; p++) { - tprof_cos_north_epd_shift[order][p] = new TProfile2D( - std::format("tprof_cos_north_epd_shift_order_{}_{}", order, p).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - tprof_sin_north_epd_shift[order][p] = new TProfile2D( - std::format("tprof_sin_north_epd_shift_order_{}_{}", order, p).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - tprof_cos_south_epd_shift[order][p] = new TProfile2D( - std::format("tprof_cos_south_epd_shift_order_{}_{}", order, p).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - tprof_sin_south_epd_shift[order][p] = new TProfile2D( - std::format("tprof_sin_south_epd_shift_order_{}_{}", order, p).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - - tprof_cos_northsouth_epd_shift[order][p] = new TProfile2D( - std::format("tprof_cos_northsouth_epd_shift_order_{}_{}", order, p).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - tprof_sin_northsouth_epd_shift[order][p] = new TProfile2D( - std::format("tprof_sin_northsouth_epd_shift_order_{}_{}", order, p).c_str(), - "", 125 * 40, 0, 25000, 20, -100, 100, -1e10, 1e10); - - cdbhistosOut->registerHisto(tprof_cos_north_epd_shift[order][p]); - cdbhistosOut->registerHisto(tprof_sin_north_epd_shift[order][p]); - cdbhistosOut->registerHisto(tprof_cos_south_epd_shift[order][p]); - cdbhistosOut->registerHisto(tprof_sin_south_epd_shift[order][p]); - cdbhistosOut->registerHisto(tprof_cos_northsouth_epd_shift[order][p]); - cdbhistosOut->registerHisto(tprof_sin_northsouth_epd_shift[order][p]); - } - } - - // Get recentering histograms - for (unsigned int order = 0; order < m_MaxOrder; order++) { - tprof_mean_cos_south_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_cos_south_epd_order_{}", order), false)); - tprof_mean_sin_south_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_sin_south_epd_order_{}", order), false)); - tprof_mean_cos_north_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_cos_north_epd_order_{}", order), false)); - tprof_mean_sin_north_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_sin_north_epd_order_{}", order), false)); - tprof_mean_cos_northsouth_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_cos_northsouth_epd_order_{}", order), - false)); - tprof_mean_sin_northsouth_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_sin_northsouth_epd_order_{}", order), - false)); - } - - // Get shifting histograms - for (unsigned int order = 0; order < m_MaxOrder; order++) { - for (int p = 0; p < _imax; p++) { - tprof_cos_north_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_cos_north_epd_shift_order_{}_{}", order, p), - false)); - tprof_sin_north_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_sin_north_epd_shift_order_{}_{}", order, p), - false)); - tprof_cos_south_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_cos_south_epd_shift_order_{}_{}", order, p), - false)); - tprof_sin_south_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_sin_south_epd_shift_order_{}_{}", order, p), - false)); - tprof_cos_northsouth_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_cos_northsouth_epd_shift_order_{}_{}", order, - p), - false)); - tprof_sin_northsouth_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_sin_northsouth_epd_shift_order_{}_{}", order, - p), - false)); - } - } - - cdbhistosIn->Print(); - - return CreateNodes(topNode); -} - -int EventPlaneCalibration::process_event(PHCompositeNode *topNode) { - if (Verbosity() > 1) { - std::cout << "EventPlaneCalibration::process_event -- entered" << std::endl; - } - - //--------------------------------- - // Get Objects off of the Node Tree - //--------------------------------- - - MbdVertexMap *mbdvtxmap = - findNode::getClass(topNode, "MbdVertexMap"); - if (!mbdvtxmap) { - std::cout << PHWHERE << "::ERROR - cannot find MbdVertexMap" << std::endl; - exit(-1); - } - - MbdVertex *mvertex = nullptr; - if (mbdvtxmap) { - for (MbdVertexMap::ConstIter mbditer = mbdvtxmap->begin(); - mbditer != mbdvtxmap->end(); ++mbditer) { - mvertex = mbditer->second; - } - if (mvertex) { - _mbdvtx = mvertex->get_z(); - } - } - - EventplaneinfoMap *epmap = - findNode::getClass(topNode, "EventplaneinfoMap"); - if (!epmap) { - std::cout << PHWHERE << "::ERROR - cannot find EventplaneinfoMap" - << std::endl; - exit(-1); - } - - Gl1Packet *gl1PacketInfo = findNode::getClass(topNode, 14001); - if (!gl1PacketInfo) { - std::cout << PHWHERE << "GlobalQA::process_event: GL1Packet node is missing" - << std::endl; - } - - uint64_t triggervec = 0; - if (gl1PacketInfo) { - triggervec = gl1PacketInfo->getScaledVector(); - } - - if (_sepdEpReco) { - - TowerInfoContainer *epd_towerinfo = - findNode::getClass(topNode, "TOWERINFO_CALIB_SEPD"); - if (!epd_towerinfo) { - epd_towerinfo = findNode::getClass( - topNode, "TOWERINFO_CALIB_EPD"); - if (!epd_towerinfo) { - std::cout << PHWHERE - << "::ERROR - cannot find sEPD Calibrated TowerInfoContainer" - << std::endl; - exit(-1); - } - } - - EpdGeom *_epdgeom = findNode::getClass(topNode, "TOWERGEOM_EPD"); - if (!_epdgeom) { - std::cout << PHWHERE << "::ERROR - cannot find TOWERGEOM_EPD" - << std::endl; - exit(-1); - } - - ResetMe(); - - if ((triggervec >> 0xAU) & 0x1U) { - - if ((std::fabs(_mbdvtx) < _mbd_vertex_cut)) { - - unsigned int ntowers = epd_towerinfo->size(); - for (unsigned int ch = 0; ch < ntowers; ch++) { - TowerInfo *_tower = epd_towerinfo->get_tower_at_channel(ch); - float epd_e = _tower->get_energy(); - bool isZS = _tower->get_isZS(); - if (!isZS) // exclude ZS - { - unsigned int key = TowerInfoDefs::encode_epd(ch); - int arm = TowerInfoDefs::get_epd_arm(key); - if (arm == 0) { - _ssum += epd_e; - } else if (arm == 1) { - _nsum += epd_e; - } - } - } - - if (_ssum > _epd_charge_min && _nsum > _epd_charge_min && - _ssum < _epd_charge_max && _nsum < _epd_charge_max) { - _do_ep = true; - } - - if (_do_ep) { - for (unsigned int ch = 0; ch < ntowers; ch++) { - TowerInfo *_tower = epd_towerinfo->get_tower_at_channel(ch); - float epd_e = _tower->get_energy(); - bool isZS = _tower->get_isZS(); - if (!isZS) // exclude ZS - { - if (epd_e < 0.2) // expecting Nmips - { - continue; - } - unsigned int key = TowerInfoDefs::encode_epd(ch); - float tile_phi = _epdgeom->get_phi(key); - int arm = TowerInfoDefs::get_epd_arm(key); - float truncated_e = - (epd_e < _epd_e) ? epd_e : _epd_e; // set cutoff at _epd_e - if (arm == 0) { - for (unsigned int order = 0; order < m_MaxOrder; order++) { - double Cosine = cos(tile_phi * (double)(order + 1)); - double Sine = sin(tile_phi * (double)(order + 1)); - south_q[order][0] += truncated_e * Cosine; // south Qn,x - south_q[order][1] += truncated_e * Sine; // south Qn,y - } - } else if (arm == 1) { - for (unsigned int order = 0; order < m_MaxOrder; order++) { - double Cosine = cos(tile_phi * (double)(order + 1)); - double Sine = sin(tile_phi * (double)(order + 1)); - north_q[order][0] += truncated_e * Cosine; // north Qn,x - north_q[order][1] += truncated_e * Sine; // north Qn,y - } - } - for (unsigned int order = 0; order < m_MaxOrder; order++) { - double Cosine = cos(tile_phi * (double)(order + 1)); - double Sine = sin(tile_phi * (double)(order + 1)); - northsouth_q[order][0] += - truncated_e * Cosine; // northsouth Qn,x - northsouth_q[order][1] += truncated_e * Sine; // northsouth Qn,y - } - } - } - - _totalcharge = _nsum + _ssum; - - // Filled during first run - for (unsigned int order = 0; order < m_MaxOrder; order++) { - // Fill recentering histograms by order - tprof_mean_cos_south_epd[order]->Fill(_ssum, _mbdvtx, - south_q[order][0] / _ssum); - tprof_mean_sin_south_epd[order]->Fill(_ssum, _mbdvtx, - south_q[order][1] / _ssum); - tprof_mean_cos_north_epd[order]->Fill(_nsum, _mbdvtx, - north_q[order][0] / _nsum); - tprof_mean_sin_north_epd[order]->Fill(_nsum, _mbdvtx, - north_q[order][1] / _nsum); - tprof_mean_cos_northsouth_epd[order]->Fill( - _totalcharge, _mbdvtx, northsouth_q[order][0] / _totalcharge); - tprof_mean_sin_northsouth_epd[order]->Fill( - _totalcharge, _mbdvtx, northsouth_q[order][1] / _totalcharge); - } - - // Get recentering histograms and do recentering - // Recentering: subtract Qn,x and Qn,y values averaged over all events - for (unsigned int order = 0; order < m_MaxOrder; order++) { - if (tprof_mean_cos_south_epd_input[order]) // check if recentering - // histograms exist - { - - // south - TAxis *south_xaxis = - tprof_mean_cos_south_epd_input[order]->GetXaxis(); - TAxis *south_yaxis = - tprof_mean_cos_south_epd_input[order]->GetYaxis(); - int xbin_south = south_xaxis->FindBin(_ssum); - int ybin_south = south_yaxis->FindBin(_mbdvtx); - - double event_ave_cos_south = - tprof_mean_cos_south_epd_input[order]->GetBinContent( - xbin_south, ybin_south); - double event_ave_sin_south = - tprof_mean_sin_south_epd_input[order]->GetBinContent( - xbin_south, ybin_south); - south_q_subtract[order][0] = _ssum * event_ave_cos_south; - south_q_subtract[order][1] = _ssum * event_ave_sin_south; - south_q[order][0] -= south_q_subtract[order][0]; - south_q[order][1] -= south_q_subtract[order][1]; - - // north - TAxis *north_xaxis = - tprof_mean_cos_north_epd_input[order]->GetXaxis(); - TAxis *north_yaxis = - tprof_mean_cos_north_epd_input[order]->GetYaxis(); - int xbin_north = north_xaxis->FindBin(_nsum); - int ybin_north = north_yaxis->FindBin(_mbdvtx); - - double event_ave_cos_north = - tprof_mean_cos_north_epd_input[order]->GetBinContent( - xbin_north, ybin_north); - double event_ave_sin_north = - tprof_mean_sin_north_epd_input[order]->GetBinContent( - xbin_north, ybin_north); - north_q_subtract[order][0] = _nsum * event_ave_cos_north; - north_q_subtract[order][1] = _nsum * event_ave_sin_north; - north_q[order][0] -= north_q_subtract[order][0]; - north_q[order][1] -= north_q_subtract[order][1]; - - // northsouth - TAxis *northsouth_xaxis = - tprof_mean_cos_northsouth_epd_input[order]->GetXaxis(); - TAxis *northsouth_yaxis = - tprof_mean_cos_northsouth_epd_input[order]->GetYaxis(); - int xbin_northsouth = northsouth_xaxis->FindBin(_totalcharge); - int ybin_northsouth = northsouth_yaxis->FindBin(_mbdvtx); - - double event_ave_cos_northsouth = - tprof_mean_cos_northsouth_epd_input[order]->GetBinContent( - xbin_northsouth, ybin_northsouth); - double event_ave_sin_northsouth = - tprof_mean_sin_northsouth_epd_input[order]->GetBinContent( - xbin_northsouth, ybin_northsouth); - northsouth_q_subtract[order][0] = - _totalcharge * event_ave_cos_northsouth; - northsouth_q_subtract[order][1] = - _totalcharge * event_ave_sin_northsouth; - northsouth_q[order][0] -= northsouth_q_subtract[order][0]; - northsouth_q[order][1] -= northsouth_q_subtract[order][1]; - } - } - - // Get recentered psi_n - Eventplaneinfo *epinfo = new Eventplaneinfov1(); - for (unsigned int order = 0; order < m_MaxOrder; order++) { - double n = order + 1.0; - if (tprof_mean_cos_south_epd_input[order]) // if present, Qs are - // recentered - { - tmp_south_psi[order] = - epinfo->GetPsi(south_q[order][0], south_q[order][1], n); - tmp_north_psi[order] = - epinfo->GetPsi(north_q[order][0], north_q[order][1], n); - tmp_northsouth_psi[order] = epinfo->GetPsi( - northsouth_q[order][0], northsouth_q[order][1], n); - } else { - tmp_south_psi[order] = NAN; - tmp_north_psi[order] = NAN; - tmp_northsouth_psi[order] = NAN; - } - } - - // Filled during second run - for (unsigned int order = 0; order < m_MaxOrder; order++) { - if (tprof_mean_cos_south_epd_input[order]) // if present, Qs are - // recentered - { - // Fill shifting histograms by order and terms - for (int p = 0; p < _imax; p++) { - double terms = p + 1.0; - double n = order + 1.0; - double tmp = (n * terms); - - tprof_cos_south_epd_shift[order][p]->Fill( - _ssum, _mbdvtx, - cos(tmp * tmp_south_psi[order])); // south - tprof_sin_south_epd_shift[order][p]->Fill( - _ssum, _mbdvtx, - sin(tmp * tmp_south_psi[order])); // south - tprof_cos_north_epd_shift[order][p]->Fill( - _nsum, _mbdvtx, - cos(tmp * tmp_north_psi[order])); // north - tprof_sin_north_epd_shift[order][p]->Fill( - _nsum, _mbdvtx, - sin(tmp * tmp_north_psi[order])); // north - tprof_cos_northsouth_epd_shift[order][p]->Fill( - _totalcharge, _mbdvtx, - cos(tmp * tmp_northsouth_psi[order])); // northsouth - // - tprof_sin_northsouth_epd_shift[order][p]->Fill( - _totalcharge, _mbdvtx, - sin(tmp * tmp_northsouth_psi[order])); // northsouth - // - } - } - } - - // Get shifting histograms and calculate shift - for (unsigned int order = 0; order < m_MaxOrder; order++) { - for (int p = 0; p < _imax; p++) { - if (tprof_cos_south_epd_shift_input[order] - [p]) // check if shifting - // histograms exist - { - double terms = p + 1.0; - double n = order + 1.0; - double tmp = (n * terms); - double prefactor = 2.0 / terms; - - // south - TAxis *south_xaxis = - tprof_cos_south_epd_shift_input[order][p]->GetXaxis(); - TAxis *south_yaxis = - tprof_cos_south_epd_shift_input[order][p]->GetYaxis(); - int xbin_south = south_xaxis->FindBin(_ssum); - int ybin_south = south_yaxis->FindBin(_mbdvtx); - - // north - TAxis *north_xaxis = - tprof_cos_north_epd_shift_input[order][p]->GetXaxis(); - TAxis *north_yaxis = - tprof_cos_north_epd_shift_input[order][p]->GetYaxis(); - int xbin_north = north_xaxis->FindBin(_nsum); - int ybin_north = north_yaxis->FindBin(_mbdvtx); - - // // northsouth - TAxis *northsouth_xaxis = - tprof_cos_northsouth_epd_shift_input[order][p]->GetXaxis(); - TAxis *northsouth_yaxis = - tprof_cos_northsouth_epd_shift_input[order][p]->GetYaxis(); - int xbin_northsouth = northsouth_xaxis->FindBin(_totalcharge); - int ybin_northsouth = northsouth_yaxis->FindBin(_mbdvtx); - - // Equation (6) of arxiv:nucl-ex/9805001 - // i = terms; n = order; i*n = tmp - // (2 / i ) * * - // sin(i*n*psi_n) - * - // cos(i*n*psi_n) - - // north - shift_north[order] += - prefactor * - (tprof_cos_north_epd_shift_input[order][p]->GetBinContent( - xbin_north, ybin_north) * - sin(tmp * tmp_north_psi[order]) - - tprof_sin_north_epd_shift_input[order][p]->GetBinContent( - xbin_north, ybin_north) * - cos(tmp * tmp_north_psi[order])); - - // south - shift_south[order] += - prefactor * - (tprof_cos_south_epd_shift_input[order][p]->GetBinContent( - xbin_south, ybin_south) * - sin(tmp * tmp_south_psi[order]) - - tprof_sin_south_epd_shift_input[order][p]->GetBinContent( - xbin_south, ybin_south) * - cos(tmp * tmp_south_psi[order])); - - // // northsouth - shift_northsouth[order] += - prefactor * - (tprof_cos_northsouth_epd_shift_input[order][p] - ->GetBinContent(xbin_northsouth, ybin_northsouth) * - sin(tmp * tmp_northsouth_psi[order]) - - tprof_sin_northsouth_epd_shift_input[order][p] - ->GetBinContent(xbin_northsouth, ybin_northsouth) * - cos(tmp * tmp_northsouth_psi[order])); - } - } - } - - // n * deltapsi_n = (2 / i ) * * sin(i*n*psi_n) - - // * cos(i*n*psi_n) Divide out n - for (unsigned int order = 0; order < m_MaxOrder; order++) { - double n = order + 1.0; - shift_north[order] /= n; - shift_south[order] /= n; - shift_northsouth[order] /= n; - } - - // Now add shift to psi_n to flatten it - for (unsigned int order = 0; order < m_MaxOrder; order++) { - if (tprof_cos_north_epd_shift_input[0][0]) { - tmp_south_psi[order] += shift_south[order]; - tmp_north_psi[order] += shift_north[order]; - tmp_northsouth_psi[order] += shift_northsouth[order]; - } - } - - // Now enforce the range - for (unsigned int order = 0; order < m_MaxOrder; order++) { - if (tprof_cos_north_epd_shift_input[0][0]) { - double range = M_PI / (double)(order + 1); - if (tmp_south_psi[order] < -1.0 * range) { - tmp_south_psi[order] += 2.0 * range; - } - if (tmp_south_psi[order] > range) { - tmp_south_psi[order] -= 2.0 * range; - } - if (tmp_north_psi[order] < -1.0 * range) { - tmp_north_psi[order] += 2.0 * range; - } - if (tmp_north_psi[order] > range) { - tmp_north_psi[order] -= 2.0 * range; - } - if (tmp_northsouth_psi[order] < -1.0 * range) { - tmp_northsouth_psi[order] += 2.0 * range; - } - if (tmp_northsouth_psi[order] > range) { - tmp_northsouth_psi[order] -= 2.0 * range; - } - } - } - - for (unsigned int order = 0; order < m_MaxOrder; order++) { - south_Qvec.emplace_back(south_q[order][0], south_q[order][1]); - north_Qvec.emplace_back(north_q[order][0], north_q[order][1]); - northsouth_Qvec.emplace_back(northsouth_q[order][0], - northsouth_q[order][1]); - } - - if (epd_towerinfo) { - Eventplaneinfo *sepds = new Eventplaneinfov1(); - sepds->set_qvector(south_Qvec); - sepds->set_shifted_psi(tmp_south_psi); - epmap->insert(sepds, EventplaneinfoMap::sEPDS); - - Eventplaneinfo *sepdn = new Eventplaneinfov1(); - sepdn->set_qvector(north_Qvec); - sepdn->set_shifted_psi(tmp_north_psi); - epmap->insert(sepdn, EventplaneinfoMap::sEPDN); - - Eventplaneinfo *sepdns = new Eventplaneinfov1(); - sepdns->set_qvector(northsouth_Qvec); - sepdns->set_shifted_psi(tmp_northsouth_psi); - epmap->insert(sepdns, EventplaneinfoMap::sEPDNS); - - if (Verbosity() > 1) { - sepds->identify(); - sepdn->identify(); - sepdns->identify(); - } - } - } - } - } - } - - if (_mbdEpReco) { - ResetMe(); - - MbdPmtContainer *mbdpmts = - findNode::getClass(topNode, "MbdPmtContainer"); - if (!mbdpmts) { - std::cout << PHWHERE << "::ERROR - cannot find MbdPmtContainer" - << std::endl; - exit(-1); - } - - MbdGeom *mbdgeom = findNode::getClass(topNode, "MbdGeom"); - if (!mbdgeom) { - std::cout << PHWHERE << "::ERROR - cannot find MbdGeom" << std::endl; - exit(-1); - } - - if (mbdpmts) { - if (Verbosity()) { - std::cout << "EventPlaneCalibration::process_event - mbdpmts" << std::endl; - } - - for (int ipmt = 0; ipmt < mbdpmts->get_npmt(); ipmt++) { - float mbd_q = mbdpmts->get_pmt(ipmt)->get_q(); - _mbdQ += mbd_q; - } - - for (int ipmt = 0; ipmt < mbdpmts->get_npmt(); ipmt++) { - float mbd_q = mbdpmts->get_pmt(ipmt)->get_q(); - float phi = mbdgeom->get_phi(ipmt); - int arm = mbdgeom->get_arm(ipmt); - - if (_mbdQ < _mbd_e) { - continue; - } - - if (arm == 0) { - for (unsigned int order = 0; order < m_MaxOrder; order++) { - double Cosine = cos(phi * (double)(order + 1)); - double Sine = sin(phi * (double)(order + 1)); - south_q[order][0] += mbd_q * Cosine; // south Qn,x - south_q[order][1] += mbd_q * Sine; // south Qn,y - } - } else if (arm == 1) { - for (unsigned int order = 0; order < m_MaxOrder; order++) { - double Cosine = cos(phi * (double)(order + 1)); - double Sine = sin(phi * (double)(order + 1)); - north_q[order][0] += mbd_q * Cosine; // north Qn,x - north_q[order][1] += mbd_q * Sine; // north Qn,y - } - } - } - } - - for (unsigned int order = 0; order < m_MaxOrder; order++) { - south_Qvec.emplace_back(south_q[order][0], south_q[order][1]); - north_Qvec.emplace_back(north_q[order][0], north_q[order][1]); - } - - if (mbdpmts) { - Eventplaneinfo *mbds = new Eventplaneinfov1(); - mbds->set_qvector(south_Qvec); - epmap->insert(mbds, EventplaneinfoMap::MBDS); - - Eventplaneinfo *mbdn = new Eventplaneinfov1(); - mbdn->set_qvector(north_Qvec); - epmap->insert(mbdn, EventplaneinfoMap::MBDN); - - if (Verbosity() > 1) { - mbds->identify(); - mbdn->identify(); - } - } - - ResetMe(); - } - - if (Verbosity()) { - epmap->identify(); - } - - return Fun4AllReturnCodes::EVENT_OK; -} - -int EventPlaneCalibration::CreateNodes(PHCompositeNode *topNode) { - PHNodeIterator iter(topNode); - - PHCompositeNode *dstNode = - dynamic_cast(iter.findFirst("PHCompositeNode", "DST")); - if (!dstNode) { - std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl; - return Fun4AllReturnCodes::ABORTRUN; - } - - PHCompositeNode *globalNode = dynamic_cast( - iter.findFirst("PHCompositeNode", "GLOBAL")); - if (!globalNode) { - globalNode = new PHCompositeNode("GLOBAL"); - dstNode->addNode(globalNode); - } - - EventplaneinfoMap *eps = - findNode::getClass(topNode, "EventplaneinfoMap"); - if (!eps) { - eps = new EventplaneinfoMapv1(); - PHIODataNode *EpMapNode = - new PHIODataNode(eps, "EventplaneinfoMap", "PHObject"); - globalNode->addNode(EpMapNode); - } - return Fun4AllReturnCodes::EVENT_OK; -} - -void EventPlaneCalibration::ResetMe() { - for (auto &vec : south_q) { - std::fill(vec.begin(), vec.end(), 0.); - } - - for (auto &vec : north_q) { - std::fill(vec.begin(), vec.end(), 0.); - } - - for (auto &vec : northsouth_q) { - std::fill(vec.begin(), vec.end(), 0.); - } - - south_Qvec.clear(); - north_Qvec.clear(); - northsouth_Qvec.clear(); - - for (auto &vec : south_q_subtract) { - std::fill(vec.begin(), vec.end(), 0.); - } - - for (auto &vec : north_q_subtract) { - std::fill(vec.begin(), vec.end(), 0.); - } - - for (auto &vec : northsouth_q_subtract) { - std::fill(vec.begin(), vec.end(), 0.); - } - - std::fill(shift_north.begin(), shift_north.end(), 0.); - std::fill(shift_south.begin(), shift_south.end(), 0.); - std::fill(shift_northsouth.begin(), shift_northsouth.end(), 0.); - - std::fill(tmp_south_psi.begin(), tmp_south_psi.end(), NAN); - std::fill(tmp_north_psi.begin(), tmp_north_psi.end(), NAN); - std::fill(tmp_northsouth_psi.begin(), tmp_northsouth_psi.end(), NAN); - - _nsum = 0.; - _ssum = 0.; - _do_ep = false; - _mbdQ = 0.; - _totalcharge = 0.; -} - -int EventPlaneCalibration::End(PHCompositeNode * /*topNode*/) { - - cdbhistosOut->WriteCDBHistos(); - delete cdbhistosOut; - - std::cout << " EventPlaneCalibration::End() " << std::endl; - return Fun4AllReturnCodes::EVENT_OK; -} diff --git a/offline/packages/eventplaneinfo/EventPlaneCalibration.h b/offline/packages/eventplaneinfo/EventPlaneCalibration.h deleted file mode 100644 index 94875c08d2..0000000000 --- a/offline/packages/eventplaneinfo/EventPlaneCalibration.h +++ /dev/null @@ -1,121 +0,0 @@ -// Tell emacs that this is a C++ source -// -*- C++ -*-. -#ifndef EVENTPLANEINFO_EVENTPLANECALIBRATION_H -#define EVENTPLANEINFO_EVENTPLANECALIBRATION_H - -//=========================================================== -/// \author Ejiro Umaka -//=========================================================== - -#include - -#include // for string -#include // for vector - -class CDBHistos; -class TProfile2D; - -class PHCompositeNode; - -class EventPlaneCalibration : public SubsysReco { -public: - EventPlaneCalibration(const std::string &name = "EventPlaneCalibration"); - ~EventPlaneCalibration() override = default; - int InitRun(PHCompositeNode *topNode) override; - int process_event(PHCompositeNode *topNode) override; - int End(PHCompositeNode * /*topNode*/) override; - - void ResetMe(); - void set_sepd_epreco(bool sepdEpReco) { _sepdEpReco = sepdEpReco; } - void set_default_calibfile(bool default_calib) { - _default_calib = default_calib; - } - void set_mbd_epreco(bool mbdEpReco) { _mbdEpReco = mbdEpReco; } - void set_isSim(bool isSim) { _isSim = isSim; } - void set_sEPD_Mip_cut(const float e) { _epd_e = e; } - void set_sEPD_Charge_cut(const float c) { _epd_charge_min = c; } - void set_MBD_Min_Qcut(const float f) { _mbd_e = f; } - void set_MBD_Vetex_cut(const float v) { _mbd_vertex_cut = v; } - void set_Ep_orders(const unsigned int n) { m_MaxOrder = n; } - void set_outfilename(const std::string &name) {OutFileName = name;} - -private: - int CreateNodes(PHCompositeNode *topNode); - unsigned int m_MaxOrder{3}; - int m_runNo{0}; - std::string OutFileName; - CDBHistos *cdbhistosOut{nullptr}; - - std::vector> south_q; - std::vector> north_q; - std::vector> northsouth_q; - - std::vector> south_Qvec; - std::vector> north_Qvec; - std::vector> northsouth_Qvec; - - // recentering utility - std::vector> south_q_subtract; - std::vector> north_q_subtract; - std::vector> northsouth_q_subtract; - - // shifting utility - std::vector shift_north; - std::vector shift_south; - std::vector shift_northsouth; - std::vector tmp_south_psi; - std::vector tmp_north_psi; - std::vector tmp_northsouth_psi; - - // recentering histograms - - TProfile2D *tprof_mean_cos_north_epd[6]{}; - TProfile2D *tprof_mean_sin_north_epd[6]{}; - TProfile2D *tprof_mean_cos_south_epd[6]{}; - TProfile2D *tprof_mean_sin_south_epd[6]{}; - TProfile2D *tprof_mean_cos_northsouth_epd[6]{}; - TProfile2D *tprof_mean_sin_northsouth_epd[6]{}; - - TProfile2D *tprof_mean_cos_north_epd_input[6]{}; - TProfile2D *tprof_mean_sin_north_epd_input[6]{}; - TProfile2D *tprof_mean_cos_south_epd_input[6]{}; - TProfile2D *tprof_mean_sin_south_epd_input[6]{}; - TProfile2D *tprof_mean_cos_northsouth_epd_input[6]{}; - TProfile2D *tprof_mean_sin_northsouth_epd_input[6]{}; - - // shifting histograms - const int _imax{12}; - - TProfile2D *tprof_cos_north_epd_shift[6][12]{}; - TProfile2D *tprof_sin_north_epd_shift[6][12]{}; - TProfile2D *tprof_cos_south_epd_shift[6][12]{}; - TProfile2D *tprof_sin_south_epd_shift[6][12]{}; - TProfile2D *tprof_cos_northsouth_epd_shift[6][12]{}; - TProfile2D *tprof_sin_northsouth_epd_shift[6][12]{}; - - TProfile2D *tprof_cos_north_epd_shift_input[6][12]{}; - TProfile2D *tprof_sin_north_epd_shift_input[6][12]{}; - TProfile2D *tprof_cos_south_epd_shift_input[6][12]{}; - TProfile2D *tprof_sin_south_epd_shift_input[6][12]{}; - TProfile2D *tprof_cos_northsouth_epd_shift_input[6][12]{}; - TProfile2D *tprof_sin_northsouth_epd_shift_input[6][12]{}; - - bool _mbdEpReco{false}; - bool _sepdEpReco{false}; - bool _isSim{false}; - bool _do_ep{false}; - bool _default_calib{false}; - - float _nsum{0.0}; - float _ssum{0.0}; - float _mbdvtx{999.0}; - float _epd_charge_min{5.0}; - float _epd_charge_max{10000.0}; - float _epd_e{10.0}; - float _mbd_e{10.0}; - float _mbdQ{0.0}; - double _totalcharge{0.0}; - float _mbd_vertex_cut{60.0}; -}; - -#endif // EVENTPLANEINFO_EVENTPLANECALIBRATION_H diff --git a/offline/packages/eventplaneinfo/EventPlaneReco.cc b/offline/packages/eventplaneinfo/EventPlaneReco.cc index f0c9f73dd4..0179e08926 100644 --- a/offline/packages/eventplaneinfo/EventPlaneReco.cc +++ b/offline/packages/eventplaneinfo/EventPlaneReco.cc @@ -1,803 +1,671 @@ #include "EventPlaneReco.h" -#include "Eventplaneinfo.h" -#include "EventplaneinfoMap.h" #include "EventplaneinfoMapv1.h" -#include "Eventplaneinfov1.h" +#include "Eventplaneinfov2.h" #include #include #include +// -- Centrality +#include + +// -- sEPD #include -#include -#include -#include -#include +#include // for CDBTTree -#include -#include -#include -#include +// -- event +#include -#include -#include #include #include -#include // for SubsysReco -#include -#include -#include // for PHNode -#include -#include // for PHObject #include -#include // for PHWHERE -#include - -#include +#include +#include -#include // for array -#include -#include -#include // for exit -#include +// c++ includes -- #include -#include // for _Rb_tree_const_iterator -#include // for pair -#include // for vector - -EventPlaneReco::EventPlaneReco(const std::string &name) : SubsysReco(name) { - - south_q.resize(m_MaxOrder); - north_q.resize(m_MaxOrder); - northsouth_q.resize(m_MaxOrder); +#include +#include +#include - south_q_subtract.resize(m_MaxOrder); - north_q_subtract.resize(m_MaxOrder); - northsouth_q_subtract.resize(m_MaxOrder); +//____________________________________________________________________________.. +EventPlaneReco::EventPlaneReco(const std::string &name): + SubsysReco(name) +{ +} - shift_north.resize(m_MaxOrder); - shift_south.resize(m_MaxOrder); - shift_northsouth.resize(m_MaxOrder); - tmp_south_psi.resize(m_MaxOrder); - tmp_north_psi.resize(m_MaxOrder); - tmp_northsouth_psi.resize(m_MaxOrder); +//____________________________________________________________________________.. +int EventPlaneReco::Init(PHCompositeNode *topNode) +{ + std::string calibdir = CDBInterface::instance()->getUrl(m_calibName); - for (auto &vec : south_q) { - vec.resize(2); + if (!m_directURL_EventPlaneCalib.empty()) + { + m_cdbttree = new CDBTTree(m_directURL_EventPlaneCalib); + std::cout << PHWHERE << " Custom Event Plane Calib Found: " << m_directURL_EventPlaneCalib << std::endl; } - - for (auto &vec : north_q) { - vec.resize(2); + else if (!calibdir.empty()) + { + m_cdbttree = new CDBTTree(calibdir); + std::cout << PHWHERE << " Event Plane Calib Found: " << calibdir << std::endl; } - - for (auto &vec : northsouth_q) { - vec.resize(2); + else if (m_doAbortNoEventPlaneCalib) + { + std::cout << PHWHERE << " Error: No Event Plane Calib Found and m_doAbortNoEventPlaneCalib is true. Aborting." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + else + { + std::cout << PHWHERE << " Error: No Event Plane Calib Found. Skipping Event Plane Calibrations." << std::endl; + m_doNotCalib = true; } - for (auto &vec : south_q_subtract) { - vec.resize(2); + if (!m_doNotCalib) + { + LoadCalib(); } - for (auto &vec : north_q_subtract) { - vec.resize(2); + if (Verbosity() > 0) + { + print_correction_data(); } - for (auto &vec : northsouth_q_subtract) { - vec.resize(2); + return CreateNodes(topNode); +} + +int EventPlaneReco::InitRun(PHCompositeNode* topNode) +{ + EpdGeom* epdgeom = findNode::getClass(topNode, "TOWERGEOM_EPD"); + if (!epdgeom) + { + std::cout << PHWHERE << " Error: TOWERGEOM_EPD is missing. Cannot build trig cache." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; } - ring_q_north.resize(nRings); - ring_q_south.resize(nRings); + m_trig_cache.assign(m_harmonics.size(), std::vector>(SEPD_CHANNELS)); + + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + int n = m_harmonics[h_idx]; + for (int channel = 0; channel < SEPD_CHANNELS; ++channel) + { + unsigned int key = TowerInfoDefs::encode_epd(channel); + double phi = epdgeom->get_phi(key); - for (auto &rq : ring_q_north) { - rq.resize(m_MaxOrder, std::vector(2, 0.0)); + m_trig_cache[h_idx][channel] = {std::cos(n * phi), std::sin(n * phi)}; + } } - for (auto &rq : ring_q_south) { - rq.resize(m_MaxOrder, std::vector(2, 0.0)); + + if (Verbosity() > 0) + { + std::cout << PHWHERE << " Trigonometry cache initialized for " << SEPD_CHANNELS << " sEPD channels." << std::endl; } - all_ring_Qvecs_north.assign( - nRings, std::vector>(m_MaxOrder, {0.0, 0.0})); + return Fun4AllReturnCodes::EVENT_OK; +} - all_ring_Qvecs_south.assign( - nRings, std::vector>(m_MaxOrder, {0.0, 0.0})); +std::array, 2> EventPlaneReco::calculate_flattening_matrix(double xx, double yy, double xy, int n, int cent_bin, const std::string& det_label) +{ + std::array, 2> mat{}; + + double D_arg = (xx * yy) - (xy * xy); + if (D_arg <= 0) + { + std::cout << PHWHERE << "Invalid D-term " << D_arg << " for n=" << n << ", cent bin=" << cent_bin << ", det=" << det_label << std::endl; + // Return Identity Matrix to preserve Recentered vector + mat[0][0] = 1.0; + mat[1][1] = 1.0; + return mat; + } + double D = std::sqrt(D_arg); + + double N_term = D * (xx + yy + (2 * D)); + if (N_term <= 0) + { + std::cout << PHWHERE << "Invalid N-term " << N_term << " for n=" << n << ", cent bin=" << cent_bin << ", det=" << det_label << std::endl; + // Return Identity Matrix to preserve Recentered vector + mat[0][0] = 1.0; + mat[1][1] = 1.0; + return mat; + } + double inv_sqrt_N = 1.0 / std::sqrt(N_term); + + mat[0][0] = inv_sqrt_N * (yy + D); + mat[0][1] = -inv_sqrt_N * xy; + mat[1][0] = mat[0][1]; + mat[1][1] = inv_sqrt_N * (xx + D); + return mat; } -int EventPlaneReco::InitRun(PHCompositeNode *topNode) { +//____________________________________________________________________________.. +void EventPlaneReco::LoadCalib() +{ + size_t south_idx = static_cast(Subdetector::S); + size_t north_idx = static_cast(Subdetector::N); + size_t ns_idx = static_cast(Subdetector::NS); - FileName = "EVENTPLANE_CORRECTION"; - if (_isSim) { - FileName = "EVENTPLANE_CORRECTION_SIM"; - } + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + int n = m_harmonics[h_idx]; - std::string calibdir = CDBInterface::instance()->getUrl(FileName); + std::string S_x_avg_name = std::format("Q_S_x_{}_avg", n); + std::string S_y_avg_name = std::format("Q_S_y_{}_avg", n); + std::string N_x_avg_name = std::format("Q_N_x_{}_avg", n); + std::string N_y_avg_name = std::format("Q_N_y_{}_avg", n); - if (calibdir.empty()) { - std::cout << PHWHERE << "No Eventplane calibration file for domain " - << FileName << " found" << std::endl; - std::cout << PHWHERE - << "Will only produce raw Q vectors and event plane angles " - << std::endl; - } - - CDBHistos *cdbhistosIn = new CDBHistos(calibdir); - cdbhistosIn->LoadCalibrations(); - - // Get phiweights - h_phi_weight_south_input = - dynamic_cast(cdbhistosIn->getHisto("h_phi_weight_south", false)); - h_phi_weight_north_input = - dynamic_cast(cdbhistosIn->getHisto("h_phi_weight_north", false)); - - // Get recentering histograms - for (unsigned int order = 0; order < m_MaxOrder; order++) { - tprof_mean_cos_south_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_cos_south_epd_order_{}", order), false)); - tprof_mean_sin_south_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_sin_south_epd_order_{}", order), false)); - tprof_mean_cos_north_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_cos_north_epd_order_{}", order), false)); - tprof_mean_sin_north_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_sin_north_epd_order_{}", order), false)); - tprof_mean_cos_northsouth_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_cos_northsouth_epd_order_{}", order), - false)); - tprof_mean_sin_northsouth_epd_input[order] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_mean_sin_northsouth_epd_order_{}", order), - false)); - } - - // Get shifting histograms - for (unsigned int order = 0; order < m_MaxOrder; order++) { - for (int p = 0; p < _imax; p++) { - tprof_cos_north_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_cos_north_epd_shift_order_{}_{}", order, p), - false)); - tprof_sin_north_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_sin_north_epd_shift_order_{}_{}", order, p), - false)); - tprof_cos_south_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_cos_south_epd_shift_order_{}_{}", order, p), - false)); - tprof_sin_south_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_sin_south_epd_shift_order_{}_{}", order, p), - false)); - tprof_cos_northsouth_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_cos_northsouth_epd_shift_order_{}_{}", order, - p), - false)); - tprof_sin_northsouth_epd_shift_input[order][p] = - dynamic_cast(cdbhistosIn->getHisto( - std::format("tprof_sin_northsouth_epd_shift_order_{}_{}", order, - p), - false)); - } - } + std::string S_xx_avg_name = std::format("Q_S_xx_{}_avg", n); + std::string S_yy_avg_name = std::format("Q_S_yy_{}_avg", n); + std::string S_xy_avg_name = std::format("Q_S_xy_{}_avg", n); + std::string N_xx_avg_name = std::format("Q_N_xx_{}_avg", n); + std::string N_yy_avg_name = std::format("Q_N_yy_{}_avg", n); + std::string N_xy_avg_name = std::format("Q_N_xy_{}_avg", n); - if (Verbosity() > 1) { - cdbhistosIn->Print(); - } + std::string NS_xx_avg_name = std::format("Q_NS_xx_{}_avg", n); + std::string NS_yy_avg_name = std::format("Q_NS_yy_{}_avg", n); + std::string NS_xy_avg_name = std::format("Q_NS_xy_{}_avg", n); - return CreateNodes(topNode); -} + for (size_t cent_bin = 0; cent_bin < m_cent_bins; ++cent_bin) + { + int key = cent_bin; -int EventPlaneReco::process_event(PHCompositeNode *topNode) { - if (Verbosity() > 1) { - std::cout << "EventPlaneReco::process_event -- entered" << std::endl; - } + // South + auto& dataS = m_correction_data[h_idx][cent_bin][south_idx]; + dataS.avg_Q.x = m_cdbttree->GetDoubleValue(key, S_x_avg_name); + dataS.avg_Q.y = m_cdbttree->GetDoubleValue(key, S_y_avg_name); - //--------------------------------- - // Get Objects off of the Node Tree - //--------------------------------- + dataS.avg_Q_xx = m_cdbttree->GetDoubleValue(key, S_xx_avg_name); + dataS.avg_Q_yy = m_cdbttree->GetDoubleValue(key, S_yy_avg_name); + dataS.avg_Q_xy = m_cdbttree->GetDoubleValue(key, S_xy_avg_name); - if (_isSim) { - // Use GlobalVertexMap for simulation - GlobalVertexMap *vertexmap = - findNode::getClass(topNode, "GlobalVertexMap"); - if (!vertexmap) { - std::cout << PHWHERE << "::ERROR - cannot find GlobalVertexMap" - << std::endl; - exit(-1); - } + dataS.X_matrix = calculate_flattening_matrix(dataS.avg_Q_xx, dataS.avg_Q_yy, dataS.avg_Q_xy, n, cent_bin, "South"); - if (!vertexmap->empty()) { - GlobalVertex *vtx = vertexmap->begin()->second; - if (vtx) { - _mbdvtx = vtx->get_z(); - } - } - } else { - // Use MbdVertexMap for data - MbdVertexMap *mbdvtxmap = - findNode::getClass(topNode, "MbdVertexMap"); - if (!mbdvtxmap) { - std::cout << PHWHERE << "::ERROR - cannot find MbdVertexMap" << std::endl; - exit(-1); - } + // North + auto& dataN = m_correction_data[h_idx][cent_bin][north_idx]; + dataN.avg_Q.x = m_cdbttree->GetDoubleValue(key, N_x_avg_name); + dataN.avg_Q.y = m_cdbttree->GetDoubleValue(key, N_y_avg_name); - MbdVertex *mvertex = nullptr; - if (mbdvtxmap) { - for (MbdVertexMap::ConstIter mbditer = mbdvtxmap->begin(); - mbditer != mbdvtxmap->end(); ++mbditer) { - mvertex = mbditer->second; - } - if (mvertex) { - _mbdvtx = mvertex->get_z(); - } - } - } + dataN.avg_Q_xx = m_cdbttree->GetDoubleValue(key, N_xx_avg_name); + dataN.avg_Q_yy = m_cdbttree->GetDoubleValue(key, N_yy_avg_name); + dataN.avg_Q_xy = m_cdbttree->GetDoubleValue(key, N_xy_avg_name); - EventplaneinfoMap *epmap = - findNode::getClass(topNode, "EventplaneinfoMap"); - if (!epmap) { - std::cout << PHWHERE << "::ERROR - cannot find EventplaneinfoMap" - << std::endl; - exit(-1); - } + dataN.X_matrix = calculate_flattening_matrix(dataN.avg_Q_xx, dataN.avg_Q_yy, dataN.avg_Q_xy, n, cent_bin, "North"); - if (_sepdEpReco) { + // North South + // Note: We do NOT load avg_Q (x,y) for NS because NS is recentered by summing the recentered S and N vectors. + auto& dataNS = m_correction_data[h_idx][cent_bin][ns_idx]; - TowerInfoContainer *epd_towerinfo = - findNode::getClass(topNode, "TOWERINFO_CALIB_SEPD"); - if (!epd_towerinfo) { - epd_towerinfo = findNode::getClass( - topNode, "TOWERINFO_CALIB_EPD"); - if (!epd_towerinfo) { - std::cout << PHWHERE - << "::ERROR - cannot find sEPD Calibrated TowerInfoContainer" - << std::endl; - exit(-1); - } - } + dataNS.avg_Q_xx = m_cdbttree->GetDoubleValue(key, NS_xx_avg_name); + dataNS.avg_Q_yy = m_cdbttree->GetDoubleValue(key, NS_yy_avg_name); + dataNS.avg_Q_xy = m_cdbttree->GetDoubleValue(key, NS_xy_avg_name); - EpdGeom *_epdgeom = findNode::getClass(topNode, "TOWERGEOM_EPD"); - if (!_epdgeom) { - std::cout << PHWHERE << "::ERROR - cannot find TOWERGEOM_EPD" - << std::endl; - exit(-1); + dataNS.X_matrix = calculate_flattening_matrix(dataNS.avg_Q_xx, dataNS.avg_Q_yy, dataNS.avg_Q_xy, n, cent_bin, "NorthSouth"); } + } + delete m_cdbttree; + m_cdbttree = nullptr; +} - ResetMe(); - - if ((std::fabs(_mbdvtx) < _mbd_vertex_cut)) { - - unsigned int ntowers = epd_towerinfo->size(); - for (unsigned int ch = 0; ch < ntowers; ch++) { - TowerInfo *_tower = epd_towerinfo->get_tower_at_channel(ch); - float epd_e = _tower->get_energy(); - bool isZS = _tower->get_isZS(); - if (!isZS) // exclude ZS +//____________________________________________________________________________.. +void EventPlaneReco::print_correction_data() +{ + std::cout << std::format("\n{:=>60}\n", ""); + std::cout << std::format("{:^60}\n", "EVENT PLANE CORRECTION DATA SUMMARY"); + std::cout << std::format("{:=>60}\n", ""); + + // Iterate through harmonics {2, 3, 4} + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + int n = m_harmonics[h_idx]; + std::cout << std::format("\n>>> HARMONIC n = {} <<<\n", n); + + // Iterate through Centrality Bins (0-79) + for (size_t cent = 0; cent < m_cent_bins; ++cent) + { + std::cout << std::format("\n Centrality Bin: {}\n", cent); + std::cout << std::format(" {:->30}\n", ""); + + // Header with fixed column widths + std::cout << std::format(" {:<12} {:>10} {:>10} {:>10} {:>10} {:>10}\n", + "Detector", "Avg Qx", "Avg Qy", "Avg Qxx", "Avg Qyy", "Avg Qxy"); + + // Iterate through Subdetectors {S, N} + for (size_t det_idx = 0; det_idx < 3; ++det_idx) + { + std::string det_name; + if (det_idx == 0) { - unsigned int key = TowerInfoDefs::encode_epd(ch); - int arm = TowerInfoDefs::get_epd_arm(key); - if (arm == 0) { - _ssum += epd_e; - } else if (arm == 1) { - _nsum += epd_e; - } + det_name = "South"; + } + else if (det_idx == 1) + { + det_name = "North"; + } + else + { + det_name = "NorthSouth"; } - } - if (_ssum > _epd_charge_min && _nsum > _epd_charge_min && - _ssum < _epd_charge_max && _nsum < _epd_charge_max) { - _do_ep = true; - } + const auto& data = m_correction_data[h_idx][cent][det_idx]; - if (_do_ep) { - - // Apply phi weights in builiding ring Q-vectors - for (unsigned int ch = 0; ch < ntowers; ch++) { - TowerInfo *_tower = epd_towerinfo->get_tower_at_channel(ch); - float epd_e = _tower->get_energy(); - bool isZS = _tower->get_isZS(); - if (!isZS) // exclude ZS - { - if (epd_e < 0.2) // expecting Nmips - { - continue; - } - unsigned int key = TowerInfoDefs::encode_epd(ch); - float tile_phi = _epdgeom->get_phi(key); - int arm = TowerInfoDefs::get_epd_arm(key); - int rbin = TowerInfoDefs::get_epd_rbin(key); - int phibin = TowerInfoDefs::get_epd_phibin(key); - - float truncated_e = - (epd_e < _epd_e) ? epd_e : _epd_e; // set cutoff at _epd_e - - float TileWeight = truncated_e; // default - - if (h_phi_weight_south_input && h_phi_weight_north_input) { - if (arm == 0) { - TileWeight = - truncated_e * h_phi_weight_south_input->GetBinContent( - phibin + 1); // scale by 1/ - } else if (arm == 1) { - TileWeight = - truncated_e * h_phi_weight_north_input->GetBinContent( - phibin + 1); // scale by 1/ - } - } - - for (unsigned int order = 0; order < m_MaxOrder; ++order) { - double Cosine = cos(tile_phi * (double)(order + 1)); - double Sine = sin(tile_phi * (double)(order + 1)); - - // Arm-specific Q-vectors - if (arm == 0) { - south_q[order][0] += truncated_e * Cosine; - south_q[order][1] += truncated_e * Sine; - ring_q_south[rbin][order][0] += TileWeight * Cosine; - ring_q_south[rbin][order][1] += TileWeight * Sine; - - } else if (arm == 1) { - north_q[order][0] += truncated_e * Cosine; - north_q[order][1] += truncated_e * Sine; - ring_q_north[rbin][order][0] += TileWeight * Cosine; - ring_q_north[rbin][order][1] += TileWeight * Sine; - } - - // Combined Q-vectors - northsouth_q[order][0] += truncated_e * Cosine; - northsouth_q[order][1] += truncated_e * Sine; - } - } - } + // For NS, Avg Qx/Qy will be 0.0 because they are not loaded from CDB. + // This is expected behavior. + std::cout << std::format(" {:<12} {:>10.6f} {:>10.6f} {:>10.6f} {:>10.6f} {:>10.6f}\n", + det_name, + data.avg_Q.x, data.avg_Q.y, + data.avg_Q_xx, data.avg_Q_yy, data.avg_Q_xy); - _totalcharge = _nsum + _ssum; - - // Get recentering histograms and do recentering - // Recentering: subtract Qn,x and Qn,y values averaged over all events - for (unsigned int order = 0; order < m_MaxOrder; order++) { - if (tprof_mean_cos_south_epd_input[order]) // check if recentering - // histograms exist - { - // south - TAxis *south_xaxis = - tprof_mean_cos_south_epd_input[order]->GetXaxis(); - TAxis *south_yaxis = - tprof_mean_cos_south_epd_input[order]->GetYaxis(); - int xbin_south = south_xaxis->FindBin(_ssum); - int ybin_south = south_yaxis->FindBin(_mbdvtx); - - double event_ave_cos_south = - tprof_mean_cos_south_epd_input[order]->GetBinContent( - xbin_south, ybin_south); - double event_ave_sin_south = - tprof_mean_sin_south_epd_input[order]->GetBinContent( - xbin_south, ybin_south); - south_q_subtract[order][0] = _ssum * event_ave_cos_south; - south_q_subtract[order][1] = _ssum * event_ave_sin_south; - south_q[order][0] -= south_q_subtract[order][0]; - south_q[order][1] -= south_q_subtract[order][1]; - - // north - TAxis *north_xaxis = - tprof_mean_cos_north_epd_input[order]->GetXaxis(); - TAxis *north_yaxis = - tprof_mean_cos_north_epd_input[order]->GetYaxis(); - int xbin_north = north_xaxis->FindBin(_nsum); - int ybin_north = north_yaxis->FindBin(_mbdvtx); - - double event_ave_cos_north = - tprof_mean_cos_north_epd_input[order]->GetBinContent( - xbin_north, ybin_north); - double event_ave_sin_north = - tprof_mean_sin_north_epd_input[order]->GetBinContent( - xbin_north, ybin_north); - north_q_subtract[order][0] = _nsum * event_ave_cos_north; - north_q_subtract[order][1] = _nsum * event_ave_sin_north; - north_q[order][0] -= north_q_subtract[order][0]; - north_q[order][1] -= north_q_subtract[order][1]; - - // northsouth - TAxis *northsouth_xaxis = - tprof_mean_cos_northsouth_epd_input[order]->GetXaxis(); - TAxis *northsouth_yaxis = - tprof_mean_cos_northsouth_epd_input[order]->GetYaxis(); - int xbin_northsouth = northsouth_xaxis->FindBin(_totalcharge); - int ybin_northsouth = northsouth_yaxis->FindBin(_mbdvtx); - - double event_ave_cos_northsouth = - tprof_mean_cos_northsouth_epd_input[order]->GetBinContent( - xbin_northsouth, ybin_northsouth); - double event_ave_sin_northsouth = - tprof_mean_sin_northsouth_epd_input[order]->GetBinContent( - xbin_northsouth, ybin_northsouth); - northsouth_q_subtract[order][0] = - _totalcharge * event_ave_cos_northsouth; - northsouth_q_subtract[order][1] = - _totalcharge * event_ave_sin_northsouth; - northsouth_q[order][0] -= northsouth_q_subtract[order][0]; - northsouth_q[order][1] -= northsouth_q_subtract[order][1]; - } - } + // Print X-Matrix in a bracketed layout + std::cout << std::format(" X-Matrix: [ {:>8.6f}, {:>8.6f} ]\n", + data.X_matrix[0][0], data.X_matrix[0][1]); + std::cout << std::format(" [ {:>8.6f}, {:>8.6f} ]\n", + data.X_matrix[1][0], data.X_matrix[1][1]); + } + } + } + std::cout << std::format("\n{:=>60}\n", ""); +} - // Get recentered psi_n - Eventplaneinfo *epinfo = new Eventplaneinfov1(); - for (unsigned int order = 0; order < m_MaxOrder; order++) { - double n = order + 1.0; - if (tprof_mean_cos_south_epd_input[order]) // if present, Qs are - // recentered - { - tmp_south_psi[order] = - epinfo->GetPsi(south_q[order][0], south_q[order][1], n); - tmp_north_psi[order] = - epinfo->GetPsi(north_q[order][0], north_q[order][1], n); - tmp_northsouth_psi[order] = epinfo->GetPsi( - northsouth_q[order][0], northsouth_q[order][1], n); - } else { - tmp_south_psi[order] = NAN; - tmp_north_psi[order] = NAN; - tmp_northsouth_psi[order] = NAN; - } - } +int EventPlaneReco::CreateNodes(PHCompositeNode *topNode) { + PHNodeIterator iter(topNode); - // Get shifting histograms and calculate shift - for (unsigned int order = 0; order < m_MaxOrder; order++) { - for (int p = 0; p < _imax; p++) { - if (tprof_cos_south_epd_shift_input[order][p]) // check if shifting - // histograms exist - { - double terms = p + 1.0; - double n = order + 1.0; - double tmp = n * terms; - double prefactor = 2.0 / terms; - - // south - TAxis *south_xaxis = - tprof_cos_south_epd_shift_input[order][p]->GetXaxis(); - TAxis *south_yaxis = - tprof_cos_south_epd_shift_input[order][p]->GetYaxis(); - int xbin_south = south_xaxis->FindBin(_ssum); - int ybin_south = south_yaxis->FindBin(_mbdvtx); - - // north - TAxis *north_xaxis = - tprof_cos_north_epd_shift_input[order][p]->GetXaxis(); - TAxis *north_yaxis = - tprof_cos_north_epd_shift_input[order][p]->GetYaxis(); - int xbin_north = north_xaxis->FindBin(_nsum); - int ybin_north = north_yaxis->FindBin(_mbdvtx); - - // // northsouth - TAxis *northsouth_xaxis = - tprof_cos_northsouth_epd_shift_input[order][p]->GetXaxis(); - TAxis *northsouth_yaxis = - tprof_cos_northsouth_epd_shift_input[order][p]->GetYaxis(); - int xbin_northsouth = northsouth_xaxis->FindBin(_totalcharge); - int ybin_northsouth = northsouth_yaxis->FindBin(_mbdvtx); - - // Equation (6) of arxiv:nucl-ex/9805001 - // i = terms; n = order; i*n = tmp - // (2 / i ) * * sin(i*n*psi_n) - // - * cos(i*n*psi_n) - - // north - shift_north[order] += - prefactor * - (tprof_cos_north_epd_shift_input[order][p]->GetBinContent( - xbin_north, ybin_north) * - sin(tmp * tmp_north_psi[order]) - - tprof_sin_north_epd_shift_input[order][p]->GetBinContent( - xbin_north, ybin_north) * - cos(tmp * tmp_north_psi[order])); - - // south - shift_south[order] += - prefactor * - (tprof_cos_south_epd_shift_input[order][p]->GetBinContent( - xbin_south, ybin_south) * - sin(tmp * tmp_south_psi[order]) - - tprof_sin_south_epd_shift_input[order][p]->GetBinContent( - xbin_south, ybin_south) * - cos(tmp * tmp_south_psi[order])); - - // // northsouth - shift_northsouth[order] += - prefactor * - (tprof_cos_northsouth_epd_shift_input[order][p] - ->GetBinContent(xbin_northsouth, ybin_northsouth) * - sin(tmp * tmp_northsouth_psi[order]) - - tprof_sin_northsouth_epd_shift_input[order][p] - ->GetBinContent(xbin_northsouth, ybin_northsouth) * - cos(tmp * tmp_northsouth_psi[order])); - } - } - } + PHCompositeNode *dstNode = dynamic_cast(iter.findFirst("PHCompositeNode", "DST")); + if (!dstNode) + { + std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } - // n * deltapsi_n = (2 / i ) * * sin(i*n*psi_n) - - // * cos(i*n*psi_n) Divide out n - for (unsigned int order = 0; order < m_MaxOrder; order++) { - double n = order + 1.0; - shift_north[order] /= n; - shift_south[order] /= n; - shift_northsouth[order] /= n; - } + PHCompositeNode *globalNode = dynamic_cast(iter.findFirst("PHCompositeNode", "GLOBAL")); + if (!globalNode) + { + globalNode = new PHCompositeNode("GLOBAL"); + dstNode->addNode(globalNode); + } - // Now add shift to psi_n to flatten it - for (unsigned int order = 0; order < m_MaxOrder; order++) { - if (tprof_cos_north_epd_shift_input[0][0]) { - tmp_south_psi[order] += shift_south[order]; - tmp_north_psi[order] += shift_north[order]; - tmp_northsouth_psi[order] += shift_northsouth[order]; - } - } + EventplaneinfoMap *eps = findNode::getClass(topNode, m_EventPlaneInfoNodeName); + if (!eps) + { + eps = new EventplaneinfoMapv1(); + PHIODataNode *newNode = new PHIODataNode(eps , m_EventPlaneInfoNodeName, "PHObject"); + globalNode->addNode(newNode); + } - // Now enforce the range - for (unsigned int order = 0; order < m_MaxOrder; order++) { - if (tprof_cos_north_epd_shift_input[0][0]) { - double range = M_PI / (double)(order + 1); - if (tmp_south_psi[order] < -1.0 * range) { - tmp_south_psi[order] += 2.0 * range; - } - if (tmp_south_psi[order] > range) { - tmp_south_psi[order] -= 2.0 * range; - } - if (tmp_north_psi[order] < -1.0 * range) { - tmp_north_psi[order] += 2.0 * range; - } - if (tmp_north_psi[order] > range) { - tmp_north_psi[order] -= 2.0 * range; - } - if (tmp_northsouth_psi[order] < -1.0 * range) { - tmp_northsouth_psi[order] += 2.0 * range; - } - if (tmp_northsouth_psi[order] > range) { - tmp_northsouth_psi[order] -= 2.0 * range; - } - } - } + return Fun4AllReturnCodes::EVENT_OK; +} - for (unsigned int order = 0; order < m_MaxOrder; order++) { - south_Qvec.emplace_back(south_q[order][0], south_q[order][1]); - north_Qvec.emplace_back(north_q[order][0], north_q[order][1]); - northsouth_Qvec.emplace_back(northsouth_q[order][0], - northsouth_q[order][1]); - } +//____________________________________________________________________________.. +int EventPlaneReco::process_centrality(PHCompositeNode *topNode) +{ + CentralityInfo* centInfo = findNode::getClass(topNode, "CentralityInfo"); + if (!centInfo) + { + std::cout << PHWHERE << " CentralityInfo is missing doing nothing" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } - for (int rbin = 0; rbin < nRings; ++rbin) { - for (unsigned int order = 0; order < m_MaxOrder; ++order) { - all_ring_Qvecs_north[rbin][order] = std::make_pair( - ring_q_north[rbin][order][0], ring_q_north[rbin][order][1]); - all_ring_Qvecs_south[rbin][order] = std::make_pair( - ring_q_south[rbin][order][0], ring_q_south[rbin][order][1]); - } - } + m_cent = centInfo->get_centile(CentralityInfo::PROP::mbd_NS) * 100; - if (epd_towerinfo) { - Eventplaneinfo *sepds = new Eventplaneinfov1(); - sepds->set_qvector(south_Qvec); - sepds->set_shifted_psi(tmp_south_psi); - epmap->insert(sepds, EventplaneinfoMap::sEPDS); - - Eventplaneinfo *sepdn = new Eventplaneinfov1(); - sepdn->set_qvector(north_Qvec); - sepdn->set_shifted_psi(tmp_north_psi); - epmap->insert(sepdn, EventplaneinfoMap::sEPDN); - - Eventplaneinfo *sepdns = new Eventplaneinfov1(); - sepdns->set_qvector(northsouth_Qvec); - sepdns->set_shifted_psi(tmp_northsouth_psi); - epmap->insert(sepdns, EventplaneinfoMap::sEPDNS); - - Eventplaneinfo *epring_south = new Eventplaneinfov1(); - epring_south->set_ring_qvector(all_ring_Qvecs_south); - epmap->insert(epring_south, EventplaneinfoMap::sEPDRING_SOUTH); - - Eventplaneinfo *epring_north = new Eventplaneinfov1(); - epring_north->set_ring_qvector(all_ring_Qvecs_north); - epmap->insert(epring_north, EventplaneinfoMap::sEPDRING_NORTH); - - if (Verbosity() > 1) { - sepds->identify(); - sepdn->identify(); - sepdns->identify(); - epring_south->identify(); - epring_north->identify(); - } - } - } + if (!std::isfinite(m_cent) || m_cent < 0) + { + if (Verbosity() > 1) + { + std::cout << PHWHERE << " Warning Centrality is out of range. Cent: " << m_cent << ". Cannot calibrate Q vector for this event." << std::endl; } + m_doNotCalibEvent = true; } - if (_mbdEpReco) { - ResetMe(); + return Fun4AllReturnCodes::EVENT_OK; +} - MbdPmtContainer *mbdpmts = - findNode::getClass(topNode, "MbdPmtContainer"); - if (!mbdpmts) { - std::cout << PHWHERE << "::ERROR - cannot find MbdPmtContainer" - << std::endl; - exit(-1); - } +//____________________________________________________________________________.. +int EventPlaneReco::process_sEPD(PHCompositeNode* topNode) +{ + TowerInfoContainer* towerinfosEPD = findNode::getClass(topNode, m_inputNode); + if (!towerinfosEPD) + { + std::cout << PHWHERE << " TOWERINFO_CALIB_SEPD is missing doing nothing" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } - MbdGeom *mbdgeom = findNode::getClass(topNode, "MbdGeom"); - if (!mbdgeom) { - std::cout << PHWHERE << "::ERROR - cannot find MbdGeom" << std::endl; - exit(-1); - } + // sepd + const unsigned int nchannels_epd = towerinfosEPD->size(); + const unsigned int channel_limit = std::min(nchannels_epd, static_cast(SEPD_CHANNELS)); - if (mbdpmts) { - if (Verbosity()) { - std::cout << "EventPlaneReco::process_event - mbdpmts" << std::endl; - } + if (nchannels_epd != channel_limit && Verbosity() > 1) + { + std::cout << PHWHERE + << " Warning: sEPD channel count (" << nchannels_epd + << ") exceeds trig cache size (" << SEPD_CHANNELS + << "); truncating iteration." << std::endl; + } - for (int ipmt = 0; ipmt < mbdpmts->get_npmt(); ipmt++) { - float mbd_q = mbdpmts->get_pmt(ipmt)->get_q(); - _mbdQ += mbd_q; - } + double sepd_total_charge_south = 0; + double sepd_total_charge_north = 0; - for (int ipmt = 0; ipmt < mbdpmts->get_npmt(); ipmt++) { - float mbd_q = mbdpmts->get_pmt(ipmt)->get_q(); - float phi = mbdgeom->get_phi(ipmt); - int arm = mbdgeom->get_arm(ipmt); + for (unsigned int channel = 0; channel < channel_limit; ++channel) + { + TowerInfo* tower = towerinfosEPD->get_tower_at_channel(channel); - if (_mbdQ < _mbd_e) { - continue; - } + unsigned int key = TowerInfoDefs::encode_epd(channel); + double charge = tower->get_energy(); - if (arm == 0) { - for (unsigned int order = 0; order < m_MaxOrder; order++) { - double Cosine = cos(phi * (double)(order + 1)); - double Sine = sin(phi * (double)(order + 1)); - south_q[order][0] += mbd_q * Cosine; // south Qn,x - south_q[order][1] += mbd_q * Sine; // south Qn,y - } - } else if (arm == 1) { - for (unsigned int order = 0; order < m_MaxOrder; order++) { - double Cosine = cos(phi * (double)(order + 1)); - double Sine = sin(phi * (double)(order + 1)); - north_q[order][0] += mbd_q * Cosine; // north Qn,x - north_q[order][1] += mbd_q * Sine; // north Qn,y - } - } - } + // skip bad channels + // skip channels with very low charge + if (tower->get_isHot() || charge < m_sepd_min_channel_charge) + { + continue; } - for (unsigned int order = 0; order < m_MaxOrder; order++) { - south_Qvec.emplace_back(south_q[order][0], south_q[order][1]); - north_Qvec.emplace_back(north_q[order][0], north_q[order][1]); - } + // arm = 0: South + // arm = 1: North + unsigned int arm = TowerInfoDefs::get_epd_arm(key); - if (mbdpmts) { - Eventplaneinfo *mbds = new Eventplaneinfov1(); - mbds->set_qvector(south_Qvec); - epmap->insert(mbds, EventplaneinfoMap::MBDS); + // sepd charge sums + double& sepd_total_charge = (arm == 0) ? sepd_total_charge_south : sepd_total_charge_north; - Eventplaneinfo *mbdn = new Eventplaneinfov1(); - mbdn->set_qvector(north_Qvec); - epmap->insert(mbdn, EventplaneinfoMap::MBDN); + // Compute total charge for the respective sEPD arm + sepd_total_charge += charge; - if (Verbosity() > 1) { - mbds->identify(); - mbdn->identify(); - } + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + const auto& [cached_cos, cached_sin] = m_trig_cache[h_idx][channel]; + + m_Q_raw[h_idx][arm].x += charge * cached_cos; + m_Q_raw[h_idx][arm].y += charge * cached_sin; } + } - ResetMe(); + // ensure both total charges are nonzero + if (sepd_total_charge_south == 0 || sepd_total_charge_north == 0) + { + if (Verbosity() > 1) + { + std::cout << PHWHERE << " Error: Total sEPD Charge is Zero: " + << "South = " << sepd_total_charge_south + << ", North = " << sepd_total_charge_north << std::endl; + } + + // ensure raw Q vec is reset + m_Q_raw = {}; + m_doNotCalibEvent = true; + return Fun4AllReturnCodes::EVENT_OK; } - if (Verbosity()) { - epmap->identify(); + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + m_Q_raw[h_idx][0].x /= sepd_total_charge_south; + m_Q_raw[h_idx][0].y /= sepd_total_charge_south; + + m_Q_raw[h_idx][1].x /= sepd_total_charge_north; + m_Q_raw[h_idx][1].y /= sepd_total_charge_north; + + // NEW: Calculate Raw NS (Sum of Raw S + Raw N) + m_Q_raw[h_idx][2].x = m_Q_raw[h_idx][0].x + m_Q_raw[h_idx][1].x; + m_Q_raw[h_idx][2].y = m_Q_raw[h_idx][0].y + m_Q_raw[h_idx][1].y; } return Fun4AllReturnCodes::EVENT_OK; } -int EventPlaneReco::CreateNodes(PHCompositeNode *topNode) { - PHNodeIterator iter(topNode); +void EventPlaneReco::correct_QVecs() +{ + size_t cent_bin = static_cast(m_cent); + + // Skip calibration for out-of-range centrality + if (cent_bin >= m_cent_bins) + { + if (Verbosity() > 2) + { + std::cout << PHWHERE << " Warning: Centrality " << m_cent + << "% exceeds calibration range (0-" << m_cent_bins - 1 + << "). Using raw Q-vectors." << std::endl; + } - PHCompositeNode *dstNode = - dynamic_cast(iter.findFirst("PHCompositeNode", "DST")); - if (!dstNode) { - std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl; - return Fun4AllReturnCodes::ABORTRUN; + m_doNotCalibEvent = true; + return; } - PHCompositeNode *globalNode = dynamic_cast( - iter.findFirst("PHCompositeNode", "GLOBAL")); - if (!globalNode) { - globalNode = new PHCompositeNode("GLOBAL"); - dstNode->addNode(globalNode); - } + size_t south_idx = static_cast(Subdetector::S); + size_t north_idx = static_cast(Subdetector::N); + size_t ns_idx = static_cast(Subdetector::NS); - EventplaneinfoMap *eps = - findNode::getClass(topNode, "EventplaneinfoMap"); - if (!eps) { - eps = new EventplaneinfoMapv1(); - PHIODataNode *EpMapNode = - new PHIODataNode(eps, "EventplaneinfoMap", "PHObject"); - globalNode->addNode(EpMapNode); + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + auto& dataS = m_correction_data[h_idx][cent_bin][south_idx]; + auto& dataN = m_correction_data[h_idx][cent_bin][north_idx]; + auto& dataNS = m_correction_data[h_idx][cent_bin][ns_idx]; + + double Q_S_x_avg = dataS.avg_Q.x; + double Q_S_y_avg = dataS.avg_Q.y; + double Q_N_x_avg = dataN.avg_Q.x; + double Q_N_y_avg = dataN.avg_Q.y; + + QVec q_S = m_Q_raw[h_idx][south_idx]; + QVec q_N = m_Q_raw[h_idx][north_idx]; + + // Apply Recentering + QVec q_S_recenter = {q_S.x - Q_S_x_avg, q_S.y - Q_S_y_avg}; + QVec q_N_recenter = {q_N.x - Q_N_x_avg, q_N.y - Q_N_y_avg}; + QVec q_NS_recenter = {q_S_recenter.x + q_N_recenter.x, q_S_recenter.y + q_N_recenter.y}; + + m_Q_recentered[h_idx][south_idx] = q_S_recenter; + m_Q_recentered[h_idx][north_idx] = q_N_recenter; + m_Q_recentered[h_idx][ns_idx] = q_NS_recenter; + + // Flattening Matrix + const auto &X_S = dataS.X_matrix; + const auto &X_N = dataN.X_matrix; + const auto &X_NS = dataNS.X_matrix; + + // Apply Flattening + double Q_S_x_flat = X_S[0][0] * q_S_recenter.x + X_S[0][1] * q_S_recenter.y; + double Q_S_y_flat = X_S[1][0] * q_S_recenter.x + X_S[1][1] * q_S_recenter.y; + double Q_N_x_flat = X_N[0][0] * q_N_recenter.x + X_N[0][1] * q_N_recenter.y; + double Q_N_y_flat = X_N[1][0] * q_N_recenter.x + X_N[1][1] * q_N_recenter.y; + + double Q_NS_x_flat = X_NS[0][0] * q_NS_recenter.x + X_NS[0][1] * q_NS_recenter.y; + double Q_NS_y_flat = X_NS[1][0] * q_NS_recenter.x + X_NS[1][1] * q_NS_recenter.y; + + QVec q_S_flat = {Q_S_x_flat, Q_S_y_flat}; + QVec q_N_flat = {Q_N_x_flat, Q_N_y_flat}; + QVec q_NS_flat = {Q_NS_x_flat, Q_NS_y_flat}; + + m_Q_flat[h_idx][south_idx] = q_S_flat; + m_Q_flat[h_idx][north_idx] = q_N_flat; + m_Q_flat[h_idx][ns_idx] = q_NS_flat; } - return Fun4AllReturnCodes::EVENT_OK; } -void EventPlaneReco::ResetMe() { - for (auto &vec : south_q) { - std::fill(vec.begin(), vec.end(), 0.); - } +void EventPlaneReco::print_QVectors() +{ + std::string header_text = std::format("EVENT Q-VECTOR SUMMARY (Event: {}, CENTRALITY: {:.0f}%)", m_globalEvent, m_cent); + + std::cout << std::format("\n{:*>100}\n", ""); + std::cout << std::format("{:^100}\n", header_text); + std::cout << std::format("{:*>100}\n", ""); + + // Table Header + std::cout << std::format(" {:<10} {:<10} | {:>21} | {:>21} | {:>21}\n", + "Harmonic", "Detector", "Raw (x, y)", "Recentered (x, y)", "Flattened (x, y)"); + std::cout << std::format(" {:-<100}\n", ""); + + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + int n = m_harmonics[h_idx]; + + for (size_t det_idx = 0; det_idx < 3; ++det_idx) + { + std::string det_name; + if (det_idx == 0) + { + det_name = "South"; + } + else if (det_idx == 1) + { + det_name = "North"; + } + else + { + det_name = "NorthSouth"; + } - for (auto &vec : north_q) { - std::fill(vec.begin(), vec.end(), 0.); - } + const auto& raw = m_Q_raw[h_idx][det_idx]; + const auto& rec = m_Q_recentered[h_idx][det_idx]; + const auto& flat = m_Q_flat[h_idx][det_idx]; - for (auto &vec : northsouth_q) { - std::fill(vec.begin(), vec.end(), 0.); - } + std::string h_label = (det_idx == 0) ? std::format("n={}", n) : ""; + + // Groups x and y into (val, val) pairs for better scannability + std::string raw_str = std::format("({:>8.5f}, {:>8.5f})", raw.x, raw.y); + std::string rec_str = std::format("({:>8.5f}, {:>8.5f})", rec.x, rec.y); + std::string flat_str = std::format("({:>8.5f}, {:>8.5f})", flat.x, flat.y); - for (auto &order_vec : ring_q_north) { - for (auto &xy_vec : order_vec) { - std::fill(xy_vec.begin(), xy_vec.end(), 0.0); + std::cout << std::format(" {:<10} {:<10} | {:<21} | {:<21} | {:10}\n", + h_label, det_name, raw_str, rec_str, flat_str); + } + if (h_idx < m_harmonics.size() - 1) + { + std::cout << std::format(" {:.>100}\n", ""); } } + std::cout << std::format("{:*>100}\n\n", ""); +} - for (auto &order_vec : ring_q_south) { - for (auto &xy_vec : order_vec) { - std::fill(xy_vec.begin(), xy_vec.end(), 0.0); - } +int EventPlaneReco::FillNode(PHCompositeNode *topNode) +{ + EventplaneinfoMap *epmap = findNode::getClass(topNode, m_EventPlaneInfoNodeName); + if (!epmap) + { + std::cout << PHWHERE << " EventplaneinfoMap is missing doing nothing" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; } - south_Qvec.clear(); - north_Qvec.clear(); - northsouth_Qvec.clear(); + size_t vec_size = static_cast(*std::ranges::max_element(m_harmonics)); - for (auto &ring : all_ring_Qvecs_north) { - for (auto &q : ring) { - q = {0.0, 0.0}; - } + std::vector> south_Qvec_raw(vec_size, {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}); + std::vector> south_Qvec_recentered(vec_size, {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}); + std::vector> south_Qvec(vec_size, {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}); + + std::vector> north_Qvec_raw(vec_size, {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}); + std::vector> north_Qvec_recentered(vec_size, {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}); + std::vector> north_Qvec(vec_size, {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}); + + std::vector> northsouth_Qvec_raw(vec_size, {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}); + std::vector> northsouth_Qvec_recentered(vec_size, {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}); + std::vector> northsouth_Qvec(vec_size, {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}); + + for (size_t h_idx = 0; h_idx < m_harmonics.size(); ++h_idx) + { + int n = m_harmonics[h_idx]; + int idx = n - 1; + + // Fallback logic: Use raw if calibration failed or centrality is out of range + const auto& Q_S = (m_doNotCalib || m_doNotCalibEvent) ? m_Q_raw[h_idx][0] : m_Q_flat[h_idx][0]; + const auto& Q_N = (m_doNotCalib || m_doNotCalibEvent) ? m_Q_raw[h_idx][1] : m_Q_flat[h_idx][1]; + const auto& Q_NS = (m_doNotCalib || m_doNotCalibEvent) ? m_Q_raw[h_idx][2] : m_Q_flat[h_idx][2]; + + const auto& Q_S_raw = m_Q_raw[h_idx][0]; + const auto& Q_S_recentered = m_Q_recentered[h_idx][0]; + + const auto& Q_N_raw = m_Q_raw[h_idx][1]; + const auto& Q_N_recentered = m_Q_recentered[h_idx][1]; + + const auto& Q_NS_raw = m_Q_raw[h_idx][2]; + const auto& Q_NS_recentered = m_Q_recentered[h_idx][2]; + + // South + south_Qvec_raw[idx] = {Q_S_raw.x, Q_S_raw.y}; + south_Qvec_recentered[idx] = {Q_S_recentered.x, Q_S_recentered.y}; + south_Qvec[idx] = {Q_S.x, Q_S.y}; + + // North + north_Qvec_raw[idx] = {Q_N_raw.x, Q_N_raw.y}; + north_Qvec_recentered[idx] = {Q_N_recentered.x, Q_N_recentered.y}; + north_Qvec[idx] = {Q_N.x, Q_N.y}; + + // Combined (North + South) + northsouth_Qvec_raw[idx] = {Q_NS_raw.x, Q_NS_raw.y}; + northsouth_Qvec_recentered[idx] = {Q_NS_recentered.x, Q_NS_recentered.y}; + northsouth_Qvec[idx] = {Q_NS.x, Q_NS.y}; } - for (auto &ring : all_ring_Qvecs_south) { - for (auto &q : ring) { - q = {0.0, 0.0}; - } + // Helper lambda to fill nodes using the class's GetPsi method + auto create_and_fill = [&](const std::vector>& qvecs_raw, const std::vector>& qvecs_recentered, const std::vector>& qvecs) { + auto node = std::make_unique(); + node->set_qvector_raw(qvecs_raw); + node->set_qvector_recentered(qvecs_recentered); + node->set_qvector(qvecs); + + std::vector psi_vec(vec_size, std::numeric_limits::quiet_NaN()); + for (int n : m_harmonics) { + psi_vec[n-1] = node->GetPsi(qvecs[n-1].first, qvecs[n-1].second, n); + } + node->set_shifted_psi(psi_vec); + return node; + }; + + epmap->insert(create_and_fill(south_Qvec_raw, south_Qvec_recentered, south_Qvec).release(), EventplaneinfoMap::sEPDS); + epmap->insert(create_and_fill(north_Qvec_raw, north_Qvec_recentered, north_Qvec).release(), EventplaneinfoMap::sEPDN); + epmap->insert(create_and_fill(northsouth_Qvec_raw, northsouth_Qvec_recentered, northsouth_Qvec).release(), EventplaneinfoMap::sEPDNS); + + return Fun4AllReturnCodes::EVENT_OK; +} + +//____________________________________________________________________________.. +int EventPlaneReco::process_event(PHCompositeNode *topNode) +{ + EventHeader *eventInfo = findNode::getClass(topNode, "EventHeader"); + if (!eventInfo) + { + return Fun4AllReturnCodes::ABORTRUN; } - for (auto &vec : south_q_subtract) { - std::fill(vec.begin(), vec.end(), 0.); + m_globalEvent = eventInfo->get_EvtSequence(); + + int ret = process_centrality(topNode); + if (ret) + { + return ret; } - for (auto &vec : north_q_subtract) { - std::fill(vec.begin(), vec.end(), 0.); + ret = process_sEPD(topNode); + if (ret) + { + return ret; } - for (auto &vec : northsouth_q_subtract) { - std::fill(vec.begin(), vec.end(), 0.); + // Calibrate Q Vectors + if (!m_doNotCalib && !m_doNotCalibEvent) + { + correct_QVecs(); } - std::fill(shift_north.begin(), shift_north.end(), 0.); - std::fill(shift_south.begin(), shift_south.end(), 0.); - std::fill(shift_northsouth.begin(), shift_northsouth.end(), 0.); + ret = FillNode(topNode); + if (ret) + { + return ret; + } - std::fill(tmp_south_psi.begin(), tmp_south_psi.end(), NAN); - std::fill(tmp_north_psi.begin(), tmp_north_psi.end(), NAN); - std::fill(tmp_northsouth_psi.begin(), tmp_northsouth_psi.end(), NAN); + if (Verbosity() > 1) + { + print_QVectors(); + } - _nsum = 0.; - _ssum = 0.; - _do_ep = false; - _mbdQ = 0.; - _totalcharge = 0.; + return Fun4AllReturnCodes::EVENT_OK; } -int EventPlaneReco::End(PHCompositeNode * /*topNode*/) { +//____________________________________________________________________________.. +int EventPlaneReco::ResetEvent(PHCompositeNode */*topNode*/) +{ + m_doNotCalibEvent = false; + + m_Q_raw = {}; + m_Q_recentered = {}; + m_Q_flat = {}; - std::cout << " EventPlaneReco::End() " << std::endl; return Fun4AllReturnCodes::EVENT_OK; } diff --git a/offline/packages/eventplaneinfo/EventPlaneReco.h b/offline/packages/eventplaneinfo/EventPlaneReco.h index ce4259c95e..231d30a8bb 100644 --- a/offline/packages/eventplaneinfo/EventPlaneReco.h +++ b/offline/packages/eventplaneinfo/EventPlaneReco.h @@ -1,107 +1,150 @@ -// Tell emacs that this is a C++ source -// -*- C++ -*-. #ifndef EVENTPLANEINFO_EVENTPLANERECO_H #define EVENTPLANEINFO_EVENTPLANERECO_H -//=========================================================== -/// \author Ejiro Umaka -//=========================================================== - #include -#include // for string -#include // for vector -class TProfile2D; -class TH1; +#include +#include +#include +class CDBTTree; class PHCompositeNode; -class EventPlaneReco : public SubsysReco { -public: - EventPlaneReco(const std::string &name = "EventPlaneReco"); +class EventPlaneReco : public SubsysReco +{ + public: + + explicit EventPlaneReco(const std::string &name = "EventPlaneReco"); ~EventPlaneReco() override = default; + + // Explicitly disable copying and moving + EventPlaneReco(const EventPlaneReco&) = delete; + EventPlaneReco& operator=(const EventPlaneReco&) = delete; + EventPlaneReco(EventPlaneReco&&) = delete; + EventPlaneReco& operator=(EventPlaneReco&&) = delete; + + /** Called during initialization. + Typically this is where you can book histograms, and e.g. + register them to Fun4AllServer (so they can be output to file + using Fun4AllServer::dumpHistos() method). + */ + int Init(PHCompositeNode *topNode) override; + + /** Called during initialization. + * geometry is available + */ int InitRun(PHCompositeNode *topNode) override; + + /** Called for each event. + This is where you do the real work. + */ int process_event(PHCompositeNode *topNode) override; - int End(PHCompositeNode * /*topNode*/) override; - - void ResetMe(); - void set_sepd_epreco(bool sepdEpReco) { _sepdEpReco = sepdEpReco; } - void set_mbd_epreco(bool mbdEpReco) { _mbdEpReco = mbdEpReco; } - void set_isSim(bool isSim) { _isSim = isSim; } - void set_sEPD_Mip_cut(const float e) { _epd_e = e; } - void set_sEPD_Charge_cut(const float c) { _epd_charge_min = c; } - void set_MBD_Min_Qcut(const float f) { _mbd_e = f; } - void set_MBD_Vertex_cut(const float v) { _mbd_vertex_cut = v; } - void set_Ep_orders(const unsigned int n) { m_MaxOrder = n; } - -private: - int CreateNodes(PHCompositeNode *topNode); - unsigned int m_MaxOrder{3}; - static const int nRings {16}; - - std::string FileName; - - std::vector> south_q; - std::vector> north_q; - std::vector> northsouth_q; - std::vector>> ring_q_north; - std::vector>> ring_q_south; - std::vector> south_Qvec; - std::vector> north_Qvec; - std::vector> northsouth_Qvec; - std::vector>> all_ring_Qvecs_north; - std::vector>> all_ring_Qvecs_south; - - // const int phibins{24}; - TH1* h_phi_weight_south_input{nullptr}; - TH1* h_phi_weight_north_input{nullptr}; - - // recentering utility - std::vector> south_q_subtract; - std::vector> north_q_subtract; - std::vector> northsouth_q_subtract; - - // shifting utility - std::vector shift_north; - std::vector shift_south; - std::vector shift_northsouth; - std::vector tmp_south_psi; - std::vector tmp_north_psi; - std::vector tmp_northsouth_psi; - - // recentering histograms - TProfile2D *tprof_mean_cos_north_epd_input[6]{}; - TProfile2D *tprof_mean_sin_north_epd_input[6]{}; - TProfile2D *tprof_mean_cos_south_epd_input[6]{}; - TProfile2D *tprof_mean_sin_south_epd_input[6]{}; - TProfile2D *tprof_mean_cos_northsouth_epd_input[6]{}; - TProfile2D *tprof_mean_sin_northsouth_epd_input[6]{}; - - // shifting histograms - const int _imax{12}; - TProfile2D *tprof_cos_north_epd_shift_input[6][12]{}; - TProfile2D *tprof_sin_north_epd_shift_input[6][12]{}; - TProfile2D *tprof_cos_south_epd_shift_input[6][12]{}; - TProfile2D *tprof_sin_south_epd_shift_input[6][12]{}; - TProfile2D *tprof_cos_northsouth_epd_shift_input[6][12]{}; - TProfile2D *tprof_sin_northsouth_epd_shift_input[6][12]{}; - - bool _mbdEpReco{false}; - bool _sepdEpReco{false}; - bool _isSim{false}; - bool _do_ep{false}; - - float _nsum{0.0}; - float _ssum{0.0}; - float _mbdvtx{999.0}; - float _epd_charge_min{5.0}; - float _epd_charge_max{10000.0}; - float _epd_e{10.0}; - float _mbd_e{10.0}; - float _mbdQ{0.0}; - double _totalcharge{0.0}; - float _mbd_vertex_cut{60.0}; -}; -#endif // EVENTPLANEINFO_EVENTPLANERECO_H + /// Clean up internals after each event. + int ResetEvent(PHCompositeNode *topNode) override; + + + void set_inputNode(const std::string &inputNode) + { + m_inputNode = inputNode; + } + + void set_directURL_EventPlaneCalib(const std::string &directURL_EventPlaneCalib) + { + m_directURL_EventPlaneCalib = directURL_EventPlaneCalib; + } + + void set_doAbortNoEventPlaneCalib(bool status = true) + { + m_doAbortNoEventPlaneCalib = status; + } + + void set_sepd_min_channel_charge(double sepd_min_channel_charge) + { + m_sepd_min_channel_charge = sepd_min_channel_charge; + } + + void set_EventPlaneInfoNodeName(const std::string &name) + { + m_EventPlaneInfoNodeName = name; + } + + private: + + int CreateNodes(PHCompositeNode *topNode); + + std::array, 2> calculate_flattening_matrix(double xx, double yy, double xy, int n, int cent_bin, const std::string& det_label); + void LoadCalib(); + + void print_correction_data(); + void print_QVectors(); + + int process_centrality(PHCompositeNode *topNode); + int process_sEPD(PHCompositeNode *topNode); + void correct_QVecs(); + + int FillNode(PHCompositeNode *topNode); + + std::string m_directURL_EventPlaneCalib; + bool m_doAbortNoEventPlaneCalib{false}; + bool m_doNotCalib{false}; + bool m_doNotCalibEvent{false}; + + double m_cent{0.0}; + double m_globalEvent{0}; + double m_sepd_min_channel_charge{0.2}; + + std::string m_calibName{"SEPD_EventPlaneCalib"}; + std::string m_inputNode{"TOWERINFO_CALIB_SEPD"}; + std::string m_EventPlaneInfoNodeName{"EventplaneinfoMap"}; + + CDBTTree *m_cdbttree {nullptr}; + + enum class Subdetector + { + S, + N, + NS + }; + + struct QVec + { + double x{0.0}; + double y{0.0}; + }; + + struct CorrectionData + { + // Averages of Qx, Qy, Qx^2, Qy^2, Qxy + QVec avg_Q{}; + double avg_Q_xx{0.0}; + double avg_Q_yy{0.0}; + double avg_Q_xy{0.0}; + + // Correction matrix + std::array, 2> X_matrix{}; + }; + + static constexpr size_t m_cent_bins {80}; + static constexpr std::array m_harmonics = {2, 3, 4}; + + // Holds all correction data + // key: [Harmonic][Cent][Subdetector] + // Harmonics {2,3,4} -> 3 elements + // Subdetectors {S,N,NS} -> 3 elements + std::array, m_cent_bins>, m_harmonics.size()> m_correction_data; + + // sEPD Q Vectors + // key: [Harmonic][Subdetector] + // Subdetectors {S,N,NS} -> 3 elements + std::array, m_harmonics.size()> m_Q_raw{}; + std::array, m_harmonics.size()> m_Q_recentered{}; + std::array, m_harmonics.size()> m_Q_flat{}; + + // [Harmonic Index][Channel Index] -> {cos, sin} + std::vector>> m_trig_cache; + + static constexpr int SEPD_CHANNELS = 744; +}; +#endif diff --git a/offline/packages/eventplaneinfo/Eventplaneinfo.h b/offline/packages/eventplaneinfo/Eventplaneinfo.h index 1ad2665881..04b085a393 100644 --- a/offline/packages/eventplaneinfo/Eventplaneinfo.h +++ b/offline/packages/eventplaneinfo/Eventplaneinfo.h @@ -1,19 +1,19 @@ // Tell emacs that this is a C++ source // -*- C++ -*-. -#ifndef EVENTPLANEINFO_H -#define EVENTPLANEINFO_H +#ifndef EVENTPLANEINFO_EVENTPLANEINFO_H +#define EVENTPLANEINFO_EVENTPLANEINFO_H #include -#include #include +#include #include #include class Eventplaneinfo : public PHObject { public: - ~Eventplaneinfo() override {} + ~Eventplaneinfo() override = default; void identify(std::ostream& os = std::cout) const override { @@ -22,18 +22,29 @@ class Eventplaneinfo : public PHObject PHObject* CloneMe() const override { return nullptr; } - virtual void set_qvector(std::vector> /*Qvec*/) { return; } - virtual void set_shifted_psi(std::vector /*Psi_Shifted*/) { return; } - virtual std::pair get_qvector(int /*order*/) const { return std::make_pair(NAN, NAN); } - virtual double get_psi(int /*order*/) const { return NAN; } - virtual double get_shifted_psi(int /*order*/) const { return NAN; } - virtual double GetPsi(const double /*Qx*/, const double /*Qy*/, const unsigned int /*order*/) const { return NAN; } - virtual void set_ring_qvector(std::vector>> /*RingQvecs*/) { return; } - virtual std::pair get_ring_qvector(int /*rbin*/, int /*order*/) const { return std::make_pair(NAN, NAN); } - virtual double get_ring_psi(int /*rbin*/, int /*order*/) const { return NAN; } + virtual void set_qvector(const std::vector>& /*Qvec*/) { return; } + virtual void set_qvector_raw(const std::vector>& /*Qvec*/) { return; } + virtual void set_qvector_recentered(const std::vector>& /*Qvec*/) { return; } + virtual void set_shifted_psi(const std::vector& /*Psi_Shifted*/) { return; } + virtual std::pair get_qvector(unsigned int /*order*/) const { return std::make_pair(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()); } + virtual std::pair get_qvector_raw(unsigned int /*order*/) const { return std::make_pair(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()); } + virtual std::pair get_qvector_recentered(unsigned int /*order*/) const { return std::make_pair(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()); } + virtual double get_psi(unsigned int /*order*/) const { return std::numeric_limits::quiet_NaN(); } + virtual double get_shifted_psi(unsigned int /*order*/) const { return std::numeric_limits::quiet_NaN(); } + virtual double GetPsi(const double /*Qx*/, const double /*Qy*/, const unsigned int /*order*/) const { return std::numeric_limits::quiet_NaN(); } + virtual void set_ring_qvector(const std::vector>>& /*RingQvecs*/) { return; } + virtual std::pair get_ring_qvector(int /*rbin*/, unsigned int /*order*/) const { return std::make_pair(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()); } + virtual double get_ring_psi(int /*rbin*/, unsigned int /*order*/) const { return std::numeric_limits::quiet_NaN(); } protected: - Eventplaneinfo() {} + Eventplaneinfo() = default; + + // Rule of Five: Protected allows derived classes to copy/move, + // but prevents "slicing" at the base class level. + Eventplaneinfo(const Eventplaneinfo&) = default; + Eventplaneinfo& operator=(const Eventplaneinfo&) = default; + Eventplaneinfo(Eventplaneinfo&&) = default; + Eventplaneinfo& operator=(Eventplaneinfo&&) = default; private: ClassDefOverride(Eventplaneinfo, 1); diff --git a/offline/packages/eventplaneinfo/EventplaneinfoMap.h b/offline/packages/eventplaneinfo/EventplaneinfoMap.h index 247a62a1f6..ee16720cff 100644 --- a/offline/packages/eventplaneinfo/EventplaneinfoMap.h +++ b/offline/packages/eventplaneinfo/EventplaneinfoMap.h @@ -25,10 +25,10 @@ class EventplaneinfoMap : public PHObject sEPDRING_NORTH = 200 }; - typedef std::map::const_iterator ConstIter; - typedef std::map::iterator Iter; + using ConstIter = std::map::const_iterator; + using Iter = std::map::iterator; - ~EventplaneinfoMap() override {} + ~EventplaneinfoMap() override = default; void identify(std::ostream& os = std::cout) const override { os << "EventplaneinfoMap base class" << std::endl; } virtual bool empty() const {return true;} @@ -47,7 +47,13 @@ class EventplaneinfoMap : public PHObject virtual Iter end(); protected: - EventplaneinfoMap() {} + EventplaneinfoMap() = default; + + // Rule of Five: Protected to support derived classes + EventplaneinfoMap(const EventplaneinfoMap&) = default; + EventplaneinfoMap& operator=(const EventplaneinfoMap&) = default; + EventplaneinfoMap(EventplaneinfoMap&&) = default; + EventplaneinfoMap& operator=(EventplaneinfoMap&&) = default; private: ClassDefOverride(EventplaneinfoMap, 1); diff --git a/offline/packages/eventplaneinfo/EventplaneinfoMapv1.cc b/offline/packages/eventplaneinfo/EventplaneinfoMapv1.cc index a0888d4d18..4aeffdd8c9 100644 --- a/offline/packages/eventplaneinfo/EventplaneinfoMapv1.cc +++ b/offline/packages/eventplaneinfo/EventplaneinfoMapv1.cc @@ -3,7 +3,6 @@ #include "Eventplaneinfo.h" #include "EventplaneinfoMap.h" -#include // for reverse_iterator #include // for pair, make_pair EventplaneinfoMapv1::~EventplaneinfoMapv1() diff --git a/offline/packages/eventplaneinfo/EventplaneinfoMapv1.h b/offline/packages/eventplaneinfo/EventplaneinfoMapv1.h index 5aac01a4ce..b4f10f3bed 100644 --- a/offline/packages/eventplaneinfo/EventplaneinfoMapv1.h +++ b/offline/packages/eventplaneinfo/EventplaneinfoMapv1.h @@ -16,6 +16,12 @@ class EventplaneinfoMapv1 : public EventplaneinfoMap EventplaneinfoMapv1() = default; ~EventplaneinfoMapv1() override; + // Rule of Five: Explicitly delete to prevent shallow copy/double free + EventplaneinfoMapv1(const EventplaneinfoMapv1&) = delete; + EventplaneinfoMapv1& operator=(const EventplaneinfoMapv1&) = delete; + EventplaneinfoMapv1(EventplaneinfoMapv1&&) = delete; + EventplaneinfoMapv1& operator=(EventplaneinfoMapv1&&) = delete; + void identify(std::ostream& os = std::cout) const override; void Reset() override { clear(); } // cppcheck-suppress [virtualCallInConstructor] diff --git a/offline/packages/eventplaneinfo/Eventplaneinfov1.h b/offline/packages/eventplaneinfo/Eventplaneinfov1.h index 571997b63b..2b027323ea 100644 --- a/offline/packages/eventplaneinfo/Eventplaneinfov1.h +++ b/offline/packages/eventplaneinfo/Eventplaneinfov1.h @@ -11,27 +11,30 @@ #include // for pair, make_pair #include -class PHObject; - class Eventplaneinfov1 : public Eventplaneinfo { public: Eventplaneinfov1() = default; ~Eventplaneinfov1() override = default; + Eventplaneinfov1(const Eventplaneinfov1&) = default; + Eventplaneinfov1& operator=(const Eventplaneinfov1&) = default; + Eventplaneinfov1(Eventplaneinfov1&&) = default; + Eventplaneinfov1& operator=(Eventplaneinfov1&&) = default; + void identify(std::ostream& os = std::cout) const override; void Reset() override { *this = Eventplaneinfov1(); } PHObject* CloneMe() const override { return new Eventplaneinfov1(*this); } - void set_qvector(std::vector> Qvec) override { mQvec = Qvec; } - void set_shifted_psi(std::vector Psi_Shifted) override { mPsi_Shifted = Psi_Shifted; } - std::pair get_qvector(int order) const override { return std::make_pair(mQvec[order - 1].first, mQvec[order - 1].second); } - void set_ring_qvector(std::vector>> Qvec) override { ring_Qvec = Qvec; } - std::pair get_ring_qvector(int ring_index, int order) const override { return ring_Qvec[ring_index][order - 1]; } - double get_ring_psi(int ring_index, int order) const override {return GetPsi(ring_Qvec[ring_index][order - 1].first,ring_Qvec[ring_index][order - 1].second,order);} - double GetPsi(const double Qx, const double Qy, const unsigned int order) const override; - double get_psi(int order) const override { return GetPsi(mQvec[order - 1].first, mQvec[order - 1].second, order);} - double get_shifted_psi(int order) const override { return mPsi_Shifted[order - 1]; } + void set_qvector(const std::vector>& Qvec) override { mQvec = Qvec; } + void set_shifted_psi(const std::vector& Psi_Shifted) override { mPsi_Shifted = Psi_Shifted; } + std::pair get_qvector(unsigned int order) const override { return std::make_pair(mQvec[order - 1].first, mQvec[order - 1].second); } + void set_ring_qvector(const std::vector>>& Qvec) override { ring_Qvec = Qvec; } + std::pair get_ring_qvector(int ring_index, unsigned int order) const override { return ring_Qvec[ring_index][order - 1]; } + double get_ring_psi(int ring_index, unsigned int order) const override {return GetPsi(ring_Qvec[ring_index][order - 1].first,ring_Qvec[ring_index][order - 1].second,order);} + double GetPsi(double Qx, double Qy, unsigned int order) const override; + double get_psi(unsigned int order) const override { return GetPsi(mQvec[order - 1].first, mQvec[order - 1].second, order);} + double get_shifted_psi(unsigned int order) const override { return mPsi_Shifted[order - 1]; } private: std::vector> mQvec; diff --git a/offline/packages/eventplaneinfo/Eventplaneinfov2.cc b/offline/packages/eventplaneinfo/Eventplaneinfov2.cc new file mode 100644 index 0000000000..7331117a17 --- /dev/null +++ b/offline/packages/eventplaneinfo/Eventplaneinfov2.cc @@ -0,0 +1,23 @@ +#include "Eventplaneinfov2.h" + +#include +#include + +void Eventplaneinfov2::identify(std::ostream& os) const +{ + os << "---------Eventplaneinfov2------------------" << std::endl; + return; +} + +double Eventplaneinfov2::GetPsi(const double Qx, const double Qy, const unsigned int order) const +{ + if (order == 0) + { + return std::numeric_limits::quiet_NaN(); + } + if ((Qx == 0.0) && (Qy == 0.0)) + { + return std::numeric_limits::quiet_NaN(); + } + return std::atan2(Qy, Qx) / order; +} diff --git a/offline/packages/eventplaneinfo/Eventplaneinfov2.h b/offline/packages/eventplaneinfo/Eventplaneinfov2.h new file mode 100644 index 0000000000..5ad62fe979 --- /dev/null +++ b/offline/packages/eventplaneinfo/Eventplaneinfov2.h @@ -0,0 +1,86 @@ +// Tell emacs that this is a C++ source +// -*- C++ -*-. +#ifndef EVENTPLANEINFO_EVENTPLANEINFOV2_H +#define EVENTPLANEINFO_EVENTPLANEINFOV2_H + +#include "Eventplaneinfo.h" + +#include // for size_t +#include +#include +#include // for pair, make_pair +#include + +class PHObject; + +class Eventplaneinfov2 : public Eventplaneinfo +{ + public: + Eventplaneinfov2() = default; + ~Eventplaneinfov2() override = default; + + Eventplaneinfov2(const Eventplaneinfov2&) = default; + Eventplaneinfov2& operator=(const Eventplaneinfov2&) = default; + Eventplaneinfov2(Eventplaneinfov2&&) = default; + Eventplaneinfov2& operator=(Eventplaneinfov2&&) = default; + + void identify(std::ostream& os = std::cout) const override; + void Reset() override { *this = Eventplaneinfov2(); } + PHObject* CloneMe() const override { return new Eventplaneinfov2(*this); } + + void set_qvector(const std::vector>& Qvec) override { mQvec = Qvec; } + void set_qvector_raw(const std::vector>& Qvec) override { mQvec_raw = Qvec; } + void set_qvector_recentered(const std::vector>& Qvec) override { mQvec_recentered = Qvec; } + void set_shifted_psi(const std::vector& Psi_Shifted) override { mPsi_Shifted = Psi_Shifted; } + std::pair get_qvector(unsigned int order) const override { return safe_qvec(mQvec, order); } + std::pair get_qvector_raw(unsigned int order) const override { return safe_qvec(mQvec_raw, order); } + std::pair get_qvector_recentered(unsigned int order) const override { return safe_qvec(mQvec_recentered, order); } + void set_ring_qvector(const std::vector>>& Qvec) override { ring_Qvec = Qvec; } + std::pair get_ring_qvector(int ring_index, unsigned int order) const override + { + if (ring_index < 0 || static_cast(ring_index) >= ring_Qvec.size()) + { + return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; + } + return safe_qvec(ring_Qvec[ring_index], order); + } + double get_ring_psi(int ring_index, unsigned int order) const override + { + auto q = get_ring_qvector(ring_index, order); + return GetPsi(q.first, q.second, order); + } + + double GetPsi(double Qx, double Qy, unsigned int order) const override; + double get_psi(unsigned int order) const override + { + auto q = get_qvector(order); + return GetPsi(q.first, q.second, order); + } + double get_shifted_psi(unsigned int order) const override + { + if (order <= 0 || order > mPsi_Shifted.size()) + { + return std::numeric_limits::quiet_NaN(); + } + return mPsi_Shifted[order - 1]; + } + + private: + static std::pair safe_qvec(const std::vector>& v, unsigned int order) + { + if (order <= 0 || order > v.size()) + { + return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; + } + return v[order - 1]; + } + + std::vector> mQvec; + std::vector> mQvec_raw; + std::vector> mQvec_recentered; + std::vector mPsi_Shifted; + std::vector>> ring_Qvec; + ClassDefOverride(Eventplaneinfov2, 1); +}; + +#endif diff --git a/offline/packages/eventplaneinfo/Eventplaneinfov2LinkDef.h b/offline/packages/eventplaneinfo/Eventplaneinfov2LinkDef.h new file mode 100644 index 0000000000..961c0446cf --- /dev/null +++ b/offline/packages/eventplaneinfo/Eventplaneinfov2LinkDef.h @@ -0,0 +1,5 @@ +#ifdef __CINT__ + +#pragma link C++ class Eventplaneinfov2 + ; + +#endif /* __CINT__ */ diff --git a/offline/packages/eventplaneinfo/Makefile.am b/offline/packages/eventplaneinfo/Makefile.am index 3a1192095d..188447cd06 100644 --- a/offline/packages/eventplaneinfo/Makefile.am +++ b/offline/packages/eventplaneinfo/Makefile.am @@ -14,8 +14,7 @@ AM_LDFLAGS = \ -L$(OFFLINE_MAIN)/lib libeventplaneinfo_io_la_LIBADD = \ - -lphool \ - -lcentrality_io + -lphool libeventplaneinfo_la_LIBADD = \ libeventplaneinfo_io.la \ @@ -24,14 +23,15 @@ libeventplaneinfo_la_LIBADD = \ -lfun4all \ -lffamodules \ -lcalotrigger_io \ + -lcentrality_io \ -lffarawobjects \ -lcdbobjects \ -lglobalvertex_io pkginclude_HEADERS = \ - EventPlaneCalibration.h \ Eventplaneinfo.h \ Eventplaneinfov1.h \ + Eventplaneinfov2.h \ EventplaneinfoMap.h \ EventplaneinfoMapv1.h \ EventPlaneReco.h @@ -39,6 +39,7 @@ pkginclude_HEADERS = \ ROOTDICTS = \ Eventplaneinfo_Dict.cc \ Eventplaneinfov1_Dict.cc \ + Eventplaneinfov2_Dict.cc \ EventplaneinfoMap_Dict.cc \ EventplaneinfoMapv1_Dict.cc @@ -50,11 +51,11 @@ libeventplaneinfo_io_la_SOURCES = \ $(ROOTDICTS) \ Eventplaneinfo.cc \ Eventplaneinfov1.cc \ + Eventplaneinfov2.cc \ EventplaneinfoMap.cc \ EventplaneinfoMapv1.cc libeventplaneinfo_la_SOURCES = \ - EventPlaneCalibration.cc \ EventPlaneReco.cc # Rule for generating table CINT dictionaries. diff --git a/offline/packages/globalvertex/GlobalVertex.h b/offline/packages/globalvertex/GlobalVertex.h index 2a42abbba6..3124cea282 100644 --- a/offline/packages/globalvertex/GlobalVertex.h +++ b/offline/packages/globalvertex/GlobalVertex.h @@ -78,8 +78,8 @@ class GlobalVertex : public PHObject virtual float get_error(unsigned int /*i*/, unsigned int /*j*/) const { return std::numeric_limits::quiet_NaN(); } virtual void set_error(unsigned int /*i*/, unsigned int /*j*/, float /*value*/) { return; } - virtual unsigned int get_beam_crossing() const { return std::numeric_limits::max(); } - virtual void set_beam_crossing(unsigned int) { return; } + virtual short int get_beam_crossing() const { return std::numeric_limits::max(); } + virtual void set_beam_crossing(short int) { return; } virtual bool empty_vtxs() const { return true; } virtual size_t size_vtxs() const { return 0; } diff --git a/offline/packages/globalvertex/GlobalVertexReco.cc b/offline/packages/globalvertex/GlobalVertexReco.cc index 4f50bbc1b6..73681759cc 100644 --- a/offline/packages/globalvertex/GlobalVertexReco.cc +++ b/offline/packages/globalvertex/GlobalVertexReco.cc @@ -3,7 +3,7 @@ //#include "GlobalVertex.h" // for GlobalVertex, GlobalVe... #include "GlobalVertexMap.h" // for GlobalVertexMap #include "GlobalVertexMapv1.h" -#include "GlobalVertexv2.h" +#include "GlobalVertexv3.h" #include "MbdVertex.h" #include "MbdVertexMap.h" #include "CaloVertex.h" @@ -140,7 +140,7 @@ int GlobalVertexReco::process_event(PHCompositeNode *topNode) } // we have a matching pair - GlobalVertex *vertex = new GlobalVertexv2(); + GlobalVertex *vertex = new GlobalVertexv3(); vertex->set_id(globalmap->size()); vertex->clone_insert_vtx(GlobalVertex::SVTX, svtx); @@ -193,7 +193,7 @@ int GlobalVertexReco::process_event(PHCompositeNode *topNode) } // we have a standalone SVTX vertex - GlobalVertex *vertex = new GlobalVertexv2(); + GlobalVertex *vertex = new GlobalVertexv3(); vertex->set_id(globalmap->size()); @@ -243,7 +243,7 @@ int GlobalVertexReco::process_event(PHCompositeNode *topNode) continue; } - GlobalVertex *vertex = new GlobalVertexv2(); + GlobalVertex *vertex = new GlobalVertexv3(); vertex->set_id(globalmap->size()); vertex->clone_insert_vtx(GlobalVertex::MBD, mbd); @@ -282,7 +282,7 @@ int GlobalVertexReco::process_event(PHCompositeNode *topNode) continue; } - GlobalVertex *vertex = new GlobalVertexv2(); + GlobalVertex *vertex = new GlobalVertexv3(); vertex->set_id(globalmap->size()); vertex->clone_insert_vtx(GlobalVertex::CALO, calo); @@ -337,7 +337,7 @@ int GlobalVertexReco::process_event(PHCompositeNode *topNode) continue; } - GlobalVertex *vertex = new GlobalVertexv2(); + GlobalVertex *vertex = new GlobalVertexv3(); vertex->set_id(globalmap->size()); vertex->clone_insert_vtx(GlobalVertex::CALO, calo); @@ -354,7 +354,7 @@ int GlobalVertexReco::process_event(PHCompositeNode *topNode) } else { - GlobalVertex *vertex = new GlobalVertexv2(); + GlobalVertex *vertex = new GlobalVertexv3(); vertex->set_id(globalmap->size()); vertex->clone_insert_vtx(GlobalVertex::MBD, mbd); @@ -393,7 +393,7 @@ int GlobalVertexReco::process_event(PHCompositeNode *topNode) tvertex->set_t(0); tvertex->set_t_err(0); // 0.1 - GlobalVertex *vertex = new GlobalVertexv2(); + GlobalVertex *vertex = new GlobalVertexv3(); vertex->clone_insert_vtx(GlobalVertex::TRUTH, tvertex); globalmap->insert(vertex); if (truthmap) diff --git a/offline/packages/globalvertex/GlobalVertexv2.h b/offline/packages/globalvertex/GlobalVertexv2.h index 06a4d637f0..4c7a077df7 100644 --- a/offline/packages/globalvertex/GlobalVertexv2.h +++ b/offline/packages/globalvertex/GlobalVertexv2.h @@ -29,8 +29,22 @@ class GlobalVertexv2 : public GlobalVertex unsigned int get_id() const override { return _id; } void set_id(unsigned int id) override { _id = id; } - unsigned int get_beam_crossing() const override { return _bco; } - void set_beam_crossing(unsigned int bco) override { _bco = bco; } + short int get_beam_crossing() const override + { + return rollover_from_unsignedint(_bco); + } + + void set_beam_crossing(short int bco) override + { + if (bco == short_int_max) + { + _bco = std::numeric_limits::max(); + return; + } + + const short int bco_ro = rollover_short(bco); + _bco = static_cast(bco_ro); + } float get_t() const override; float get_t_err() const override; @@ -65,6 +79,25 @@ class GlobalVertexv2 : public GlobalVertex GlobalVertex::VertexIter end_vertexes() override { return _vtxs.end(); } private: + static constexpr short int short_int_max = std::numeric_limits::max(); + + static short int rollover_short(short int bco) + { + if (bco == short_int_max) return short_int_max; + if (bco >= 0) return bco; + return static_cast(static_cast(short_int_max) + static_cast(bco)); + } + + static short int rollover_from_unsignedint(unsigned int bco) + { + if (bco == std::numeric_limits::max()) return short_int_max; + if (bco <= static_cast(short_int_max)) return static_cast(bco); + + const short int bco_ro = static_cast(static_cast(bco)); + if (bco_ro >= 0) return bco_ro; + return rollover_short(bco_ro); + } + unsigned int _id{std::numeric_limits::max()}; unsigned int _bco{std::numeric_limits::max()}; //< global bco std::map _vtxs; //< list of vtxs diff --git a/offline/packages/globalvertex/GlobalVertexv3.cc b/offline/packages/globalvertex/GlobalVertexv3.cc new file mode 100644 index 0000000000..4eca34c62c --- /dev/null +++ b/offline/packages/globalvertex/GlobalVertexv3.cc @@ -0,0 +1,236 @@ +#include "GlobalVertexv3.h" + +#include + +GlobalVertexv3::GlobalVertexv3(const unsigned int id) + : _id(id) +{ +} + +GlobalVertexv3::~GlobalVertexv3() +{ + GlobalVertexv3::Reset(); +} + +void GlobalVertexv3::Reset() +{ + for (auto& _vtx : _vtxs) + { + for (const auto* vertex : _vtx.second) + { + delete vertex; + } + } + _vtxs.clear(); +} + +void GlobalVertexv3::identify(std::ostream& os) const +{ + os << "---GlobalVertexv3-----------------------" << std::endl; + + os << " list of vtx ids: " << std::endl; + for (ConstVertexIter iter = begin_vertexes(); iter != end_vertexes(); ++iter) + { + os << " Vertex type " << iter->first << " has " << iter->second.size() + << " vertices associated to it" << std::endl; + for (const auto& vertex : iter->second) + { + vertex->identify(); + } + } + + os << "-----------------------------------------------" << std::endl; +} + +int GlobalVertexv3::isValid() const +{ + if (_vtxs.empty()) + { + return 0; + } + return 1; +} + +void GlobalVertexv3::insert_vtx(GlobalVertex::VTXTYPE type, const Vertex* vertex) +{ + auto it = _vtxs.find(type); + if (it == _vtxs.end()) + { + VertexVector vector; + vector.push_back(vertex); + _vtxs.insert(std::make_pair(type, vector)); + return; + } + + it->second.push_back(vertex); +} + +void GlobalVertexv3::clone_insert_vtx(GlobalVertex::VTXTYPE type, const Vertex* vertex) +{ + auto it = _vtxs.find(type); + Vertex* clone = dynamic_cast(vertex->CloneMe()); + if (it == _vtxs.end()) + { + VertexVector vector; + vector.push_back(clone); + _vtxs.insert(std::make_pair(type, vector)); + return; + } + + it->second.push_back(clone); +} + +size_t GlobalVertexv3::count_vtxs(GlobalVertex::VTXTYPE type) const +{ + auto it = _vtxs.find(type); + if (it == _vtxs.end()) + { + return 0; + } + + return it->second.size(); +} + +float GlobalVertexv3::get_t() const +{ + auto it = _vtxs.find(GlobalVertex::VTXTYPE::MBD); + if (it == _vtxs.end()) + { + return std::numeric_limits::quiet_NaN(); + } + + return it->second[0]->get_t(); +} + +float GlobalVertexv3::get_t_err() const +{ + auto it = _vtxs.find(GlobalVertex::VTXTYPE::MBD); + if (it == _vtxs.end()) + { + return std::numeric_limits::quiet_NaN(); + } + + return it->second[0]->get_t_err(); +} + +float GlobalVertexv3::get_x() const { return get_position(0); } +float GlobalVertexv3::get_y() const { return get_position(1); } +float GlobalVertexv3::get_z() const { return get_position(2); } + +float GlobalVertexv3::get_position(unsigned int coor) const +{ + auto svtxit = _vtxs.find(GlobalVertex::VTXTYPE::SVTX); + if (svtxit == _vtxs.end()) + { + auto mbdit = _vtxs.find(GlobalVertex::VTXTYPE::MBD); + if (mbdit == _vtxs.end()) + { + auto caloit = _vtxs.find(GlobalVertex::VTXTYPE::CALO); + if (caloit == _vtxs.end()) + { + auto truthit = _vtxs.find(GlobalVertex::VTXTYPE::TRUTH); + if (truthit == _vtxs.end()) + { + return std::numeric_limits::quiet_NaN(); + } + return truthit->second[0]->get_position(coor); + } + return caloit->second[0]->get_position(coor); + } + return mbdit->second[0]->get_position(coor); + } + + GlobalVertex::VertexVector trackvertices = svtxit->second; + size_t mosttracks = 0; + float pos = std::numeric_limits::quiet_NaN(); + for (const auto* vertex : trackvertices) + { + if (vertex->size_tracks() > mosttracks) + { + mosttracks = vertex->size_tracks(); + pos = vertex->get_position(coor); + } + } + + return pos; +} + +float GlobalVertexv3::get_chisq() const +{ + auto svtxit = _vtxs.find(GlobalVertex::VTXTYPE::SVTX); + if (svtxit == _vtxs.end()) + { + return std::numeric_limits::quiet_NaN(); + } + + GlobalVertex::VertexVector trackvertices = svtxit->second; + size_t mosttracks = 0; + float chisq = std::numeric_limits::quiet_NaN(); + for (const auto* vertex : trackvertices) + { + if (vertex->size_tracks() > mosttracks) + { + mosttracks = vertex->size_tracks(); + chisq = vertex->get_chisq(); + } + } + + return chisq; +} + +unsigned int GlobalVertexv3::get_ndof() const +{ + auto svtxit = _vtxs.find(GlobalVertex::VTXTYPE::SVTX); + if (svtxit == _vtxs.end()) + { + return std::numeric_limits::max(); + } + + GlobalVertex::VertexVector trackvertices = svtxit->second; + size_t mosttracks = 0; + unsigned int ndf = std::numeric_limits::max(); + for (const auto* vertex : trackvertices) + { + if (vertex->size_tracks() > mosttracks) + { + mosttracks = vertex->size_tracks(); + ndf = vertex->get_ndof(); + } + } + + return ndf; +} + +float GlobalVertexv3::get_error(unsigned int i, unsigned int j) const +{ + auto svtxit = _vtxs.find(GlobalVertex::VTXTYPE::SVTX); + if (svtxit == _vtxs.end()) + { + auto mbdit = _vtxs.find(GlobalVertex::VTXTYPE::MBD); + if (mbdit == _vtxs.end()) + { + return std::numeric_limits::quiet_NaN(); + } + // MBD only has z error defined + if (i == 2 && j == 2) + { + return mbdit->second[0]->get_z_err(); + } + + return std::numeric_limits::quiet_NaN(); + } + + GlobalVertex::VertexVector trackvertices = svtxit->second; + size_t mosttracks = 0; + float err = std::numeric_limits::quiet_NaN(); + for (const auto* vertex : trackvertices) + { + if (vertex->size_tracks() > mosttracks) + { + mosttracks = vertex->size_tracks(); + err = vertex->get_error(i, j); + } + } + + return err; +} diff --git a/offline/packages/globalvertex/GlobalVertexv3.h b/offline/packages/globalvertex/GlobalVertexv3.h new file mode 100644 index 0000000000..c89e51e5c9 --- /dev/null +++ b/offline/packages/globalvertex/GlobalVertexv3.h @@ -0,0 +1,73 @@ +// Tell emacs that this is a C++ source +// -*- C++ -*-. +#ifndef GLOBALVERTEX_GLOBALVERTEXV3_H +#define GLOBALVERTEX_GLOBALVERTEXV3_H + +#include "GlobalVertex.h" + +#include // for size_t +#include +#include +#include + +class PHObject; + +class GlobalVertexv3 : public GlobalVertex +{ + public: + GlobalVertexv3() = default; + GlobalVertexv3(const unsigned int id); + ~GlobalVertexv3() override; + + // PHObject virtual overloads + void identify(std::ostream& os = std::cout) const override; + void Reset() override; + int isValid() const override; + PHObject* CloneMe() const override { return new GlobalVertexv3(*this); } + + unsigned int get_id() const override { return _id; } + void set_id(unsigned int id) override { _id = id; } + + short int get_beam_crossing() const override { return _bco; } + void set_beam_crossing(short int bco) override { _bco = bco; } + + float get_t() const override; + float get_t_err() const override; + float get_x() const override; + float get_y() const override; + float get_z() const override; + float get_chisq() const override; + unsigned int get_ndof() const override; + float get_position(unsigned int coor) const override; + float get_error(unsigned int i, unsigned int j) const override; + + // + // associated vertex methods + // + bool empty_vtxs() const override { return _vtxs.empty(); } + size_t size_vtxs() const override { return _vtxs.size(); } + size_t count_vtxs(GlobalVertex::VTXTYPE type) const override; + + void clear_vtxs() override { _vtxs.clear(); } + void insert_vtx(GlobalVertex::VTXTYPE type, const Vertex* vertex) override; + void clone_insert_vtx(GlobalVertex::VTXTYPE type, const Vertex* vertex) override; + size_t erase_vtxs(GlobalVertex::VTXTYPE type) override { return _vtxs.erase(type); } + void erase_vtxs(GlobalVertex::VertexIter iter) override { _vtxs.erase(iter); } + + GlobalVertex::ConstVertexIter begin_vertexes() const override { return _vtxs.begin(); } + GlobalVertex::ConstVertexIter find_vertexes(GlobalVertex::VTXTYPE type) const override { return _vtxs.find(type); } + GlobalVertex::ConstVertexIter end_vertexes() const override { return _vtxs.end(); } + + GlobalVertex::VertexIter begin_vertexes() override { return _vtxs.begin(); } + GlobalVertex::VertexIter find_vertexes(GlobalVertex::VTXTYPE type) override { return _vtxs.find(type); } + GlobalVertex::VertexIter end_vertexes() override { return _vtxs.end(); } + + private: + unsigned int _id{std::numeric_limits::max()}; + short int _bco{std::numeric_limits::max()}; //< global bco (signed short) + std::map _vtxs; //< list of vtxs + + ClassDefOverride(GlobalVertexv3, 3); +}; + +#endif diff --git a/offline/packages/globalvertex/GlobalVertexv3LinkDef.h b/offline/packages/globalvertex/GlobalVertexv3LinkDef.h new file mode 100644 index 0000000000..8cd2f1abf7 --- /dev/null +++ b/offline/packages/globalvertex/GlobalVertexv3LinkDef.h @@ -0,0 +1,5 @@ +#ifdef __CINT__ + +#pragma link C++ class GlobalVertexv3 + ; + +#endif /* __CINT__ */ diff --git a/offline/packages/globalvertex/Makefile.am b/offline/packages/globalvertex/Makefile.am index 5cedef884d..0ff0587389 100644 --- a/offline/packages/globalvertex/Makefile.am +++ b/offline/packages/globalvertex/Makefile.am @@ -30,17 +30,20 @@ pkginclude_HEADERS = \ GlobalVertex.h \ GlobalVertexv1.h \ GlobalVertexv2.h \ + GlobalVertexv3.h \ GlobalVertexMap.h \ GlobalVertexMapv1.h \ GlobalVertexReco.h \ MbdVertex.h \ MbdVertexv1.h \ MbdVertexv2.h \ + MbdVertexv3.h \ MbdVertexMap.h \ MbdVertexMapv1.h \ SvtxVertex.h \ SvtxVertex_v1.h \ SvtxVertex_v2.h \ + SvtxVertex_v3.h \ SvtxVertexMap.h \ SvtxVertexMap_v1.h \ TruthVertex.h \ @@ -57,16 +60,19 @@ ROOTDICTS = \ GlobalVertex_Dict.cc \ GlobalVertexv1_Dict.cc \ GlobalVertexv2_Dict.cc \ + GlobalVertexv3_Dict.cc \ GlobalVertexMap_Dict.cc \ GlobalVertexMapv1_Dict.cc \ MbdVertex_Dict.cc \ MbdVertexv1_Dict.cc \ MbdVertexv2_Dict.cc \ + MbdVertexv3_Dict.cc \ MbdVertexMap_Dict.cc \ MbdVertexMapv1_Dict.cc \ SvtxVertex_Dict.cc \ SvtxVertex_v1_Dict.cc \ SvtxVertex_v2_Dict.cc \ + SvtxVertex_v3_Dict.cc \ SvtxVertexMap_Dict.cc \ SvtxVertexMap_v1_Dict.cc \ TruthVertex_Dict.cc \ @@ -87,15 +93,18 @@ libglobalvertex_io_la_SOURCES = \ GlobalVertex.cc \ GlobalVertexv1.cc \ GlobalVertexv2.cc \ + GlobalVertexv3.cc \ GlobalVertexMap.cc \ GlobalVertexMapv1.cc \ MbdVertexv1.cc \ MbdVertexv2.cc \ + MbdVertexv3.cc \ MbdVertexMap.cc \ MbdVertexMapv1.cc \ SvtxVertex.cc \ SvtxVertex_v1.cc \ SvtxVertex_v2.cc \ + SvtxVertex_v3.cc \ SvtxVertexMap.cc \ SvtxVertexMap_v1.cc \ TruthVertex.cc \ diff --git a/offline/packages/globalvertex/MbdVertex.h b/offline/packages/globalvertex/MbdVertex.h index 6d0900b768..ed8d18e1d8 100644 --- a/offline/packages/globalvertex/MbdVertex.h +++ b/offline/packages/globalvertex/MbdVertex.h @@ -36,8 +36,12 @@ class MbdVertex : public Vertex virtual float get_z_err() const override { return std::numeric_limits::quiet_NaN(); } virtual void set_z_err(float) override {} - virtual unsigned int get_beam_crossing() const override { return std::numeric_limits::max(); } - virtual void set_beam_crossing(unsigned int) override {} + virtual short int get_beam_crossing() const override + { + return std::numeric_limits::max(); + } + virtual void set_beam_crossing(short int) override {} + virtual void set_bbc_ns(int, int, float, float) override {} virtual int get_bbc_npmt(int) const override { return std::numeric_limits::max(); } diff --git a/offline/packages/globalvertex/MbdVertexv2.h b/offline/packages/globalvertex/MbdVertexv2.h index bee34059e4..3b3482ed4f 100644 --- a/offline/packages/globalvertex/MbdVertexv2.h +++ b/offline/packages/globalvertex/MbdVertexv2.h @@ -44,12 +44,56 @@ class MbdVertexv2 : public MbdVertex float get_position(unsigned int coor) const override; - unsigned int get_beam_crossing() const override { return _bco; } - void set_beam_crossing(unsigned int bco) override { _bco = bco; } + short int get_beam_crossing() const override + { + return rollover_from_unsignedint(_bco); + } + void set_beam_crossing(short int bco) override + { + if (bco == short_int_max) + { + _bco = std::numeric_limits::max(); + return; + } + + const short int bco_ro = rollover_short(bco); + _bco = static_cast(bco_ro); + } private: + static constexpr short int short_int_max = std::numeric_limits::max(); // 32767 + + static short int rollover_short(short int bco) + { + if (bco == short_int_max) return short_int_max; + if (bco >= 0) return bco; + + const int bco_ro = static_cast(short_int_max) + static_cast(bco); // bco negative + return static_cast(bco_ro); + } + + static short int rollover_from_unsignedint(unsigned int bco) + { + // if unsigned int max, return short int max + if (bco == std::numeric_limits::max()) + { + return short_int_max; + } + + // common case: [0, 32767] + if (bco <= static_cast(short_int_max)) + { + return static_cast(bco); + } + + const short int bco_ro = static_cast(static_cast(bco)); + if (bco_ro >= 0) return bco_ro; + + return rollover_short(bco_ro); + } + unsigned int _id{std::numeric_limits::max()}; //< unique identifier within container - unsigned int _bco{std::numeric_limits::max()}; //< global bco + unsigned int _bco{std::numeric_limits::max()}; //< global bco (legacy storage) float _t{std::numeric_limits::quiet_NaN()}; //< collision time float _t_err{std::numeric_limits::quiet_NaN()}; //< collision time uncertainty float _z{std::numeric_limits::quiet_NaN()}; //< collision position z diff --git a/offline/packages/globalvertex/MbdVertexv3.cc b/offline/packages/globalvertex/MbdVertexv3.cc new file mode 100644 index 0000000000..9c76f521a3 --- /dev/null +++ b/offline/packages/globalvertex/MbdVertexv3.cc @@ -0,0 +1,60 @@ +#include "MbdVertexv3.h" + +#include +#include + +void MbdVertexv3::identify(std::ostream& os) const +{ + os << "---MbdVertexv3--------------------------------" << std::endl; + os << "vertexid: " << get_id() << std::endl; + os << " t = " << get_t() << " +/- " << get_t_err() << std::endl; + os << " z = " << get_z() << " +/- " << get_z_err() << std::endl; + os << " bco = " << get_beam_crossing() << std::endl; + os << "-----------------------------------------------" << std::endl; + + return; +} + +int MbdVertexv3::isValid() const +{ + if (_id == std::numeric_limits::max()) + { + return 0; + } + if (std::isnan(_t)) + { + return 0; + } + if (std::isnan(_t_err)) + { + return 0; + } + if (std::isnan(_z)) + { + return 0; + } + if (std::isnan(_z_err)) + { + return 0; + } + + return 1; +} + +float MbdVertexv3::get_position(unsigned int coor) const +{ + if (coor == 0) + { + return get_x(); + } + if (coor == 1) + { + return get_y(); + } + if (coor == 2) + { + return get_z(); + } + + return std::numeric_limits::quiet_NaN(); +} diff --git a/offline/packages/globalvertex/MbdVertexv3.h b/offline/packages/globalvertex/MbdVertexv3.h new file mode 100644 index 0000000000..7d59c82d79 --- /dev/null +++ b/offline/packages/globalvertex/MbdVertexv3.h @@ -0,0 +1,60 @@ +// Tell emacs that this is a C++ source +// -*- C++ -*-. +#ifndef GLOBALVERTEX_MBDVERTEXV3_H +#define GLOBALVERTEX_MBDVERTEXV3_H + +#include "MbdVertex.h" + +#include +#include + +class MbdVertexv3 : public MbdVertex +{ + public: + MbdVertexv3() = default; + ~MbdVertexv3() override = default; + + // PHObject virtual overloads + void identify(std::ostream& os = std::cout) const override; + void Reset() override { *this = MbdVertexv3(); } + int isValid() const override; + PHObject* CloneMe() const override { return new MbdVertexv3(*this); } + + // vertex info + unsigned int get_id() const override { return _id; } + void set_id(unsigned int id) override { _id = id; } + + float get_t() const override { return _t; } + void set_t(float t) override { _t = t; } + + float get_t_err() const override { return _t_err; } + void set_t_err(float t_err) override { _t_err = t_err; } + + // Return 0 for now, can implement beam spot + float get_x() const override { return 0; } + float get_y() const override { return 0; } + + float get_z() const override { return _z; } + void set_z(float z) override { _z = z; } + + float get_z_err() const override { return _z_err; } + void set_z_err(float z_err) override { _z_err = z_err; } + + float get_position(unsigned int coor) const override; + + // beam crossing methods (v3: native signed short storage) + short int get_beam_crossing() const override { return _bco; } + void set_beam_crossing(short int bco) override { _bco = bco; } + + private: + unsigned int _id{std::numeric_limits::max()}; //< unique identifier within container + short int _bco{std::numeric_limits::max()}; //< global bco (signed short) + float _t{std::numeric_limits::quiet_NaN()}; //< collision time + float _t_err{std::numeric_limits::quiet_NaN()}; //< collision time uncertainty + float _z{std::numeric_limits::quiet_NaN()}; //< collision position z + float _z_err{std::numeric_limits::quiet_NaN()}; //< collision position z uncertainty + + ClassDefOverride(MbdVertexv3, 1); +}; + +#endif diff --git a/offline/packages/globalvertex/MbdVertexv3LinkDef.h b/offline/packages/globalvertex/MbdVertexv3LinkDef.h new file mode 100644 index 0000000000..b55e4bf42d --- /dev/null +++ b/offline/packages/globalvertex/MbdVertexv3LinkDef.h @@ -0,0 +1,5 @@ +#ifdef __CINT__ + +#pragma link C++ class MbdVertexv3 + ; + +#endif /* __CINT__ */ diff --git a/offline/packages/globalvertex/SvtxVertex_v2.h b/offline/packages/globalvertex/SvtxVertex_v2.h index 24ccbfc0ca..32d19eda66 100644 --- a/offline/packages/globalvertex/SvtxVertex_v2.h +++ b/offline/packages/globalvertex/SvtxVertex_v2.h @@ -54,8 +54,21 @@ class SvtxVertex_v2 : public SvtxVertex float get_error(unsigned int i, unsigned int j) const override; //< get vertex error covar void set_error(unsigned int i, unsigned int j, float value) override; //< set vertex error covar - unsigned int get_beam_crossing() const override { return _beamcrossing; } - void set_beam_crossing(unsigned int cross) override { _beamcrossing = cross; } + short int get_beam_crossing() const override + { + return rollover_from_unsignedint(_beamcrossing); + } + void set_beam_crossing(short int cross) override + { + if (cross == short_int_max) + { + _beamcrossing = std::numeric_limits::max(); + return; + } + + const short int cross_ro = rollover_short(cross); + _beamcrossing = static_cast(cross_ro); + } // // associated track ids methods @@ -73,6 +86,37 @@ class SvtxVertex_v2 : public SvtxVertex TrackIter end_tracks() override { return _track_ids.end(); } private: + static constexpr short int short_int_max = std::numeric_limits::max(); // 32767 + // for unsigned int to short int conversion (rollover) + static short int rollover_short(short int cross) + { + if (cross == short_int_max) return short_int_max; + if (cross >= 0) return cross; + + const int cross_ro = static_cast(short_int_max) + static_cast(cross); // cross negative + return static_cast(cross_ro); + } + + static short int rollover_from_unsignedint(unsigned int cross) + { + // if unsigned int max, return short int max + if (cross == std::numeric_limits::max()) + { + return short_int_max; + } + + // Common case: [0, 32767] + if (cross <= static_cast(short_int_max)) + { + return static_cast(cross); + } + + const short int cross_ro = static_cast(static_cast(cross)); + if (cross_ro >= 0) return cross_ro; + + return rollover_short(cross_ro); + } + unsigned int covar_index(unsigned int i, unsigned int j) const; unsigned int _id{std::numeric_limits::max()}; //< unique identifier within container diff --git a/offline/packages/globalvertex/SvtxVertex_v3.cc b/offline/packages/globalvertex/SvtxVertex_v3.cc new file mode 100644 index 0000000000..731a2c841f --- /dev/null +++ b/offline/packages/globalvertex/SvtxVertex_v3.cc @@ -0,0 +1,113 @@ +#include "SvtxVertex_v3.h" + +#include +#include +#include +#include // for swap + +SvtxVertex_v3::SvtxVertex_v3() +{ + std::fill(std::begin(_pos), std::end(_pos), std::numeric_limits::quiet_NaN()); + std::fill(std::begin(_err), std::end(_err), std::numeric_limits::quiet_NaN()); +} + +void SvtxVertex_v3::identify(std::ostream& os) const +{ + os << "---SvtxVertex_v3--------------------" << std::endl; + os << "vertexid: " << get_id() << std::endl; + + os << " t0 = " << get_t() << std::endl; + os << " beam crossing = " << get_beam_crossing() << std::endl; + os << " (x,y,z) = (" << get_position(0); + os << ", " << get_position(1) << ", "; + os << get_position(2) << ") cm" << std::endl; + + os << " chisq = " << get_chisq() << ", "; + os << " ndof = " << get_ndof() << std::endl; + + os << " ( "; + os << get_error(0, 0) << " , "; + os << get_error(0, 1) << " , "; + os << get_error(0, 2) << " )" << std::endl; + os << " err = ( "; + os << get_error(1, 0) << " , "; + os << get_error(1, 1) << " , "; + os << get_error(1, 2) << " )" << std::endl; + os << " ( "; + os << get_error(2, 0) << " , "; + os << get_error(2, 1) << " , "; + os << get_error(2, 2) << " )" << std::endl; + + os << " list of tracks ids: "; + for (ConstTrackIter iter = begin_tracks(); iter != end_tracks(); ++iter) + { + os << *iter << " "; + } + os << std::endl; + os << "-----------------------------------------------" << std::endl; + + return; +} + +int SvtxVertex_v3::isValid() const +{ + if (_id == std::numeric_limits::max()) + { + return 0; + } + if (std::isnan(_t0)) + { + return 0; + } + if (std::isnan(_chisq)) + { + return 0; + } + if (_ndof == std::numeric_limits::max()) + { + return 0; + } + + for (float _po : _pos) + { + if (std::isnan(_po)) + { + return 0; + } + } + for (int j = 0; j < 3; ++j) + { + for (int i = j; i < 3; ++i) + { + if (std::isnan(get_error(i, j))) + { + return 0; + } + } + } + if (_track_ids.empty()) + { + return 0; + } + return 1; +} + +void SvtxVertex_v3::set_error(unsigned int i, unsigned int j, float value) +{ + _err[covar_index(i, j)] = value; + return; +} + +float SvtxVertex_v3::get_error(unsigned int i, unsigned int j) const +{ + return _err[covar_index(i, j)]; +} + +unsigned int SvtxVertex_v3::covar_index(unsigned int i, unsigned int j) const +{ + if (i > j) + { + std::swap(i, j); + } + return i + 1 + (j + 1) * (j) / 2 - 1; +} diff --git a/offline/packages/globalvertex/SvtxVertex_v3.h b/offline/packages/globalvertex/SvtxVertex_v3.h new file mode 100644 index 0000000000..74a75d90ea --- /dev/null +++ b/offline/packages/globalvertex/SvtxVertex_v3.h @@ -0,0 +1,89 @@ +// Tell emacs that this is a C++ source +// -*- C++ -*-. +#ifndef GLOBALVERTEX_SVTXVERTEXV3_H +#define GLOBALVERTEX_SVTXVERTEXV3_H + +#include "SvtxVertex.h" + +#include // for size_t +#include +#include +#include + +class PHObject; + +class SvtxVertex_v3 : public SvtxVertex +{ + public: + SvtxVertex_v3(); + ~SvtxVertex_v3() override {} + + // PHObject virtual overloads + void identify(std::ostream& os = std::cout) const override; + void Reset() override { *this = SvtxVertex_v3(); } + int isValid() const override; + PHObject* CloneMe() const override { return new SvtxVertex_v3(*this); } + + // vertex info + unsigned int get_id() const override { return _id; } + void set_id(unsigned int id) override { _id = id; } + + float get_t() const override { return _t0; } + void set_t(float t0) override { _t0 = t0; } + + float get_x() const override { return _pos[0]; } + void set_x(float x) override { _pos[0] = x; } + + float get_y() const override { return _pos[1]; } + void set_y(float y) override { _pos[1] = y; } + + float get_z() const override { return _pos[2]; } + void set_z(float z) override { _pos[2] = z; } + + float get_chisq() const override { return _chisq; } + void set_chisq(float chisq) override { _chisq = chisq; } + + unsigned int get_ndof() const override { return _ndof; } + void set_ndof(unsigned int ndof) override { _ndof = ndof; } + + float get_position(unsigned int coor) const override { return _pos[coor]; } + void set_position(unsigned int coor, float xi) override { _pos[coor] = xi; } + + float get_error(unsigned int i, unsigned int j) const override; //< get vertex error covar + void set_error(unsigned int i, unsigned int j, float value) override; //< set vertex error covar + + // v3 uses signed short + short int get_beam_crossing() const override { return _beamcrossing; } + void set_beam_crossing(short int cross) override { _beamcrossing = cross; } + + // + // associated track ids methods + // + void clear_tracks() override { _track_ids.clear(); } + bool empty_tracks() override { return _track_ids.empty(); } + size_t size_tracks() const override { return _track_ids.size(); } + void insert_track(unsigned int trackid) override { _track_ids.insert(trackid); } + size_t erase_track(unsigned int trackid) override { return _track_ids.erase(trackid); } + ConstTrackIter begin_tracks() const override { return _track_ids.begin(); } + ConstTrackIter find_track(unsigned int trackid) const override { return _track_ids.find(trackid); } + ConstTrackIter end_tracks() const override { return _track_ids.end(); } + TrackIter begin_tracks() override { return _track_ids.begin(); } + TrackIter find_track(unsigned int trackid) override { return _track_ids.find(trackid); } + TrackIter end_tracks() override { return _track_ids.end(); } + + private: + unsigned int covar_index(unsigned int i, unsigned int j) const; + + unsigned int _id{std::numeric_limits::max()}; //< unique identifier within container + float _t0{std::numeric_limits::quiet_NaN()}; //< collision time + float _pos[3]{}; //< collision position x,y,z + float _chisq{std::numeric_limits::quiet_NaN()}; //< vertex fit chisq + unsigned int _ndof{std::numeric_limits::max()}; //< degrees of freedom + float _err[6]{}; //< error covariance matrix (packed storage) (+/- cm^2) + std::set _track_ids; //< list of track ids + short int _beamcrossing{std::numeric_limits::max()}; + + ClassDefOverride(SvtxVertex_v3, 3); +}; + +#endif diff --git a/offline/packages/globalvertex/SvtxVertex_v3LinkDef.h b/offline/packages/globalvertex/SvtxVertex_v3LinkDef.h new file mode 100644 index 0000000000..7b6506845d --- /dev/null +++ b/offline/packages/globalvertex/SvtxVertex_v3LinkDef.h @@ -0,0 +1,5 @@ +#ifdef __CINT__ + +#pragma link C++ class SvtxVertex_v3 + ; + +#endif /* __CINT__ */ diff --git a/offline/packages/globalvertex/TruthVertex_v1.cc b/offline/packages/globalvertex/TruthVertex_v1.cc index 38e9b2a61b..1c1ad39f4d 100644 --- a/offline/packages/globalvertex/TruthVertex_v1.cc +++ b/offline/packages/globalvertex/TruthVertex_v1.cc @@ -15,3 +15,21 @@ int TruthVertex_v1::isValid() const { return std::isfinite(_z) && std::isfinite(_t); } + +float TruthVertex_v1::get_position(unsigned int coor) const +{ + if (coor == 0) + { + return get_x(); + } + if (coor == 1) + { + return get_y(); + } + if (coor == 2) + { + return get_z(); + } + + return std::numeric_limits::quiet_NaN(); +} \ No newline at end of file diff --git a/offline/packages/globalvertex/TruthVertex_v1.h b/offline/packages/globalvertex/TruthVertex_v1.h index 42b48d9903..e5148387af 100644 --- a/offline/packages/globalvertex/TruthVertex_v1.h +++ b/offline/packages/globalvertex/TruthVertex_v1.h @@ -46,6 +46,7 @@ class TruthVertex_v1 : public TruthVertex float get_y_err() const override { return _y_err; } void set_y_err(float y_err) override { _y_err = y_err; } + float get_position(unsigned int coor) const override; private: unsigned int _id{std::numeric_limits::max()}; float _t{std::numeric_limits::quiet_NaN()}; diff --git a/offline/packages/globalvertex/Vertex.h b/offline/packages/globalvertex/Vertex.h index 7bbfa5f381..e475bfb95d 100644 --- a/offline/packages/globalvertex/Vertex.h +++ b/offline/packages/globalvertex/Vertex.h @@ -62,8 +62,8 @@ class Vertex : public PHObject virtual void set_error(unsigned int /*i*/, unsigned int /*j*/, float /*value*/) {} // beam crossing methods - virtual unsigned int get_beam_crossing() const { return std::numeric_limits::max(); } - virtual void set_beam_crossing(unsigned int) {} + virtual short int get_beam_crossing() const { return std::numeric_limits::max(); } + virtual void set_beam_crossing(short int) {} // bbcvertex methods virtual void set_bbc_ns(int, int, float, float) {} diff --git a/offline/packages/intt/InttCombinedRawDataDecoder.cc b/offline/packages/intt/InttCombinedRawDataDecoder.cc index 18db00ef01..4ffd06f8e1 100644 --- a/offline/packages/intt/InttCombinedRawDataDecoder.cc +++ b/offline/packages/intt/InttCombinedRawDataDecoder.cc @@ -18,7 +18,12 @@ #include #include +#include +#include +#include + +#include #include #include // for PHIODataNode #include @@ -35,8 +40,9 @@ InttCombinedRawDataDecoder::InttCombinedRawDataDecoder(std::string const& name) : SubsysReco(name) - , m_calibinfoDAC({"INTT_DACMAP", CDB}) + // , m_calibinfoDAC({"INTT_DACMAP", CDB}) , m_calibinfoBCO({"INTT_BCOMAP", CDB}) + , m_intt_dac_values(0) { // Do nothing // Consider calling LoadHotChannelMapRemote() @@ -128,17 +134,60 @@ int InttCombinedRawDataDecoder::InitRun(PHCompositeNode* topNode) } /////////////////////////////////////// - std::cout << "calibinfo DAC : " << m_calibinfoDAC.first << " " << (m_calibinfoDAC.second == CDB ? "CDB" : "FILE") << std::endl; - m_dacmap.Verbosity(Verbosity()); - if (m_calibinfoDAC.second == CDB) - { - m_dacmap.LoadFromCDB(m_calibinfoDAC.first); - } - else + recoConsts *rc = recoConsts::instance(); + int run_number = rc->get_IntFlag("RUNNUMBER"); + + odbc::Statement* statement = DBInterface::instance()->getStatement("daq"); + if (!statement) { - m_dacmap.LoadFromFile(m_calibinfoDAC.first); + std::cerr << PHWHERE << "\n" + << "\tCould not get ODBC statement for 'daq' database\n" + << "\tExiting\n" + << std::flush; + exit(1); + gSystem->Exit(1); } + if (DACValue_set_count == 0){ + std::cout<< PHWHERE << ", " << "No manual setting for DAC values. Querying INTT DAC values from intt_setting table for run number " << run_number << std::endl; + int error_count = InttCombinedRawDataDecoder::QueryAllDACValues(statement, run_number); + + int count_minus = 0; + for (const auto& dac_value : m_intt_dac_values) + { + if (dac_value <= 0) {count_minus++;} + } + + if (error_count != 0 || m_intt_dac_values.size() != 8 || count_minus != 0) + { + std::cerr << PHWHERE << "\n" + << "\tError retrieving DAC values. error_count: " << error_count + << ", size of m_intt_dac_values: " << m_intt_dac_values.size() << std::endl; + std:: cout << "In the dac map: "; + for (size_t i = 0; i < m_intt_dac_values.size(); ++i) + { + std::cout << "dac" << i << ": " << m_intt_dac_values[i] << ", "; + } + std::cout << std::endl; + std::cout<< " The DAC values should be 8 integers and all should be positive. Exiting."<< std::endl; + std::cout<< " Please contact the INTT group if the run you analyzed doesn't appear in the intt_setting table."<< std::endl; + + exit(1); + gSystem->Exit(1); + } + } + + // std::cout << "calibinfo DAC : " << m_calibinfoDAC.first << " " << (m_calibinfoDAC.second == CDB ? "CDB" : "FILE") << std::endl; + // m_dacmap.Verbosity(Verbosity()); + // if (m_calibinfoDAC.second == CDB) + // { + // m_dacmap.LoadFromCDB(m_calibinfoDAC.first); + // } + // else + // { + // m_dacmap.LoadFromFile(m_calibinfoDAC.first); + // } + /////////////////////////////////////// std::cout << "calibinfo BCO : " << m_calibinfoBCO.first << " " << (m_calibinfoBCO.second == CDB ? "CDB" : "FILE") << std::endl; m_bcomap.Verbosity(Verbosity()); @@ -302,6 +351,19 @@ int InttCombinedRawDataDecoder::process_event(PHCompositeNode* topNode) continue; } + if (std::find(permanant_mask_chip.begin(), permanant_mask_chip.end(), std::format("{}_{}_{}", raw.felix_server, raw.felix_channel, raw.chip)) != permanant_mask_chip.end()) + { + if (1 < Verbosity()) + { + std::cout + << PHWHERE << "\n" + << "\tMasking permanant bad chip due to timing issues:\n" + << "\t" << raw.felix_server << " " << raw.felix_channel << " " << raw.chip << " " << raw.channel << "\n" + << std::endl; + } + continue; + } + //////////////////////// // bco filter if (m_bcomap.IsBad(raw, bco_full, bco) && m_bcoFilter) @@ -429,7 +491,13 @@ int InttCombinedRawDataDecoder::process_event(PHCompositeNode* topNode) //////////////////////// // dac conversion - int dac = m_dacmap.GetDAC(raw, adc); + // int dac = m_dacmap.GetDAC(raw, adc); + int dac = (adc >= 0 && adc <= 7) ? m_intt_dac_values[adc] : -1; + + if (Verbosity() > 100000){ + std::cout<< PHWHERE << "\n" << "ADC value: " << adc << ", converted DAC value: " << dac << std::endl; + } + hit = new TrkrHitv2; //--hit->setAdc(adc); @@ -441,3 +509,70 @@ int InttCombinedRawDataDecoder::process_event(PHCompositeNode* topNode) return Fun4AllReturnCodes::EVENT_OK; } + + +void InttCombinedRawDataDecoder::set_DACValues(const std::vector& input_dac_vec) +{ + m_intt_dac_values = input_dac_vec; + DACValue_set_count = 1; + int count_minus = 0; + std::cout<Exit(1); + } +} + +int InttCombinedRawDataDecoder::QueryAllDACValues(odbc::Statement *statement, int runnumber) +{ + + std::unique_ptr result_set; + m_intt_dac_values.clear(); + + try + { + std::string sql = "SELECT dac0, dac1, dac2, dac3, dac4, dac5, dac6, dac7 From intt_setting WHERE runnumber = " + std::to_string(runnumber) + ";"; + result_set = std::unique_ptr(statement->executeQuery(sql)); + + if (!(result_set && result_set->next())) + { + std::cerr << PHWHERE << "\n" + << "\tNo DAC row found in intt_setting for run " << runnumber << std::endl; + return 1; + } + for (int i = 0; i < 8; i++) + { + std::string column_name = "dac" + std::to_string(i); + int DAC_value = -1; + DAC_value = result_set->getInt(column_name); + m_intt_dac_values.push_back(DAC_value); + std::cout << PHWHERE << ", retrieved DAC value for " << column_name << ": " << DAC_value << std::endl; + } + } + catch (odbc::SQLException& e) + { + std::cerr << PHWHERE << "\n" + << "\tSQL Exception:\n" + << "\t" << e.getMessage() << std::endl; + return 1; + } + + return 0; +} \ No newline at end of file diff --git a/offline/packages/intt/InttCombinedRawDataDecoder.h b/offline/packages/intt/InttCombinedRawDataDecoder.h index 1ebb71200e..642f2edafa 100644 --- a/offline/packages/intt/InttCombinedRawDataDecoder.h +++ b/offline/packages/intt/InttCombinedRawDataDecoder.h @@ -3,12 +3,13 @@ #include "InttBadChannelMap.h" #include "InttBCOMap.h" -#include "InttDacMap.h" +// #include "InttDacMap.h" #include #include #include +#include #include #include #include @@ -17,6 +18,11 @@ class PHCompositeNode; class InttEventInfo; +namespace odbc +{ + class Statement; +} // namespace odbc + class InttCombinedRawDataDecoder : public SubsysReco { public: @@ -40,10 +46,10 @@ class InttCombinedRawDataDecoder : public SubsysReco /// Depreciated; use LoadHotChannelMap(const std::string&); int LoadHotChannelMapRemote(std::string const& s = "INTT_HotChannelMap") {return LoadBadChannelMap(s);} - void SetCalibDAC(std::string const& calibname = "INTT_DACMAP", const CalibRef& calibref = CDB) - { - m_calibinfoDAC = std::pair(calibname, calibref); - } + // void SetCalibDAC(std::string const& calibname = "INTT_DACMAP", const CalibRef& calibref = CDB) + // { + // m_calibinfoDAC = std::pair(calibname, calibref); + // } void SetCalibBCO(std::string const& calibname = "INTT_BCOMAP", const CalibRef& calibref = CDB) { @@ -60,21 +66,27 @@ class InttCombinedRawDataDecoder : public SubsysReco void set_bcoFilter(bool flag) {m_bcoFilter = flag; } void set_SaturatedChipRejection(bool flag){m_SaturatedChipRejection = flag;} // note : this is for removing a fraction of the saturated chips void set_HighChipMultiplicityCut(int cut){HighChipMultiplicityCut = cut;} + void set_DACValues(const std::vector& input_dac_vec); private: + int QueryAllDACValues(odbc::Statement *statement, int runnumber); + InttEventInfo* intt_event_header = nullptr; std::string m_InttRawNodeName = "INTTRAWHIT"; bool m_runStandAlone = false; bool m_writeInttEventHeader = false; bool m_bcoFilter = false; bool m_SaturatedChipRejection = true; // note : true as default - std::pair m_calibinfoDAC; + // std::pair m_calibinfoDAC; std::pair m_calibinfoBCO; InttBadChannelMap m_badmap; - InttDacMap m_dacmap; + // InttDacMap m_dacmap; InttBCOMap m_bcomap; + std::vector m_intt_dac_values; + int DACValue_set_count = 0; + int m_inttFeeOffset = 23; //23 is the offset for INTT in streaming mode bool m_outputBcoDiff = false; bool m_triggeredMode = false; @@ -83,6 +95,10 @@ class InttCombinedRawDataDecoder : public SubsysReco std::map evt_ChipHit_count_map; int HighChipMultiplicityCut = 71; + std::vector permanant_mask_chip = { + "2_9_15" // note : FELIX 2, FELIX channel 9, chip 15 (chip ID range: 0 to 25) + }; + }; #endif // INTT_COMBINEDRAWDATADECODER_H diff --git a/offline/packages/jetbackground/DetermineTowerBackground.cc b/offline/packages/jetbackground/DetermineTowerBackground.cc index 9823d337f6..64ffd50835 100644 --- a/offline/packages/jetbackground/DetermineTowerBackground.cc +++ b/offline/packages/jetbackground/DetermineTowerBackground.cc @@ -14,6 +14,10 @@ #include #include +#include +#include +#include + #include #include @@ -52,9 +56,57 @@ DetermineTowerBackground::DetermineTowerBackground(const std::string &name) int DetermineTowerBackground::InitRun(PHCompositeNode *topNode) { + if (_do_flow == 4) + { + if (Verbosity()) + { + std::cout << "Loading the average calo v2" << std::endl; + } + if (LoadCalibrations()) + { + std::cout << "Load calibrations failed." << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + + } + return CreateNode(topNode); } +int DetermineTowerBackground::LoadCalibrations() +{ + + CDBTTree *cdbtree_calo_v2 = nullptr; + + std::string calibdir = CDBInterface::instance()->getUrl(m_calibName); + if (m_overwrite_average_calo_v2) + { + calibdir = m_overwrite_average_calo_v2_path; + } + + if (calibdir.empty()) + { + std::cout << "Could not find filename for calo average v2, exiting" << std::endl; + exit(-1); + } + + cdbtree_calo_v2 = new CDBTTree(calibdir); + + + cdbtree_calo_v2->LoadCalibrations(); + + _CENTRALITY_V2.assign(100,0); + + for (int icent = 0; icent < 100; icent++) + { + _CENTRALITY_V2[icent] = cdbtree_calo_v2->GetFloatValue(icent, "jet_calo_v2"); + } + + delete cdbtree_calo_v2; + + return Fun4AllReturnCodes::EVENT_OK; +} + int DetermineTowerBackground::process_event(PHCompositeNode *topNode) { @@ -226,7 +278,7 @@ int DetermineTowerBackground::process_event(PHCompositeNode *topNode) const RawTowerDefs::keytype key = RawTowerDefs::encode_towerid(RawTowerDefs::CalorimeterId::HCALIN, comp_ieta, comp_iphi); tower_geom = geomIH->get_tower_geometry(key); comp_ET = towerinfo->get_energy() / cosh(tower_geom->get_eta()); - comp_isBad = towerinfo->get_isHot() || towerinfo->get_isNoCalib() || towerinfo->get_isNotInstr() || towerinfo->get_isBadChi2(); + comp_isBad = !towerinfo->get_isGood(); } else if (comp.first == 7 || comp.first == 27) { @@ -237,7 +289,7 @@ int DetermineTowerBackground::process_event(PHCompositeNode *topNode) const RawTowerDefs::keytype key = RawTowerDefs::encode_towerid(RawTowerDefs::CalorimeterId::HCALOUT, comp_ieta, comp_iphi); tower_geom = geomOH->get_tower_geometry(key); comp_ET = towerinfo->get_energy() / cosh(tower_geom->get_eta()); - comp_isBad = towerinfo->get_isHot() || towerinfo->get_isNoCalib() || towerinfo->get_isNotInstr() || towerinfo->get_isBadChi2(); + comp_isBad = !towerinfo->get_isGood(); } else if (comp.first == 13 || comp.first == 28) { @@ -248,7 +300,7 @@ int DetermineTowerBackground::process_event(PHCompositeNode *topNode) const RawTowerDefs::keytype key = RawTowerDefs::encode_towerid(RawTowerDefs::CalorimeterId::HCALIN, comp_ieta, comp_iphi); tower_geom = geomIH->get_tower_geometry(key); comp_ET = towerinfo->get_energy() / cosh(tower_geom->get_eta()); - comp_isBad = towerinfo->get_isHot() || towerinfo->get_isNoCalib() || towerinfo->get_isNotInstr() || towerinfo->get_isBadChi2(); + comp_isBad = !towerinfo->get_isGood(); } @@ -415,7 +467,7 @@ int DetermineTowerBackground::process_event(PHCompositeNode *topNode) int this_phibin = towerinfosEM3->getTowerPhiBin(key); TowerInfo *tower = towerinfosEM3->get_tower_at_channel(channel); float this_E = tower->get_energy(); - int this_isBad = tower->get_isHot() || tower->get_isNoCalib() || tower->get_isNotInstr() || tower->get_isBadChi2(); + int this_isBad = !tower->get_isGood(); _EMCAL_ISBAD[this_etabin][this_phibin] = this_isBad; if (!this_isBad) { // just in case since all energy is summed @@ -433,7 +485,7 @@ int DetermineTowerBackground::process_event(PHCompositeNode *topNode) int this_phibin = towerinfosIH3->getTowerPhiBin(key); TowerInfo *tower = towerinfosIH3->get_tower_at_channel(channel); float this_E = tower->get_energy(); - int this_isBad = tower->get_isHot() || tower->get_isNoCalib() || tower->get_isNotInstr() || tower->get_isBadChi2(); + int this_isBad = !tower->get_isGood(); _IHCAL_ISBAD[this_etabin][this_phibin] = this_isBad; if (!this_isBad) { // just in case since all energy is summed @@ -451,7 +503,7 @@ int DetermineTowerBackground::process_event(PHCompositeNode *topNode) int this_phibin = towerinfosOH3->getTowerPhiBin(key); TowerInfo *tower = towerinfosOH3->get_tower_at_channel(channel); float this_E = tower->get_energy(); - int this_isBad = tower->get_isHot() || tower->get_isNoCalib() || tower->get_isNotInstr() || tower->get_isBadChi2(); + int this_isBad = !tower->get_isGood(); _OHCAL_ISBAD[this_etabin][this_phibin] = this_isBad; if (!this_isBad) { // just in case since all energy is summed @@ -481,7 +533,103 @@ int DetermineTowerBackground::process_event(PHCompositeNode *topNode) } } - if ( _do_flow >= 1 ) + + // Get psi + if (_do_flow == 2) + { // HIJING truth flow extraction + PHG4TruthInfoContainer *truthinfo = findNode::getClass(topNode, "G4TruthInfo"); + + if (!truthinfo) + { + std::cout << "DetermineTowerBackground::process_event: FATAL , G4TruthInfo does not exist , cannot extract truth flow with do_flow = " << _do_flow << std::endl; + return -1; + } + + PHG4TruthInfoContainer::Range range = truthinfo->GetPrimaryParticleRange(); + + float Hijing_Qx = 0; + float Hijing_Qy = 0; + + for (PHG4TruthInfoContainer::ConstIterator iter = range.first; iter != range.second; ++iter) + { + PHG4Particle *g4particle = iter->second; + + if (truthinfo->isEmbeded(g4particle->get_track_id()) != 0) + { + continue; + } + + TLorentzVector t; + t.SetPxPyPzE(g4particle->get_px(), g4particle->get_py(), g4particle->get_pz(), g4particle->get_e()); + + float truth_pt = t.Pt(); + if (truth_pt < 0.4) + { + continue; + } + float truth_eta = t.Eta(); + if (std::fabs(truth_eta) > 1.1) + { + continue; + } + float truth_phi = t.Phi(); + int truth_pid = g4particle->get_pid(); + + if (Verbosity() > 10) + { + std::cout << "DetermineTowerBackground::process_event: determining truth flow, using particle w/ pt / eta / phi " << truth_pt << " / " << truth_eta << " / " << truth_phi << " , embed / PID = " << truthinfo->isEmbeded(g4particle->get_track_id()) << " / " << truth_pid << std::endl; + } + + Hijing_Qx += truth_pt * std::cos(2 * truth_phi); + Hijing_Qy += truth_pt * std::sin(2 * truth_phi); + } + + _Psi2 = std::atan2(Hijing_Qy, Hijing_Qx) / 2.0; + + if (Verbosity() > 0) + { + std::cout << "DetermineTowerBackground::process_event: flow extracted from Hijing truth particles, setting Psi2 = " << _Psi2 << " ( " << _Psi2 / M_PI << " * pi ) " << std::endl; + } + } + else if (_do_flow == 3 || _do_flow == 4) + { // sEPD event plane extraction + // get event plane map + EventplaneinfoMap *epmap = findNode::getClass(topNode, "EventplaneinfoMap"); + if (!epmap) + { + std::cout << "DetermineTowerBackground::process_event: FATAL, EventplaneinfoMap does not exist, cannot extract sEPD flow with do_flow = " << _do_flow << std::endl; + exit(-1); + } + if (!(epmap->empty())) + { + auto *EPDNS = epmap->get(EventplaneinfoMap::sEPDNS); + _Psi2 = EPDNS->get_shifted_psi(2); + } + else + { + _is_flow_failure = true; + _Psi2 = 0; + } + + // Safety check + if (!std::isfinite(_Psi2)) + { + if (Verbosity() > 0) + { + std::cout << "DetermineTowerBackground::process_event: WARNING Psi2 is non-finite (NaN or Inf), setting Psi2 = 0." << std::endl; + } + _is_flow_failure = true; + _Psi2 = 0; + } + + if (Verbosity() > 0) + { + std::cout << "DetermineTowerBackground::process_event: flow extracted from sEPD, setting Psi2 = " << _Psi2 << " ( " << _Psi2 / M_PI << " * pi ) " << std::endl; + } + + } + + if ( _do_flow >= 1 && _do_flow < 4) { if (Verbosity() > 0) @@ -754,88 +902,6 @@ int DetermineTowerBackground::process_event(PHCompositeNode *topNode) { // Calo event plane _Psi2 = std::atan2(Q_y, Q_x) / 2.0; } - else if (_do_flow == 2) - { // HIJING truth flow extraction - PHG4TruthInfoContainer *truthinfo = findNode::getClass(topNode, "G4TruthInfo"); - - if (!truthinfo) - { - std::cout << "DetermineTowerBackground::process_event: FATAL , G4TruthInfo does not exist , cannot extract truth flow with do_flow = " << _do_flow << std::endl; - return -1; - } - - PHG4TruthInfoContainer::Range range = truthinfo->GetPrimaryParticleRange(); - - float Hijing_Qx = 0; - float Hijing_Qy = 0; - - for (PHG4TruthInfoContainer::ConstIterator iter = range.first; iter != range.second; ++iter) - { - PHG4Particle *g4particle = iter->second; - - if (truthinfo->isEmbeded(g4particle->get_track_id()) != 0) - { - continue; - } - - TLorentzVector t; - t.SetPxPyPzE(g4particle->get_px(), g4particle->get_py(), g4particle->get_pz(), g4particle->get_e()); - - float truth_pt = t.Pt(); - if (truth_pt < 0.4) - { - continue; - } - float truth_eta = t.Eta(); - if (std::fabs(truth_eta) > 1.1) - { - continue; - } - float truth_phi = t.Phi(); - int truth_pid = g4particle->get_pid(); - - if (Verbosity() > 10) - { - std::cout << "DetermineTowerBackground::process_event: determining truth flow, using particle w/ pt / eta / phi " << truth_pt << " / " << truth_eta << " / " << truth_phi << " , embed / PID = " << truthinfo->isEmbeded(g4particle->get_track_id()) << " / " << truth_pid << std::endl; - } - - Hijing_Qx += truth_pt * std::cos(2 * truth_phi); - Hijing_Qy += truth_pt * std::sin(2 * truth_phi); - } - - _Psi2 = std::atan2(Hijing_Qy, Hijing_Qx) / 2.0; - - if (Verbosity() > 0) - { - std::cout << "DetermineTowerBackground::process_event: flow extracted from Hijing truth particles, setting Psi2 = " << _Psi2 << " ( " << _Psi2 / M_PI << " * pi ) " << std::endl; - } - } - else if (_do_flow == 3) - { // sEPD event plane extraction - // get event plane map - EventplaneinfoMap *epmap = findNode::getClass(topNode, "EventplaneinfoMap"); - if (!epmap) - { - std::cout << "DetermineTowerBackground::process_event: FATAL, EventplaneinfoMap does not exist, cannot extract sEPD flow with do_flow = " << _do_flow << std::endl; - exit(-1); - } - if (!(epmap->empty())) - { - auto *EPDNS = epmap->get(EventplaneinfoMap::sEPDNS); - _Psi2 = EPDNS->get_shifted_psi(2); - } - else - { - _is_flow_failure = true; - _Psi2 = 0; - } - - if (Verbosity() > 0) - { - std::cout << "DetermineTowerBackground::process_event: flow extracted from sEPD, setting Psi2 = " << _Psi2 << " ( " << _Psi2 / M_PI << " * pi ) " << std::endl; - } - - } if (std::isnan(_Psi2) || std::isinf(_Psi2)) { @@ -890,7 +956,30 @@ int DetermineTowerBackground::process_event(PHCompositeNode *topNode) std::cout << "DetermineTowerBackground::process_event: flow extraction successful, Psi2 = " << _Psi2 << " ( " << _Psi2 / M_PI << " * pi ) , v2 = " << _v2 << std::endl; } } // if do flow + else if (_do_flow == 4) + { + CentralityInfo *centinfo = findNode::getClass(topNode, "CentralityInfo"); + + if (!centinfo) + { + std::cout << "DetermineTowerBackground::process_event: FATAL, CentralityInfo does not exist, cannot extract centrality with do_flow = " << _do_flow << std::endl; + exit(-1); + } + + int centrality_bin = centinfo->get_centrality_bin(CentralityInfo::PROP::mbd_NS); + + if (centrality_bin > 0 && centrality_bin < 95) + { + _v2 = _CENTRALITY_V2[centrality_bin]; + } + else + { + _v2 = 0; + _is_flow_failure = true; + _Psi2 = 0; + } + } // now calculate energy densities... _nTowers = 0; // store how many towers were used to determine bkg diff --git a/offline/packages/jetbackground/DetermineTowerBackground.h b/offline/packages/jetbackground/DetermineTowerBackground.h index a8a6d0209c..ed9e34bf9a 100644 --- a/offline/packages/jetbackground/DetermineTowerBackground.h +++ b/offline/packages/jetbackground/DetermineTowerBackground.h @@ -13,6 +13,7 @@ #include #include #include +#include // forward declarations class PHCompositeNode; @@ -37,7 +38,11 @@ class DetermineTowerBackground : public SubsysReco void SetBackgroundOutputName(const std::string &name) { _backgroundName = name; } void SetSeedType(int seed_type) { _seed_type = seed_type; } void SetFlow(int do_flow) { _do_flow = do_flow; }; - + void SetOverwriteCaloV2(std::string &url) + { + m_overwrite_average_calo_v2 = true; + m_overwrite_average_calo_v2_path = url; + } void SetSeedJetD(float D) { _seed_jet_D = D; }; void SetSeedJetPt(float pt) { _seed_jet_pt = pt; }; void SetSeedMaxConst(float max_const) { _seed_max_const = max_const; }; @@ -55,6 +60,13 @@ class DetermineTowerBackground : public SubsysReco int CreateNode(PHCompositeNode *topNode); void FillNode(PHCompositeNode *topNode); + int LoadCalibrations(); + + std::vector _CENTRALITY_V2; + std::string m_calibName = "JET_AVERAGE_CALO_V2_SEPD_PSI2"; + bool m_overwrite_average_calo_v2{false}; + std::string m_overwrite_average_calo_v2_path; + int _do_flow{0}; float _v2{0}; float _Psi2{0}; diff --git a/offline/packages/jetbackground/Makefile.am b/offline/packages/jetbackground/Makefile.am index 6fe9740a4e..ad45676fbe 100644 --- a/offline/packages/jetbackground/Makefile.am +++ b/offline/packages/jetbackground/Makefile.am @@ -24,6 +24,8 @@ libjetbackground_la_LDFLAGS = \ libjetbackground_la_LIBADD = \ libjetbackground_io.la \ -lcalo_io \ + -lcentrality_io \ + -lcdbobjects \ -lConstituentSubtractor \ -leventplaneinfo_io \ -lglobalvertex \ @@ -33,6 +35,7 @@ libjetbackground_la_LIBADD = \ -lphg4hit \ -lphparameter \ -lqautils \ + -lffamodules \ -lSubsysReco pkginclude_HEADERS = \ diff --git a/offline/packages/jetbackground/RetowerCEMC.cc b/offline/packages/jetbackground/RetowerCEMC.cc index 6125052a23..f9afbad6dd 100644 --- a/offline/packages/jetbackground/RetowerCEMC.cc +++ b/offline/packages/jetbackground/RetowerCEMC.cc @@ -86,7 +86,7 @@ int RetowerCEMC::process_event(PHCompositeNode *topNode) int iphi = towerinfosEM3->getTowerPhiBin(channelkey); rawtower_e[ieta][iphi] = tower->get_energy(); rawtower_time[ieta][iphi] = tower->get_time(); - rawtower_status[ieta][iphi] = tower->get_isHot() || tower->get_isNoCalib() || tower->get_isNotInstr() || tower->get_isBadChi2(); + rawtower_status[ieta][iphi] = !tower->get_isGood(); } EMRetowerName = m_towerNodePrefix + "_CEMC_RETOWER"; TowerInfoContainer *emcal_retower = findNode::getClass(topNode, EMRetowerName); diff --git a/offline/packages/jetbackground/SubtractTowers.cc b/offline/packages/jetbackground/SubtractTowers.cc index 3d0ee5532e..1c6c51a0db 100644 --- a/offline/packages/jetbackground/SubtractTowers.cc +++ b/offline/packages/jetbackground/SubtractTowers.cc @@ -166,7 +166,7 @@ int SubtractTowers::process_event(PHCompositeNode *topNode) } float new_energy = raw_energy - UE; // if a tower is masked, leave it at zero - if (tower->get_isHot() || tower->get_isNoCalib() || tower->get_isNotInstr() || tower->get_isBadChi2()) + if (!tower->get_isGood()) { new_energy = 0; } @@ -259,7 +259,7 @@ int SubtractTowers::process_event(PHCompositeNode *topNode) } float new_energy = raw_energy - UE; // if a tower is masked, leave it at zero - if (tower->get_isHot() || tower->get_isNoCalib() || tower->get_isNotInstr() || tower->get_isBadChi2()) + if (!tower->get_isGood()) { new_energy = 0; } @@ -348,7 +348,7 @@ int SubtractTowers::process_event(PHCompositeNode *topNode) } float new_energy = raw_energy - UE; // if a tower is masked, leave it at zero - if (tower->get_isHot() || tower->get_isNoCalib() || tower->get_isNotInstr() || tower->get_isBadChi2()) + if (!tower->get_isGood()) { new_energy = 0; } diff --git a/offline/packages/jetbackground/TimingCut.cc b/offline/packages/jetbackground/TimingCut.cc index 69ab008124..41d8dc571d 100644 --- a/offline/packages/jetbackground/TimingCut.cc +++ b/offline/packages/jetbackground/TimingCut.cc @@ -12,21 +12,36 @@ #include #include +#include // for CDBTF1 + +#include +#include +#include #include #include // for basic_ostream, operator<< #include // for _Rb_tree_iterator, opera... #include // for pair #include // for vector //____________________________________________________________________________.. -TimingCut::TimingCut(const std::string &jetNodeName, const std::string &name, const bool doAbort) +TimingCut::TimingCut(const std::string &jetNodeName, const std::string &name, const bool doAbort, const std::string &ohTowerName) : SubsysReco(name) , _doAbort(doAbort) , _jetNodeName(jetNodeName) + , _ohTowerName(ohTowerName) , _cutParams(name) { SetDefaultParams(); } +TimingCut::~TimingCut() +{ + if(_fitFunc) + { + delete _fitFunc; + _fitFunc = nullptr; + } +} + //____________________________________________________________________________.. int TimingCut::Init(PHCompositeNode *topNode) { @@ -35,6 +50,26 @@ int TimingCut::Init(PHCompositeNode *topNode) return Fun4AllReturnCodes::ABORTRUN; } + std::string fitUrl = CDBInterface::instance()->getUrl("OHCAL_JET_TIME_FRACTION"); + if(!fitUrl.empty()) + { + CDBTF* fitFile = new CDBTF(fitUrl); + fitFile->LoadCalibrations(); + TF1* tmp = fitFile->getTF("JET_TIMING_CALO_FRACTION_CALIB_fullrange"); + if(!tmp) + { + std::cout << "ERROR: NO CALIBRATION TF1 FOUND FOR TIMING CUT OHCAL FRACTION CORRECTION! This should never happen. ABORT RUN!" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + _fitFunc = (TF1*)tmp->Clone(); + delete fitFile; + } + else + { + std::cout << "ERROR: NO CALIBRATION FILE FOUND FOR TIMING CUT OHCAL FRACTION CORRECTION! ABORT RUN!" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + return Fun4AllReturnCodes::EVENT_OK; } @@ -57,11 +92,12 @@ int TimingCut::CreateNodeTree(PHCompositeNode *topNode) int TimingCut::process_event(PHCompositeNode *topNode) { JetContainer *jets = findNode::getClass(topNode, _jetNodeName); - if (!jets) + TowerInfoContainer* towersOH = findNode::getClass(topNode, _ohTowerName); + if (!jets || !towersOH) { if (Verbosity() > 0 && !_missingInfoWarningPrinted) { - std::cout << "Missing jets; abort event. Further warnings will be suppressed." << std::endl; + std::cout << "Missing jets or OHCal towers; abort event. Further warnings will be suppressed." << std::endl; } _missingInfoWarningPrinted = true; return Fun4AllReturnCodes::ABORTEVENT; @@ -69,6 +105,8 @@ int TimingCut::process_event(PHCompositeNode *topNode) float maxJetpT = 0; float subJetpT = 0; + float maxJetOHFrac = std::numeric_limits::quiet_NaN(); + float subJetOHFrac = std::numeric_limits::quiet_NaN(); float maxJett = std::numeric_limits::quiet_NaN(); float subJett = std::numeric_limits::quiet_NaN(); float maxJetPhi = std::numeric_limits::quiet_NaN(); @@ -86,12 +124,36 @@ int TimingCut::process_event(PHCompositeNode *topNode) float jetpT = 0; float jett = std::numeric_limits::quiet_NaN(); float jetPhi = std::numeric_limits::quiet_NaN(); + float jetOHFrac = 0; Jet *jet = jets->get_jet(i); if (jet) { jetpT = jet->get_pt(); jett = jet->get_property(Jet::PROPERTY::prop_t); jetPhi = jet->get_phi(); + for(auto comp: jet->get_comp_vec()) + { + if(comp.first == 7 || comp.first == 27) + { + unsigned int channel = comp.second; + TowerInfo* tower = towersOH->get_tower_at_channel(channel); + if(!tower) + { + std::cout << "Component tower missing! This should not happen (something is wrong, check your inputs). Abort event!" << std::endl; + return Fun4AllReturnCodes::ABORTEVENT; + } + jetOHFrac += tower->get_energy(); + } + } + float jetE = jet->get_e(); + if(jetE == 0) + { + jetOHFrac = std::numeric_limits::quiet_NaN(); + } + else + { + jetOHFrac /= jetE; + } } else { @@ -104,16 +166,19 @@ int TimingCut::process_event(PHCompositeNode *topNode) subJetpT = maxJetpT; subJett = maxJett; subJetPhi = maxJetPhi; + subJetOHFrac = maxJetOHFrac; } maxJetpT = jetpT; maxJett = jett; maxJetPhi = jetPhi; + maxJetOHFrac = jetOHFrac; } else if (jetpT > subJetpT) { subJetpT = jetpT; subJett = jett; subJetPhi = jetPhi; + subJetOHFrac = jetOHFrac; } } } @@ -126,8 +191,23 @@ int TimingCut::process_event(PHCompositeNode *topNode) return Fun4AllReturnCodes::ABORTEVENT; } - bool passDeltat = Pass_Delta_t(maxJett, subJett, maxJetPhi, subJetPhi); - bool passLeadt = Pass_Lead_t(maxJett); + if(!std::isfinite(maxJetOHFrac) || !std::isfinite(subJetOHFrac)) + { + if(Verbosity() > 1) + { + std::cout << "Warning: bad OH fraction for leading or subleading jet; this event will automatically fail cuts." << std::endl; + } + maxJetOHFrac = std::numeric_limits::quiet_NaN(); + subJetOHFrac = std::numeric_limits::quiet_NaN(); + } + + float corrMaxJett = Correct_Time_Ohfrac(maxJett, maxJetOHFrac); //likewise, intentional NaNs here. + float corrSubJett = Correct_Time_Ohfrac(subJett, subJetOHFrac); + + + + bool passDeltat = Pass_Delta_t(corrMaxJett, corrSubJett, maxJetPhi, subJetPhi); + bool passLeadt = Pass_Lead_t(corrMaxJett); MbdOut * mbdout = static_cast(findNode::getClass(topNode,"MbdOut")); float m_mbd_t0 = std::numeric_limits::quiet_NaN(); @@ -157,10 +237,10 @@ int TimingCut::process_event(PHCompositeNode *topNode) bool passMbdt = false; if(!std::isnan(mbd_time)) { - passMbdt = Pass_Mbd_dt(maxJett, mbd_time); + passMbdt = Pass_Mbd_dt(corrMaxJett, mbd_time); } - bool failAnyCut = !passDeltat || !passLeadt || !passMbdt; + bool failAnyCut = !passDeltat || !passLeadt || (!passMbdt && _abortFailMbd); if (failAnyCut && _doAbort) { @@ -174,7 +254,11 @@ int TimingCut::process_event(PHCompositeNode *topNode) _cutParams.set_int_param("failAnyTimeCut", failAnyCut); _cutParams.set_double_param("maxJett",maxJett); _cutParams.set_double_param("subJett",subJett); + _cutParams.set_double_param("corrMaxJett",corrMaxJett); + _cutParams.set_double_param("corrSubJett",corrSubJett); _cutParams.set_double_param("mbd_time",mbd_time); + _cutParams.set_double_param("leadOhFrac",maxJetOHFrac); + _cutParams.set_double_param("subOhFrac",subJetOHFrac); _cutParams.set_double_param("dPhi",calc_dphi(maxJetPhi, subJetPhi)); _cutParams.UpdateNodeTree(parNode, "TimingCutParams"); diff --git a/offline/packages/jetbackground/TimingCut.h b/offline/packages/jetbackground/TimingCut.h index 2e426a82da..a6c56433e8 100644 --- a/offline/packages/jetbackground/TimingCut.h +++ b/offline/packages/jetbackground/TimingCut.h @@ -7,40 +7,22 @@ #include + +#include +#include #include #include +#include +class CDBTF; class PHCompositeNode; class TimingCut : public SubsysReco { public: - explicit TimingCut(const std::string &jetNodeName, const std::string &name = "TimingCutModule", bool doAbort = false); - - ~TimingCut() override = default; + explicit TimingCut(const std::string &jetNodeName, const std::string &name = "TimingCutModule", bool doAbort = false, const std::string &ohTowerName = "TOWERINFO_CALIB_HCALOUT"); - float calc_dphi(float maxJetPhi, float subJetPhi) - { - float dPhi = std::abs(maxJetPhi - subJetPhi); - if(dPhi>M_PI) dPhi -= M_PI; - return dPhi; - } - - bool Pass_Delta_t(float lead_time, float sub_time, float maxJetPhi, float subJetPhi) - { - float dPhi = calc_dphi(maxJetPhi, subJetPhi); - return (std::abs(lead_time - sub_time) < _dt_width && dPhi > _min_dphi); - } - - bool Pass_Lead_t(float lead_time) - { - return std::abs(lead_time + _t_shift) < _t_width; - } - - bool Pass_Mbd_dt(float lead_time, float mbd_time) - { - return std::abs(lead_time - mbd_time) < _mbd_dt_width; - } + ~TimingCut() override; void set_t_shift(float new_shift) { _t_shift = new_shift; } float get_t_shift() { return _t_shift; } @@ -57,6 +39,9 @@ class TimingCut : public SubsysReco void set_min_dphi(float new_min_dphi) { _min_dphi = new_min_dphi; } float get_min_dphi() { return _min_dphi; } + void set_abortFailMbd(bool abortFailMbd) { _abortFailMbd = abortFailMbd; } + bool get_abortFailMbd() { return _abortFailMbd; } + int Init(PHCompositeNode *topNode) override; int process_event(PHCompositeNode *topNode) override; @@ -76,23 +61,69 @@ class TimingCut : public SubsysReco _cutParams.set_int_param("passLeadtCut", 0); _cutParams.set_int_param("passDeltatCut", 0); _cutParams.set_int_param("passMbdDtCut", 0); - _cutParams.set_int_param("failAnyTimeCut",0); + _cutParams.set_int_param("failAnyTimeCut",1); _cutParams.set_double_param("maxJett",9999); _cutParams.set_double_param("subJett",9999); _cutParams.set_double_param("mbd_time",9999); _cutParams.set_double_param("dPhi",9999); + _cutParams.set_double_param("leadOhFrac",-1); + _cutParams.set_double_param("subOhFrac",-1); + _cutParams.set_double_param("corrMaxJett",9999); + _cutParams.set_double_param("corrSubJett",9999); + } private: + + float Correct_Time_Ohfrac(float t, float ohfrac) + { + if(!_fitFunc) + { + if(Verbosity() > 0) + { + std::cout << "ERROR: mising fit function. All events will fail!" << std::endl; + } + return std::numeric_limits::quiet_NaN(); + } + float corrt = t - _fitFunc->Eval(ohfrac); + return corrt; + } + + float calc_dphi(float maxJetPhi, float subJetPhi) + { + float dPhi = std::abs(maxJetPhi - subJetPhi); + if(dPhi>M_PI) dPhi = 2*M_PI - dPhi; + return dPhi; + } + + bool Pass_Delta_t(float lead_time, float sub_time, float maxJetPhi, float subJetPhi) + { + float dPhi = calc_dphi(maxJetPhi, subJetPhi); + return (std::abs(lead_time - sub_time) < _dt_width && dPhi > _min_dphi); + } + + bool Pass_Lead_t(float lead_time) + { + return std::abs(lead_time + _t_shift) < _t_width; + } + + bool Pass_Mbd_dt(float lead_time, float mbd_time) + { + return std::abs(lead_time - mbd_time) < _mbd_dt_width; + } + bool _doAbort; + bool _abortFailMbd = false; bool _missingInfoWarningPrinted = false; std::string _jetNodeName; + std::string _ohTowerName; PHParameters _cutParams; float _t_width{6.0}; float _dt_width{3.0}; - float _t_shift{2.0}; + float _t_shift{0.0}; float _mbd_dt_width{3.0}; float _min_dphi{3*M_PI/4}; + TF1* _fitFunc{nullptr}; }; #endif diff --git a/offline/packages/jetbase/JetCalib.cc b/offline/packages/jetbase/JetCalib.cc index cc2fdd11b9..a6c9b8cf4d 100644 --- a/offline/packages/jetbase/JetCalib.cc +++ b/offline/packages/jetbase/JetCalib.cc @@ -244,6 +244,7 @@ int JetCalib::process_event(PHCompositeNode *topNode) calib_jet->set_py(calib_pt * std::sin(phi)); calib_jet->set_pz(calib_pt * std::sinh(eta)); calib_jet->set_id(ijet); + calib_jet->insert_comp(jet->get_comp_vec(), true); calib_jet->set_isCalib(1); ijet++; } diff --git a/offline/packages/jetbase/TowerJetInput.cc b/offline/packages/jetbase/TowerJetInput.cc index f58249ad04..ca2af6ba3d 100644 --- a/offline/packages/jetbase/TowerJetInput.cc +++ b/offline/packages/jetbase/TowerJetInput.cc @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include @@ -471,7 +471,7 @@ std::vector TowerJetInput::get_input(PHCompositeNode *topNode) int iphi = towerinfos->getTowerPhiBin(calokey); const RawTowerDefs::keytype key = RawTowerDefs::encode_towerid(geocaloid, ieta, iphi); // skip masked towers - if (tower->get_isHot() || tower->get_isNoCalib() || tower->get_isNotInstr() || tower->get_isBadChi2()) + if (!tower->get_isGood()) { continue; } diff --git a/offline/packages/mbd/Makefile.am b/offline/packages/mbd/Makefile.am index 111f9b31df..be588c0adb 100644 --- a/offline/packages/mbd/Makefile.am +++ b/offline/packages/mbd/Makefile.am @@ -49,8 +49,10 @@ pkginclude_HEADERS = \ MbdPmtHitV1.h \ MbdRawContainer.h \ MbdRawContainerV1.h \ + MbdRawContainerV2.h \ MbdRawHit.h \ MbdRawHitV1.h \ + MbdRawHitV2.h \ MbdReturnCodes.h \ MbdRunningStats.h \ MbdCalib.h \ @@ -70,8 +72,10 @@ pkginclude_HEADERS = \ MbdPmtSimHitV1.h \ MbdRawContainer.h \ MbdRawContainerV1.h \ + MbdRawContainerV2.h \ MbdRawHit.h \ MbdRawHitV1.h \ + MbdRawHitV2.h \ MbdRunningStats.h \ MbdSig.h \ MbdEvent.h \ @@ -97,8 +101,10 @@ ROOTDICTS = \ MbdPmtHitV1_Dict.cc \ MbdRawContainer_Dict.cc \ MbdRawContainerV1_Dict.cc \ + MbdRawContainerV2_Dict.cc \ MbdRawHit_Dict.cc \ - MbdRawHitV1_Dict.cc + MbdRawHitV1_Dict.cc \ + MbdRawHitV2_Dict.cc else ROOTDICTS = \ @@ -116,8 +122,10 @@ ROOTDICTS = \ MbdPmtSimContainerV1_Dict.cc \ MbdRawHit_Dict.cc \ MbdRawHitV1_Dict.cc \ + MbdRawHitV2_Dict.cc \ MbdRawContainer_Dict.cc \ - MbdRawContainerV1_Dict.cc + MbdRawContainerV1_Dict.cc \ + MbdRawContainerV2_Dict.cc endif pcmdir = $(libdir) @@ -138,8 +146,10 @@ libmbd_io_la_SOURCES = \ MbdPmtContainerV1.cc \ MbdRawHit.cc \ MbdRawHitV1.cc \ + MbdRawHitV2.cc \ MbdRawContainer.cc \ MbdRawContainerV1.cc \ + MbdRawContainerV2.cc \ MbdRunningStats.cc \ MbdCalib.cc \ MbdSig.cc @@ -160,8 +170,10 @@ libmbd_io_la_SOURCES = \ MbdPmtSimContainerV1.cc \ MbdRawHit.cc \ MbdRawHitV1.cc \ + MbdRawHitV2.cc \ MbdRawContainer.cc \ MbdRawContainerV1.cc \ + MbdRawContainerV2.cc \ MbdRunningStats.cc \ MbdSig.cc diff --git a/offline/packages/mbd/MbdCalib.cc b/offline/packages/mbd/MbdCalib.cc index 22b1e9930d..82d87b7671 100644 --- a/offline/packages/mbd/MbdCalib.cc +++ b/offline/packages/mbd/MbdCalib.cc @@ -79,15 +79,28 @@ int MbdCalib::Download_All() // if rc flag MBD_CALDIR does not exist, we create it and set it to an empty string if (!_rc->FlagExist("MBD_CALDIR")) { - std::string sampmax_url = _cdb->getUrl("MBD_SAMPMAX"); + // Always load Status + std::string status_url = _cdb->getUrl("MBD_STATUS"); + if ( ! status_url.empty() ) + { + // if this doesn't exist, the status is assumed to be all good + Download_Status(status_url); + } if (Verbosity() > 0) { - std::cout << "sampmax_url " << sampmax_url << std::endl; + std::cout << "status_url " << status_url << std::endl; } - Download_SampMax(sampmax_url); if ( !_rawdstflag ) { + // sampmax and ped will be calculated on the fly if calibs don't exist + std::string sampmax_url = _cdb->getUrl("MBD_SAMPMAX"); + if (Verbosity() > 0) + { + std::cout << "sampmax_url " << sampmax_url << std::endl; + } + Download_SampMax(sampmax_url); + std::string ped_url = _cdb->getUrl("MBD_PED"); if (Verbosity() > 0) { @@ -95,8 +108,12 @@ int MbdCalib::Download_All() } Download_Ped(ped_url); - std::string pileup_url = _cdb->getUrl("MBD_PILEUP"); + if ( pileup_url.empty() ) + { + std::cerr << "ERROR, MBD_PILEUP missing" << std::endl; + return -1; + } if (Verbosity() > 0) { std::cout << "pileup_url " << pileup_url << std::endl; @@ -106,6 +123,11 @@ int MbdCalib::Download_All() if (do_templatefit) { std::string shape_url = _cdb->getUrl("MBD_SHAPES"); + if ( shape_url.empty() ) + { + std::cerr << "ERROR, MBD_SHAPES missing" << std::endl; + return -1; + } if (Verbosity() > 0) { std::cout << "shape_url " << shape_url << std::endl; @@ -114,29 +136,29 @@ int MbdCalib::Download_All() } } - std::string qfit_url = _cdb->getUrl("MBD_QFIT"); - if (Verbosity() > 0) + if ( !_fitsonly ) { - std::cout << "qfit_url " << qfit_url << std::endl; - } - Download_Gains(qfit_url); + std::string qfit_url = _cdb->getUrl("MBD_QFIT"); + if (Verbosity() > 0) + { + std::cout << "qfit_url " << qfit_url << std::endl; + } + Download_Gains(qfit_url); - std::string tt_t0_url = _cdb->getUrl("MBD_TT_T0"); - if ( Verbosity() > 0 ) - { - std::cout << "tt_t0_url " << tt_t0_url << std::endl; - } - Download_TTT0(tt_t0_url); + std::string tt_t0_url = _cdb->getUrl("MBD_TT_T0"); + if ( Verbosity() > 0 ) + { + std::cout << "tt_t0_url " << tt_t0_url << std::endl; + } + Download_TTT0(tt_t0_url); - std::string tq_t0_url = _cdb->getUrl("MBD_TQ_T0"); - if (Verbosity() > 0) - { - std::cout << "tq_t0_url " << tq_t0_url << std::endl; - } - Download_TQT0(tq_t0_url); + std::string tq_t0_url = _cdb->getUrl("MBD_TQ_T0"); + if (Verbosity() > 0) + { + std::cout << "tq_t0_url " << tq_t0_url << std::endl; + } + Download_TQT0(tq_t0_url); - if ( !_fitsonly ) - { std::string t0corr_url = _cdb->getUrl("MBD_T0CORR"); if ( Verbosity() > 0 ) { @@ -176,6 +198,9 @@ int MbdCalib::Download_All() std::string sampmax_file = bbc_caldir + "/mbd_sampmax.calib"; Download_SampMax(sampmax_file); + std::string status_file = bbc_caldir + "/mbd_status.calib"; + Download_Status(status_file); + if ( !_rawdstflag ) { std::string ped_file = bbc_caldir + "/mbd_ped.calib"; @@ -617,8 +642,6 @@ int MbdCalib::Download_Ped(const std::string& dbase_location) if ( std::isnan(_pedmean[0]) ) { std::cout << PHWHERE << ", WARNING, ped calib missing, " << dbase_location << std::endl; - _status = -1; - return _status; } return 1; @@ -681,6 +704,74 @@ int MbdCalib::Download_SampMax(const std::string& dbase_location) if ( _sampmax[0] == -1 ) { std::cout << PHWHERE << ", WARNING, sampmax calib missing, " << dbase_location << std::endl; + } + + return 1; +} + +int MbdCalib::Download_Status(const std::string& dbase_location) +{ + // Reset All Values + _mbdstatus.fill(-1); + + TString dbase_file = dbase_location; + +#ifndef ONLINE + if (dbase_file.EndsWith(".root")) // read from database + { + CDBTTree* cdbttree = new CDBTTree(dbase_location); + cdbttree->LoadCalibrations(); + + for (int ifeech = 0; ifeech < MbdDefs::MBD_N_FEECH; ifeech++) + { + _mbdstatus[ifeech] = cdbttree->GetIntValue(ifeech, "status"); + if (Verbosity() > 0) + { + if (ifeech < 5 || ifeech >= MbdDefs::MBD_N_FEECH - 5) + { + std::cout << ifeech << "\t" << _mbdstatus[ifeech] << std::endl; + } + } + } + delete cdbttree; + } +#endif + + if (dbase_file.EndsWith(".calib")) // read from text file + { + std::ifstream infile(dbase_location); + if (!infile.is_open()) + { + std::cout << PHWHERE << "unable to open " << dbase_location << std::endl; + _status = -3; + return _status; + } + + int feech = -1; + while (infile >> feech) + { + if (feech < 0 || feech >= MbdDefs::MBD_N_FEECH) + { + std::cout << "ERROR, invalid FEECH " << feech << " in MBD status calibration" << std::endl; + _status = -4; + return _status; + } + infile >> _mbdstatus[feech]; + if (Verbosity() > 0) + { + if (feech < 5 || feech >= MbdDefs::MBD_N_FEECH - 5) + { + std::cout << "status\t" << feech << "\t" << _mbdstatus[feech] << std::endl; + } + } + } + infile.close(); + } + + + if ( _mbdstatus[0] == -1 ) + { + std::cout << PHWHERE << ", WARNING, status calib seems bad, " << dbase_location << std::endl; _status = -1; return _status; // file not found } @@ -1225,7 +1316,6 @@ int MbdCalib::Download_TimeRMS(const std::string& dbase_location) trms.clear(); } std::fill(_trms_npts.begin(), _trms_npts.end(), 0); - TString dbase_file = dbase_location; #ifndef ONLINE @@ -1331,9 +1421,10 @@ int MbdCalib::Download_TimeRMS(const std::string& dbase_location) if ( _trms_y[0].empty() ) { - std::cout << PHWHERE << ", ERROR, unknown file type, " << dbase_location << std::endl; - _status = -1; - return _status; // file not found + std::cout << PHWHERE << ", WARNING, trms calib missing " << dbase_location << std::endl; +// _status = -1; +// return _status; // file not found + return 0; } // Now we interpolate the trms @@ -1450,7 +1541,7 @@ int MbdCalib::Download_Pileup(const std::string& dbase_location) if (Verbosity() > 0) { - if (feech < 2 || feech >= MbdDefs::MBD_N_PMT - 2) + if (feech < 2 || feech >= MbdDefs::MBD_N_FEECH - 2) { std::cout << feech << "\t" << _pileup_p0[feech] << "\t" << _pileup_p0err[feech] << "\t" << _pileup_p1[feech] << "\t" << _pileup_p1err[feech] @@ -1591,6 +1682,52 @@ int MbdCalib::Write_SampMax(const std::string& dbfile) return 1; } +#ifndef ONLINE +int MbdCalib::Write_CDB_Status(const std::string& dbfile) +{ + CDBTTree* cdbttree{ nullptr }; + + std::cout << "Creating " << dbfile << std::endl; + cdbttree = new CDBTTree( dbfile ); + cdbttree->SetSingleIntValue("version", 1); + cdbttree->CommitSingle(); + + std::cout << "STATUS" << std::endl; + for (size_t ifeech = 0; ifeech < _mbdstatus.size(); ifeech++) + { + // store in a CDBTree + cdbttree->SetIntValue(ifeech, "status", _mbdstatus[ifeech]); + + if (ifeech < 12 || ifeech >= MbdDefs::MBD_N_FEECH - 5) + { + std::cout << ifeech << "\t" << cdbttree->GetIntValue(ifeech, "status") << std::endl; + } + } + + cdbttree->Commit(); + // cdbttree->Print(); + + // for now we create the tree after reading it + cdbttree->WriteCDBTTree(); + delete cdbttree; + + return 1; +} +#endif + +int MbdCalib::Write_Status(const std::string& dbfile) +{ + std::ofstream cal_file; + cal_file.open(dbfile); + for (int ifeech = 0; ifeech < MbdDefs::MBD_N_FEECH; ifeech++) + { + cal_file << ifeech << "\t" << _mbdstatus[ifeech] << std::endl; + } + cal_file.close(); + + return 1; +} + #ifndef ONLINE int MbdCalib::Write_CDB_TTT0(const std::string& dbfile) { @@ -1930,6 +2067,40 @@ int MbdCalib::Write_CDB_TimeCorr(const std::string& dbfile) } #endif +int MbdCalib::Write_TimeCorr(const std::string& dbfile) +{ + std::ofstream cal_timecorr_file; + cal_timecorr_file.open(dbfile); + if (!cal_timecorr_file.is_open()) + { + std::cout << PHWHERE << "unable to open " << dbfile << std::endl; + return -1; + } + for (int ifeech = 0; ifeech < MbdDefs::MBD_N_FEECH; ifeech++) + { + if ( _mbdgeom->get_type(ifeech) == 1 ) + { + continue; // skip q-channels + } + cal_timecorr_file << ifeech << "\t" << _tcorr_npts[ifeech] << "\t" << _tcorr_minrange[ifeech] << "\t" << _tcorr_maxrange[ifeech] << std::endl; + for (int ipt=0; ipt<_tcorr_npts[ifeech]; ipt++) + { + cal_timecorr_file << _tcorr_y[ifeech][ipt]; + if ( ipt%10 == 9 ) + { + cal_timecorr_file << std::endl; + } + else + { + cal_timecorr_file << " "; + } + } + } + cal_timecorr_file.close(); + + return 1; +} + #ifndef ONLINE int MbdCalib::Write_CDB_SlewCorr(const std::string& dbfile) { @@ -2327,7 +2498,7 @@ void MbdCalib::Reset_Pileup() _pileup_p0err.fill(std::numeric_limits::quiet_NaN()); _pileup_p1err.fill(std::numeric_limits::quiet_NaN()); _pileup_p2err.fill(std::numeric_limits::quiet_NaN()); - _qfit_chi2ndf.fill(std::numeric_limits::quiet_NaN()); + _pileup_chi2ndf.fill(std::numeric_limits::quiet_NaN()); } void MbdCalib::Reset_Thresholds() @@ -2353,6 +2524,7 @@ void MbdCalib::Reset() Reset_Thresholds(); _sampmax.fill(-1); + _mbdstatus.fill(0); } void MbdCalib::set_ped(const int ifeech, const float m, const float merr, const float s, const float serr) @@ -2419,3 +2591,31 @@ TGraph *MbdCalib::get_lut_graph(const int pmtch, std::string_view type) return g; } + +void MbdCalib::set_pileup(const int ifeech, const int ipar, const float pval) +{ + int chtype = (ifeech / 8) % 2; // 0=T-ch, 1=Q-ch + + if (ipar==0) + { + _pileup_p0[ifeech] = pval; + } + else if (ipar==1) + { + _pileup_p1[ifeech] = pval; + } + else if (ipar==2) + { + _pileup_p2[ifeech] = pval; + } + else if (ipar==3 && chtype==0) + { + _pileup_p1err[ifeech] = pval; + } + else if (ipar==4 && chtype==0) + { + _pileup_p2err[ifeech] = pval; + } +} + + diff --git a/offline/packages/mbd/MbdCalib.h b/offline/packages/mbd/MbdCalib.h index 6d7208f631..65b5a52fee 100644 --- a/offline/packages/mbd/MbdCalib.h +++ b/offline/packages/mbd/MbdCalib.h @@ -35,8 +35,41 @@ class MbdCalib float get_tq0(const int ipmt) const { return _tqfit_t0mean[ipmt]; } float get_t0corr() const { return _t0corrmean; } float get_ped(const int ifeech) const { return _pedmean[ifeech]; } + float get_pederr(const int ifeech) const { return _pedmeanerr[ifeech]; } float get_pedrms(const int ifeech) const { return _pedsigma[ifeech]; } + float get_pedrmserr(const int ifeech) const { return _pedsigmaerr[ifeech]; } int get_sampmax(const int ifeech) const { return _sampmax[ifeech]; } + int get_status(const int ifeech) const { return _mbdstatus[ifeech]; } + + float get_pileup(const int ifeech, const int ipar) const + { + int chtype = (ifeech / 8) % 2; // 0=T-ch, 1=Q-ch + + if (ipar==0) + { + return _pileup_p0[ifeech]; + } + else if (ipar==1) + { + return _pileup_p1[ifeech]; + } + else if (ipar==2) + { + return _pileup_p2[ifeech]; + } + else if (ipar==3 && chtype==0) + { + return _pileup_p1err[ifeech]; + } + else if (ipar==4 && chtype==0) + { + return _pileup_p2err[ifeech]; + } + + return std::numeric_limits::quiet_NaN(); + } + + float get_tcorr(const int ifeech, const int tdc) const { if (tdc<0) { @@ -85,30 +118,14 @@ class MbdCalib std::vector get_shape(const int ifeech) const { return _shape_y[ifeech]; } std::vector get_sherr(const int ifeech) const { return _sherr_yerr[ifeech]; } - float get_pileup(const int ifeech, const int ipar) const { - - if (ipar==0) - { - return _pileup_p0[ifeech]; - } - else if (ipar==1) - { - return _pileup_p1[ifeech]; - } - else if (ipar==2) - { - return _pileup_p2[ifeech]; - } - - return std::numeric_limits::quiet_NaN(); - } - float get_threshold(const int pmtch, const int rel_or_abs = 0); TGraph *get_lut_graph(const int pmtch, std::string_view type); void set_sampmax(const int ifeech, const int val) { _sampmax[ifeech] = val; } + void set_status(const int ifeech, const int val) { _mbdstatus[ifeech] = val; } void set_ped(const int ifeech, const float m, const float merr, const float s, const float serr); + void set_pileup(const int ifeech, const int ipar, const float val); void set_tt0(const int ipmt, const float t0) { _ttfit_t0mean[ipmt] = t0; } void set_tq0(const int ipmt, const float t0) { _tqfit_t0mean[ipmt] = t0; } @@ -118,6 +135,7 @@ class MbdCalib int Download_T0Corr(const std::string& dbase_location); int Download_Ped(const std::string& dbase_location); int Download_SampMax(const std::string& dbase_location); + int Download_Status(const std::string& dbase_location); int Download_Shapes(const std::string& dbase_location); int Download_TimeCorr(const std::string& dbase_location); int Download_SlewCorr(const std::string& dbase_location); @@ -128,6 +146,7 @@ class MbdCalib #ifndef ONLINE int Write_CDB_SampMax(const std::string& dbfile); + int Write_CDB_Status(const std::string& dbfile); int Write_CDB_TTT0(const std::string& dbfile); int Write_CDB_TQT0(const std::string& dbfile); int Write_CDB_T0Corr(const std::string& dbfile); @@ -143,10 +162,12 @@ class MbdCalib #endif int Write_SampMax(const std::string& dbfile); + int Write_Status(const std::string& dbfile); int Write_TQT0(const std::string& dbfile); int Write_TTT0(const std::string& dbfile); int Write_T0Corr(const std::string& dbfile); int Write_Ped(const std::string& dbfile); + int Write_TimeCorr(const std::string& dbfile); int Write_Gains(const std::string& dbfile); int Write_Pileup(const std::string& dbfile); int Write_Thresholds(const std::string& dbfile); @@ -231,6 +252,9 @@ class MbdCalib // SampMax (Peak of waveform) std::array _sampmax{}; + // Status (MBD Channel Status) + std::array _mbdstatus{}; + // Pileup waveform correction std::array _pileup_p0{}; std::array _pileup_p0err{}; diff --git a/offline/packages/mbd/MbdEvent.cc b/offline/packages/mbd/MbdEvent.cc index d8c72b4395..b97d750f29 100644 --- a/offline/packages/mbd/MbdEvent.cc +++ b/offline/packages/mbd/MbdEvent.cc @@ -35,6 +35,7 @@ #include #include #include +#include MbdEvent::MbdEvent(const int cal_pass, const bool proc_charge) : _nsamples(MbdDefs::MAX_SAMPLES), @@ -150,10 +151,16 @@ int MbdEvent::InitRun() _mbdcal->SetRawDstFlag( _rawdstflag ); _mbdcal->SetFitsOnly( _fitsonly ); - _mbdcal->Download_All(); if ( _simflag == 0 ) // do following for real data { + // Download calibrations + int status = _mbdcal->Download_All(); + if ( status < 0 && _calpass==0 && _fitsonly ) // only abort for production waveform pass + { + return Fun4AllReturnCodes::ABORTRUN; + } + // load pass1 calibs from local file for calpass2+ if ( _calpass>1 ) { @@ -175,35 +182,36 @@ int MbdEvent::InitRun() _calib_done = 0; std::cout << PHWHERE << ",no sampmax calib, determining it on the fly using first " << _no_sampmax << " evts." << std::endl; } - } - - // Init parameters of the signal processing - for (int ifeech = 0; ifeech < MbdDefs::BBC_N_FEECH; ifeech++) - { - _mbdsig[ifeech].SetCalib(_mbdcal); - // Do evt-by-evt pedestal using sample range below - if ( _calpass==1 || _is_online || _no_sampmax>0 ) - { - _mbdsig[ifeech].SetEventPed0Range(0,1); - } - else + // Init parameters of the signal processing + for (int ifeech = 0; ifeech < MbdDefs::BBC_N_FEECH; ifeech++) { - const int presamp = 5; // start from 5 samples before sampmax - const int nsamps = -1; // use all to sample 0 - _mbdsig[ifeech].SetEventPed0PreSamp(presamp, nsamps, _mbdcal->get_sampmax(ifeech)); - } + _mbdsig[ifeech].SetCalib(_mbdcal); - // Read in template if specified - if ( do_templatefit && _mbdgeom->get_type(ifeech)==1 ) - { - // std::cout << PHWHERE << "Reading template " << ifeech << std::endl; - // std::cout << "SIZES0 " << _mbdcal->get_shape(ifeech).size() << std::endl; - // Should set template size automatically here - _mbdsig[ifeech].SetTemplate(_mbdcal->get_shape(ifeech), _mbdcal->get_sherr(ifeech)); - _mbdsig[ifeech].SetMinMaxFitTime(_mbdcal->get_sampmax(ifeech) - 2 - 3, _mbdcal->get_sampmax(ifeech) - 2 + 3); - //_mbdsig[ifeech].SetMinMaxFitTime( 0, 31 ); + // Do evt-by-evt pedestal using sample range below + if ( _calpass==1 || _is_online || _no_sampmax>0 ) + { + _mbdsig[ifeech].SetEventPed0Range(0,1); + } + else + { + const int presamp = 5; // start from 5 samples before sampmax + const int nsamps = -1; // use all to sample 0 + _mbdsig[ifeech].SetEventPed0PreSamp(presamp, nsamps, _mbdcal->get_sampmax(ifeech)); + } + + // Read in template if specified + if ( do_templatefit && _mbdgeom->get_type(ifeech)==1 ) + { + // std::cout << PHWHERE << "Reading template " << ifeech << std::endl; + // std::cout << "SIZES0 " << _mbdcal->get_shape(ifeech).size() << std::endl; + // Should set template size automatically here + _mbdsig[ifeech].SetTemplate(_mbdcal->get_shape(ifeech), _mbdcal->get_sherr(ifeech)); + _mbdsig[ifeech].SetMinMaxFitTime(_mbdcal->get_sampmax(ifeech) - 2 - 3, _mbdcal->get_sampmax(ifeech) - 2 + 3); + //_mbdsig[ifeech].SetMinMaxFitTime( 0, 31 ); + } } + } if ( _calpass > 0 ) @@ -361,6 +369,24 @@ int MbdEvent::End() orig_dir->cd(); } + // Write out MbdSig eval histograms + if ( _doeval ) + { + TDirectory *orig_dir = gDirectory; + + // _doeval is overloaded with segment_number+1 + std::string savefname = std::format("mbdfiteval_{:08}-{:05}.root",_runnum,_doeval-1); + _evalfile = std::make_unique(savefname.c_str(),"RECREATE"); + + for (auto & sig : _mbdsig) + { + sig.WritePedvsEvent(); + sig.WriteChi2Hist(); + } + + orig_dir->cd(); + } + return 1; } @@ -397,7 +423,13 @@ void MbdEvent::Clear() bool MbdEvent::isbadtch(const int ipmtch) { - return std::fabs(_mbdcal->get_tt0(ipmtch))>100.; + int feech = _mbdgeom->get_feech(ipmtch,0); + if ( _mbdcal->get_status(feech) > 0 ) + { + return true; + } + + return false; } @@ -412,13 +444,18 @@ int MbdEvent::SetRawData(std::array< CaloPacket *,2> &dstp, MbdRawContainer *bbc return Fun4AllReturnCodes::DISCARDEVENT; } + int evtseq = 0; + if ( gl1raw != nullptr ) + { + evtseq = gl1raw->getEvtSequence(); + } + // Only use MBDNS triggered events for MBD calibrations if ( _calpass>0 && gl1raw != nullptr ) { const uint64_t MBDTRIGS = 0x7c00; // MBDNS trigger bits //uint64_t trigvec = gl1raw->getTriggerVector(); // raw trigger only (obsolete, was only available in run1) uint64_t strig = gl1raw->getScaledVector(); // scaled trigger only - int evtseq = gl1raw->getEvtSequence(); if ( Verbosity() ) { static int counter = 0; @@ -451,6 +488,7 @@ int MbdEvent::SetRawData(std::array< CaloPacket *,2> &dstp, MbdRawContainer *bbc if (dstp[ipkt]) { _nsamples = dstp[ipkt]->iValue(0, "SAMPLES"); + { static bool printcount{true}; if ( printcount && Verbosity() > 0) @@ -460,6 +498,13 @@ int MbdEvent::SetRawData(std::array< CaloPacket *,2> &dstp, MbdRawContainer *bbc } } + // skip empty packets, corrupt event + if ( _nsamples == 0 ) + { + std::cout << PHWHERE << " ERROR, evt " << m_evt << " no samples in Packet " << pktid << std::endl; + return Fun4AllReturnCodes::ABORTEVENT; + } + m_xmitclocks[ipkt] = static_cast(dstp[ipkt]->iValue(0, "CLOCK")); m_femclocks[ipkt][0] = static_cast(dstp[ipkt]->iValue(0, "FEMCLOCK")); @@ -484,9 +529,18 @@ int MbdEvent::SetRawData(std::array< CaloPacket *,2> &dstp, MbdRawContainer *bbc } _mbdsig[feech].SetNSamples( _nsamples ); - _mbdsig[feech].SetXY(m_samp[feech], m_adc[feech]); - + + if ( _nsamples > 0 && _nsamples <= 30 ) + { + _mbdsig[feech].SetXY(m_samp[feech], m_adc[feech]); + _mbdsig[feech].SetEvtNum( evtseq ); + } /* + else + { + std::cout << PHWHERE << " empty feech " << feech << std::endl; + } + std::cout << "feech " << feech << std::endl; _mbdsig[feech].Print(); */ @@ -565,6 +619,7 @@ int MbdEvent::SetRawData(Event *event, MbdRawContainer *bbcraws, MbdPmtContainer if (p[ipkt]) { _nsamples = p[ipkt]->iValue(0, "SAMPLES"); + { static int counter = 0; if ( counter<1 ) @@ -574,6 +629,15 @@ int MbdEvent::SetRawData(Event *event, MbdRawContainer *bbcraws, MbdPmtContainer counter++; } + // If packets are missing, stop processing event + if ( _nsamples == 0 ) + { + std::cout << PHWHERE << " ERROR, skipping evt " << m_evt << " nsamples = 0 " << pktid << std::endl; + delete p[ipkt]; + p[ipkt] = nullptr; + return Fun4AllReturnCodes::ABORTEVENT; + } + m_xmitclocks[ipkt] = static_cast(p[ipkt]->iValue(0, "CLOCK")); m_femclocks[ipkt][0] = static_cast(p[ipkt]->iValue(0, "FEMCLOCK")); @@ -600,6 +664,7 @@ int MbdEvent::SetRawData(Event *event, MbdRawContainer *bbcraws, MbdPmtContainer _mbdsig[feech].SetNSamples( _nsamples ); _mbdsig[feech].SetXY(m_samp[feech], m_adc[feech]); + _mbdsig[feech].SetEvtNum( m_evt ); //_mbdsig[feech].Print(); } @@ -637,8 +702,9 @@ int MbdEvent::ProcessPackets(MbdRawContainer *bbcraws) // Do a quick sanity check that all fem counters agree if (m_xmitclocks[0] != m_xmitclocks[1]) { - std::cout << __FILE__ << ":" << __LINE__ << " ERROR, xmitclocks don't agree" << std::endl; + std::cout << __FILE__ << ":" << __LINE__ << " ERROR, xmitclocks don't agree, evt " << m_evt << std::endl; } + /* // format changed in run2024, need to update check for (auto &femclock : femclocks) @@ -673,20 +739,24 @@ int MbdEvent::ProcessPackets(MbdRawContainer *bbcraws) int pmtch = _mbdgeom->get_pmt(ifeech); int type = _mbdgeom->get_type(ifeech); // 0 = T-channel, 1 = Q-channel + if ( _mbdsig[ifeech].GetNSamples()==0 ) + { + continue; + } + // time channel if (type == 0) { m_ttdc[pmtch] = _mbdsig[ifeech].MBDTDC(_mbdcal->get_sampmax(ifeech)); - if ( m_ttdc[pmtch] < 40. || std::isnan(m_ttdc[pmtch]) || isbadtch(pmtch) ) + if ( m_ttdc[pmtch] < 40. || std::isnan(m_ttdc[pmtch]) ) { m_ttdc[pmtch] = std::numeric_limits::quiet_NaN(); // no hit } } - else if ( type == 1 && (!std::isnan(m_ttdc[pmtch]) || isbadtch(pmtch) || _always_process_charge ) ) + else if ( type == 1 && (!std::isnan(m_ttdc[pmtch]) || _always_process_charge ) ) { // we process charge channels which have good time hit - // or have time channels marked as bad // or have always_process_charge set to 1 (useful for threshold studies) // Use dCFD method to seed time in charge channels (or as primary if not fitting template) @@ -697,24 +767,21 @@ int MbdEvent::ProcessPackets(MbdRawContainer *bbcraws) m_ampl[ifeech] = _mbdsig[ifeech].GetAmpl(); // in adc units if (do_templatefit) { - //std::cout << "fittemplate" << std::endl; + //std::cout << "fittemplate " << ifeech << std::endl; _mbdsig[ifeech].FitTemplate( _mbdcal->get_sampmax(ifeech) ); + /* if ( _verbose ) { std::cout << "tt " << ifeech << " " << pmtch << " " << m_pmttt[pmtch] << std::endl; } + */ m_qtdc[pmtch] = _mbdsig[ifeech].GetTime(); // in units of sample number m_ampl[ifeech] = _mbdsig[ifeech].GetAmpl(); // in units of adc } // calpass 2, uncal_mbd. template fit. make sure qgain = 1, tq_t0 = 0 - // In Run 1 (runs before 40000), we didn't set hardware thresholds, and instead set a software threshold of 0.25 - if ( ((m_ampl[ifeech] < (_mbdcal->get_qgain(pmtch) * 0.25)) && (_runnum < 40000)) || std::fabs(_mbdcal->get_tq0(pmtch))>100. ) - { - m_qtdc[pmtch] = std::numeric_limits::quiet_NaN(); - } } } @@ -724,6 +791,8 @@ int MbdEvent::ProcessPackets(MbdRawContainer *bbcraws) { int feech = _mbdgeom->get_feech(ipmt); bbcraws->get_pmt(ipmt)->set_pmt(ipmt, m_ampl[feech], m_ttdc[ipmt], m_qtdc[ipmt]); + bbcraws->get_pmt(ipmt)->set_chi2ndf( _mbdsig[feech].GetChi2NDF() ); + bbcraws->get_pmt(ipmt)->set_fitinfo( _mbdsig[feech].GetFitInfo() ); } bbcraws->set_npmt(MbdDefs::BBC_N_PMT); // this would need to be changed if we zero-suppressed bbcraws->set_clocks(m_evt, m_clk, m_femclk); @@ -739,11 +808,17 @@ int MbdEvent::ProcessRawContainer(MbdRawContainer *bbcraws, MbdPmtContainer *bbc int pmtch = _mbdgeom->get_pmt(ifeech); int type = _mbdgeom->get_type(ifeech); // 0 = T-channel, 1 = Q-channel + if ( _mbdsig[ifeech].GetNSamples()==0 ) + { + continue; + } + // time channel if (type == 0) { if ( std::isnan(bbcraws->get_pmt(pmtch)->get_ttdc()) || isbadtch(pmtch) ) { + // time channel has no hit or is marked as bad m_pmttt[pmtch] = std::numeric_limits::quiet_NaN(); // no hit } else @@ -754,6 +829,16 @@ int MbdEvent::ProcessRawContainer(MbdRawContainer *bbcraws, MbdPmtContainer *bbc m_pmttt[pmtch] -= _mbdcal->get_tt0(pmtch); } + /* + if ( !std::isnan(m_pmttt[pmtch]) ) + { + std::cout << "pmttt " << m_evt << "\t" << pmtch << "\t" << m_pmttt[pmtch] << "\t" + << bbcraws->get_pmt(pmtch)->get_ttdc() << "\t" + << _mbdcal->get_tcorr(ifeech,bbcraws->get_pmt(pmtch)->get_ttdc()) << "\t" + << _mbdcal->get_tt0(pmtch) << std::endl; + } + */ + } else if ( type == 1 && (!std::isnan(bbcraws->get_pmt(pmtch)->get_ttdc()) || isbadtch(pmtch) || _always_process_charge ) ) { @@ -761,7 +846,15 @@ int MbdEvent::ProcessRawContainer(MbdRawContainer *bbcraws, MbdPmtContainer *bbc // or have time channels marked as bad // or have always_process_charge set to 1 (useful for threshold studies) - m_pmttq[pmtch] = bbcraws->get_pmt(pmtch)->get_qtdc(); + // In Run 1 (runs before 40000), we didn't set hardware thresholds, and instead set a software threshold of 0.25 + if ( ((bbcraws->get_pmt(pmtch)->get_adc() < (_mbdcal->get_qgain(pmtch) * 0.25)) && (_runnum < 40000)) || std::fabs(_mbdcal->get_tq0(pmtch))>100. ) + { + m_pmttq[pmtch] = std::numeric_limits::quiet_NaN(); + } + else + { + m_pmttq[pmtch] = bbcraws->get_pmt(pmtch)->get_qtdc(); + } if ( !std::isnan(m_pmttq[pmtch]) ) { @@ -770,17 +863,15 @@ int MbdEvent::ProcessRawContainer(MbdRawContainer *bbcraws, MbdPmtContainer *bbc m_pmttq[pmtch] = m_pmttq[pmtch] - _mbdcal->get_tq0(pmtch); // if ( m_pmttq[pmtch]<-50. && ifeech==255 ) std::cout << "hit_times " << ifeech << "\t" << m_pmttq[pmtch] << std::endl; - // if ( arm==1 ) std::cout << "hit_times " << ifeech << "\t" << setw(10) << m_pmttq[pmtch] << "\t" << board << "\t" << TRIG_SAMP[board] << std::endl; // if tt is bad, use tq - if ( std::fabs(_mbdcal->get_tt0(pmtch))>100. ) + if ( _mbdcal->get_status(ifeech-8)>0 ) { m_pmttt[pmtch] = m_pmttq[pmtch]; } else { // we have a good tt ch. correct for slew if there is a hit - //if ( ifeech==0 ) std::cout << "applying scorr" << std::endl; if ( !std::isnan(m_pmttt[pmtch]) ) { m_pmttt[pmtch] -= _mbdcal->get_scorr(ifeech-8,bbcraws->get_pmt(pmtch)->get_adc()); @@ -819,7 +910,10 @@ int MbdEvent::ProcessRawContainer(MbdRawContainer *bbcraws, MbdPmtContainer *bbc // Copy to output for (int ipmt = 0; ipmt < MbdDefs::BBC_N_PMT; ipmt++) { + int feech = _mbdgeom->get_feech(ipmt); bbcpmts->get_pmt(ipmt)->set_pmt(ipmt, m_pmtq[ipmt], m_pmttt[ipmt], m_pmttq[ipmt]); + bbcraws->get_pmt(ipmt)->set_chi2ndf( _mbdsig[feech].GetChi2NDF() ); + bbcraws->get_pmt(ipmt)->set_fitinfo( _mbdsig[feech].GetFitInfo() ); } bbcpmts->set_npmt(MbdDefs::BBC_N_PMT); @@ -854,8 +948,14 @@ int MbdEvent::ProcessRawContainer(MbdRawContainer *bbcraws, MbdPmtContainer *bbc */ TGraphErrors *gsubpulse = _mbdsig[ifeech].GetGraph(); - Double_t *y = gsubpulse->GetY(); - h2_trange->Fill( y[samp_max], pmtch ); // fill ped-subtracted tdc + if ( gsubpulse ) + { + Double_t *y = gsubpulse->GetY(); + if ( y ) + { + h2_trange->Fill( y[samp_max], pmtch ); // fill ped-subtracted tdc + } + } } } @@ -1040,11 +1140,6 @@ int MbdEvent::Calculate(MbdPmtContainer *bbcpmts, MbdOut *bbcout, PHCompositeNod gausfit[iarm]->SetRange(hevt_bbct[iarm]->GetMean() - 5, hevt_bbct[iarm]->GetMean() + 5); */ - if ( hevt_bbct[iarm]->GetEntries()==0 )//chiu - { - std::cout << PHWHERE << " hevt_bbct EMPTY" << std::endl; - } - hevt_bbct[iarm]->Fit(gausfit[iarm], "BNQLR"); // m_bbct[iarm] = m_bbct[iarm] / m_bbcn[iarm]; @@ -1375,10 +1470,6 @@ int MbdEvent::CalcPedCalib() pedgaus->SetParameters(ampl,mean,sigma); pedgaus->SetRange(mean-(4*sigma), mean+(4*sigma)); - if ( hped0->GetEntries()==0 ) //chiu - { - std::cout << "HPED0 EMPTY" << std::endl; - } hped0->Fit(pedgaus,"RNQ"); mean = pedgaus->GetParameter(1); diff --git a/offline/packages/mbd/MbdEvent.h b/offline/packages/mbd/MbdEvent.h index ede1670171..5abd48aeae 100644 --- a/offline/packages/mbd/MbdEvent.h +++ b/offline/packages/mbd/MbdEvent.h @@ -74,6 +74,7 @@ class MbdEvent void set_EventNumber(int ievt) { m_evt = ievt; } void set_debug(const int d) { _debug = d; } + void set_doeval(const int d) { _doeval = d; } MbdSig *GetSig(const int ipmt) { return &_mbdsig[ipmt]; } @@ -196,12 +197,14 @@ class MbdEvent // debug stuff TCanvas *ac{nullptr}; // for plots used during debugging void PlotDebug(); + int _doeval{0}; + std::unique_ptr _evalfile{nullptr}; std::unique_ptr _synctfile{nullptr}; TTree *_syncttree{nullptr}; Double_t _refz{ std::numeric_limits::quiet_NaN() }; - std::vector bbevt; + std::vector bbevt; std::vector bbclk; - std::vector mybbz; + std::vector mybbz; std::vector bco; std::vector intz; std::vector bbz; diff --git a/offline/packages/mbd/MbdRawContainerV2.cc b/offline/packages/mbd/MbdRawContainerV2.cc new file mode 100644 index 0000000000..9b7236de4a --- /dev/null +++ b/offline/packages/mbd/MbdRawContainerV2.cc @@ -0,0 +1,64 @@ +#include "MbdRawContainerV2.h" +#include "MbdRawHitV2.h" +#include "MbdReturnCodes.h" +#include "MbdDefs.h" + +#include + +#include + +MbdRawContainerV2::MbdRawContainerV2() : MbdRawHits(new TClonesArray("MbdRawHitV2", MbdDefs::MBD_N_PMT)) +{ + // MbdRawHit is class for single hit (members: pmt,adc,ttdc,qtdc), do not mix + // with TClonesArray *MbdRawHits + +} + +MbdRawContainerV2::~MbdRawContainerV2() +{ + delete MbdRawHits; +} + +int MbdRawContainerV2::isValid() const +{ + if (npmt <= 0) + { + return 0; + } + return 1; +} + +void MbdRawContainerV2::Reset() +{ + MbdRawHits->Clear(); + npmt = 0; +} + +void MbdRawContainerV2::identify(std::ostream &out) const +{ + out << "identify yourself: I am a MbdRawContainerV2 object" << std::endl; +} + +//______________________________________ +void MbdRawContainerV2::set_clocks(const Int_t ievt, const UShort_t iclk, const UShort_t ifemclk) +{ + evt = ievt; + clk = iclk; + femclk = ifemclk; +} + +Int_t MbdRawContainerV2::get_evt() const +{ + return evt; +} + +UShort_t MbdRawContainerV2::get_clock() const +{ + return clk; +} + +UShort_t MbdRawContainerV2::get_femclock() const +{ + return femclk; +} + diff --git a/offline/packages/mbd/MbdRawContainerV2.h b/offline/packages/mbd/MbdRawContainerV2.h new file mode 100644 index 0000000000..199ab4cc73 --- /dev/null +++ b/offline/packages/mbd/MbdRawContainerV2.h @@ -0,0 +1,84 @@ +#ifndef MBD_MBDRAWCONTAINERV2_H__ +#define MBD_MBDRAWCONTAINERV2_H__ + +#include "MbdRawContainer.h" + +#include + +#include + +/// +class MbdRawContainerV2 : public MbdRawContainer +{ +public: + /// ctor + MbdRawContainerV2(); + + /// dtor + virtual ~MbdRawContainerV2(); + + /// Clear Event + void Reset() override; + + /** identify Function from PHObject + @param os Output Stream + */ + void identify(std::ostream &out = std::cout) const override; + + /// isValid returns non zero if object contains vailid data + int isValid() const override; + + /** Add Mbd data containing evt, clk, and femclk + @param ievt Event number + @param iclk XMIT clock + @param ifemclk FEM clock + */ + virtual void set_clocks(const Int_t ievt, const UShort_t iclk, const UShort_t ifemclk) override; + + /** get Event Number + */ + virtual Int_t get_evt() const override; + + /** get XMIT Clock Counter + */ + virtual UShort_t get_clock() const override; + + /** get FEM Clock Counter + */ + virtual UShort_t get_femclock() const override; + + /** set number of pmts for Mbd + @param ival Number of Mbd Pmt's + */ + void set_npmt(const Short_t ival) override + { + if ( ival != MbdRawHits->GetEntries() ) + { + std::cout << "ERROR, " << ival << " differs from " << MbdRawHits->GetEntries() << std::endl; + std::cout << " Setting npmt to " << MbdRawHits->GetEntries() << std::endl; + } + npmt = MbdRawHits->GetEntries(); + return; + } + + /// get Number of Mbd Pmt's + Short_t get_npmt() const override { return MbdRawHits->GetEntries(); } + + /** get MbdRawPmt of Pmt iPmt in TClonesArray + @param iPmt no of Pmt in TClonesArray + */ + MbdRawHit *get_pmt(const int iPmt) const override { return (MbdRawHit*)MbdRawHits->ConstructedAt(iPmt); } + +private: + TClonesArray *GetMbdRawHits() const { return MbdRawHits; } + + Int_t evt{-1}; + UShort_t clk{0}; + UShort_t femclk{0}; + Short_t npmt = 0; + TClonesArray *MbdRawHits = nullptr; + + ClassDefOverride(MbdRawContainerV2, 1) +}; + +#endif diff --git a/offline/packages/mbd/MbdRawContainerV2LinkDef.h b/offline/packages/mbd/MbdRawContainerV2LinkDef.h new file mode 100644 index 0000000000..2c3bf0df5d --- /dev/null +++ b/offline/packages/mbd/MbdRawContainerV2LinkDef.h @@ -0,0 +1,5 @@ +#ifdef __CINT__ + +#pragma link C++ class MbdRawContainerV2 + ; + +#endif diff --git a/offline/packages/mbd/MbdRawHit.h b/offline/packages/mbd/MbdRawHit.h index 45bd089d5b..862194352b 100644 --- a/offline/packages/mbd/MbdRawHit.h +++ b/offline/packages/mbd/MbdRawHit.h @@ -40,11 +40,53 @@ class MbdRawHit : public PHObject return MbdReturnCodes::MBD_INVALID_FLOAT; } + virtual Float_t get_chi2ndf() const + { + static int ctr = 0; + if ( ctr<3 ) + { + PHOOL_VIRTUAL_WARNING; + ctr++; + } + return MbdReturnCodes::MBD_INVALID_FLOAT; + } + + virtual UShort_t get_fitinfo() const + { + static int ctr = 0; + if ( ctr<3 ) + { + PHOOL_VIRTUAL_WARNING; + ctr++; + } + return 0; + } + virtual void set_pmt(const Short_t /*pmt*/, const Float_t /*adc*/, const Float_t /*ttdc*/, const Float_t /*qtdc*/) { PHOOL_VIRTUAL_WARNING; } + virtual void set_chi2ndf(const Double_t /*chi2ndf*/) + { + static int ctr = 0; + if ( ctr<3 ) + { + PHOOL_VIRTUAL_WARNING; + ctr++; + } + } + + virtual void set_fitinfo(const UShort_t /*fitinfo*/) + { + static int ctr = 0; + if ( ctr<3 ) + { + PHOOL_VIRTUAL_WARNING; + ctr++; + } + } + virtual void identify(std::ostream& out = std::cout) const override; virtual int isValid() const override { return 0; } diff --git a/offline/packages/mbd/MbdRawHitV1.cc b/offline/packages/mbd/MbdRawHitV1.cc index 6f4eec2001..2ea6b34c01 100644 --- a/offline/packages/mbd/MbdRawHitV1.cc +++ b/offline/packages/mbd/MbdRawHitV1.cc @@ -7,7 +7,7 @@ void MbdRawHitV1::Reset() void MbdRawHitV1::Clear(Option_t* /*unused*/) { - std::cout << "clearing " << bpmt << std::endl; + //std::cout << "clearing " << bpmt << std::endl; bpmt = -1; badc = std::numeric_limits::quiet_NaN(); bttdc = std::numeric_limits::quiet_NaN(); diff --git a/offline/packages/mbd/MbdRawHitV1.h b/offline/packages/mbd/MbdRawHitV1.h index ddb5e593e7..3b33d62e2c 100644 --- a/offline/packages/mbd/MbdRawHitV1.h +++ b/offline/packages/mbd/MbdRawHitV1.h @@ -39,6 +39,18 @@ class MbdRawHitV1 : public MbdRawHit bqtdc = tq; } + //! dummy method, only exists in V2 + void set_chi2ndf(const Double_t /*chi2ndf*/) override + { + return; + } + + //! dummy method, only exists in V2 + void set_fitinfo(const UShort_t /*fitinfo*/) override + { + return; + } + //! Prints out exact identity of object void identify(std::ostream& out = std::cout) const override; diff --git a/offline/packages/mbd/MbdRawHitV2.cc b/offline/packages/mbd/MbdRawHitV2.cc new file mode 100644 index 0000000000..695003cfb1 --- /dev/null +++ b/offline/packages/mbd/MbdRawHitV2.cc @@ -0,0 +1,23 @@ +#include "MbdRawHitV2.h" + +void MbdRawHitV2::Reset() +{ + Clear(); +} + +void MbdRawHitV2::Clear(Option_t* /*unused*/) +{ + //std::cout << "clearing " << bpmt << std::endl; + bpmt = -1; + fitstat = 0; + badc = std::numeric_limits::quiet_NaN(); + bttdc = std::numeric_limits::quiet_NaN(); + bqtdc = std::numeric_limits::quiet_NaN(); +} + +void MbdRawHitV2::identify(std::ostream& out) const +{ + out << "identify yourself: I am a MbdRawHitV2 object" << std::endl; + out << "Pmt: " << bpmt << ", adc: " << badc << ", ttdc: " + << bttdc << ", bqtdc: " << bqtdc << std::endl; +} diff --git a/offline/packages/mbd/MbdRawHitV2.h b/offline/packages/mbd/MbdRawHitV2.h new file mode 100644 index 0000000000..4bc88f871d --- /dev/null +++ b/offline/packages/mbd/MbdRawHitV2.h @@ -0,0 +1,89 @@ +#ifndef __MBD_MBDRAWHITV2_H__ +#define __MBD_MBDRAWHITV2_H__ + +#include "MbdRawHit.h" + +#include +#include +#include + +class MbdRawHitV2 : public MbdRawHit +{ + public: + MbdRawHitV2() = default; + ~MbdRawHitV2() override = default; + + //! Just does a clear + void Reset() override; + + //! Clear is used by TClonesArray to reset the tower to initial state without calling destructor/constructor + void Clear(Option_t* = "") override; + + //! PMT number + Short_t get_pmt() const override { return bpmt; } + + //! ADC + Float_t get_adc() const override { return badc; } + + //! TDC from time channel + Float_t get_ttdc() const override { return bttdc; } + + //! TDC from charge channel + Float_t get_qtdc() const override { return bqtdc; } + + //! Chi2/NDF from charge channel waveform fit + Float_t get_chi2ndf() const override { return (fitstat&0xfff)/100.; } + + //! Info about charge channel waveform fit + UShort_t get_fitinfo() const override { return (fitstat>>12); } + + //! Set PMT data values + void set_pmt(const Short_t pmt, const Float_t a, const Float_t tt, const Float_t tq) override + { + bpmt = pmt; + badc = a; + bttdc = tt; + bqtdc = tq; + } + + //! Store chi2/ndf (encoded in fitstat) + void set_chi2ndf(const Double_t chi2ndf) override + { + UShort_t us_chi2ndf = 0; + if (std::isfinite(chi2ndf) && chi2ndf > 0.) + { + const Double_t clipped = (chi2ndf > 40.95) ? 40.95 : chi2ndf; + us_chi2ndf = static_cast(clipped * 100.); + } + fitstat &= 0xf000; + fitstat |= us_chi2ndf; + } + + //! Store fitinfo (encoded in fitstat) + void set_fitinfo(const UShort_t fitinfo) override + { + fitstat &= 0xfff; + fitstat |= (fitinfo<<12); + } + + //! Prints out exact identity of object + void identify(std::ostream& out = std::cout) const override; + + //! isValid returns non zero if object contains valid data + virtual int isValid() const override + { + if (std::isnan(get_ttdc())) return 0; + return 1; + } + + private: + Short_t bpmt; + UShort_t fitstat; //waveform fit status + Float_t badc; + Float_t bttdc; + Float_t bqtdc; + + ClassDefOverride(MbdRawHitV2, 1) +}; + +#endif diff --git a/offline/packages/mbd/MbdRawHitV2LinkDef.h b/offline/packages/mbd/MbdRawHitV2LinkDef.h new file mode 100644 index 0000000000..8936852bfe --- /dev/null +++ b/offline/packages/mbd/MbdRawHitV2LinkDef.h @@ -0,0 +1,5 @@ +#ifdef __CINT__ + +#pragma link C++ class MbdRawHitV2 + ; + +#endif diff --git a/offline/packages/mbd/MbdReco.cc b/offline/packages/mbd/MbdReco.cc index c19ed37ba9..5ae4a67271 100644 --- a/offline/packages/mbd/MbdReco.cc +++ b/offline/packages/mbd/MbdReco.cc @@ -2,12 +2,12 @@ #include "MbdEvent.h" #include "MbdGeomV1.h" #include "MbdOutV2.h" -#include "MbdRawContainerV1.h" +#include "MbdRawContainerV2.h" #include "MbdPmtContainerV1.h" #include "MbdPmtSimContainerV1.h" #include -#include +#include #include @@ -61,11 +61,17 @@ int MbdReco::InitRun(PHCompositeNode *topNode) } int ret = getNodes(topNode); + if ( ret != Fun4AllReturnCodes::EVENT_OK ) + { + return ret; + } m_mbdevent->SetSim(_simflag); m_mbdevent->SetRawDstFlag(_rawdstflag); m_mbdevent->SetFitsOnly(_fitsonly); - m_mbdevent->InitRun(); + m_mbdevent->set_doeval(_fiteval); + + ret = m_mbdevent->InitRun(); return ret; } @@ -103,7 +109,8 @@ int MbdReco::process_event(PHCompositeNode *topNode) int status = Fun4AllReturnCodes::EVENT_OK; if ( m_evtheader!=nullptr ) { - m_mbdevent->set_EventNumber( m_evtheader->get_EvtSequence() ); + _evtnum = m_evtheader->get_EvtSequence(); + m_mbdevent->set_EventNumber( _evtnum ); } if ( m_event!=nullptr ) @@ -125,7 +132,7 @@ int MbdReco::process_event(PHCompositeNode *topNode) static int counter = 0; if ( counter<3 ) { - std::cout << PHWHERE << " Warning, MBD discarding event " << std::endl; + std::cout << PHWHERE << " Warning, MBD discarding event " << _evtnum << std::endl; counter++; } return Fun4AllReturnCodes::DISCARDEVENT; @@ -135,7 +142,7 @@ int MbdReco::process_event(PHCompositeNode *topNode) static int counter = 0; if ( counter<3 ) { - std::cout << PHWHERE << " Warning, MBD aborting event " << std::endl; + std::cout << PHWHERE << " Warning, MBD aborting event " << _evtnum << std::endl; counter++; } return Fun4AllReturnCodes::ABORTEVENT; @@ -171,7 +178,7 @@ int MbdReco::process_event(PHCompositeNode *topNode) // For multiple global vertex if (m_mbdevent->get_bbcn(0) > 0 && m_mbdevent->get_bbcn(1) > 0 && _calpass==0 ) { - auto *vertex = new MbdVertexv2(); + auto *vertex = new MbdVertexv3(); vertex->set_t(m_mbdevent->get_bbct0()); vertex->set_z(m_mbdevent->get_bbcz()); vertex->set_z_err(0.6); @@ -255,7 +262,7 @@ int MbdReco::createNodes(PHCompositeNode *topNode) if (!m_mbdraws) { std::cout << "Creating MbdRawContainer Node " << std::endl; - m_mbdraws = new MbdRawContainerV1(); + m_mbdraws = new MbdRawContainerV2(); PHIODataNode *MbdRawContainerNode = new PHIODataNode(m_mbdraws, "MbdRawContainer", "PHObject"); bbcNode->addNode(MbdRawContainerNode); } diff --git a/offline/packages/mbd/MbdReco.h b/offline/packages/mbd/MbdReco.h index 0dfc7d7cbc..13a635d602 100644 --- a/offline/packages/mbd/MbdReco.h +++ b/offline/packages/mbd/MbdReco.h @@ -34,10 +34,13 @@ class MbdReco : public SubsysReco int process_event(PHCompositeNode *topNode) override; int End(PHCompositeNode *topNode) override; - void DoOnlyFits() { _fitsonly = 1; } + void DoOnlyFits() { _fitsonly = 1; } + void DoFitEval(const int s) { _fiteval = s; } void SetCalPass(const int calpass) { _calpass = calpass; } void SetProcChargeCh(const bool s) { _always_process_charge = s; } - void SetMbdTrigOnly(const int m) { _mbdonly = m; } + void SetMbdTrigOnly(const int m) { _mbdonly = m; } + + MbdEvent* GetMbdEvent() { return m_mbdevent.get(); } private: int createNodes(PHCompositeNode *topNode); @@ -48,10 +51,13 @@ class MbdReco : public SubsysReco int _mbdonly{0}; // only use mbd triggers int _rawdstflag{0}; // dst with raw container int _fitsonly{0}; // stop reco after waveform fits (for DST_CALOFIT pass) + int _fiteval{0}; // overload with segment+1 float m_tres = 0.05; std::unique_ptr m_gaussian = nullptr; + int _evtnum{-1}; + std::unique_ptr m_mbdevent{nullptr}; Event *m_event{nullptr}; std::arraym_mbdpacket{nullptr}; diff --git a/offline/packages/mbd/MbdReturnCodes.h b/offline/packages/mbd/MbdReturnCodes.h index c9b1aea40e..ee808346fa 100644 --- a/offline/packages/mbd/MbdReturnCodes.h +++ b/offline/packages/mbd/MbdReturnCodes.h @@ -8,8 +8,9 @@ namespace MbdReturnCodes { - const short MBD_INVALID_SHORT = std::numeric_limits::min(); //-9999; - const int MBD_INVALID_INT = std::numeric_limits::min(); //-9999; + const short MBD_INVALID_SHORT = std::numeric_limits::min(); + const unsigned short MBD_INVALID_USHORT = std::numeric_limits::min(); + const int MBD_INVALID_INT = std::numeric_limits::min(); const float MBD_INVALID_FLOAT = std::numeric_limits::quiet_NaN(); } // namespace MbdReturnCodes diff --git a/offline/packages/mbd/MbdSig.cc b/offline/packages/mbd/MbdSig.cc index ae1f821a4e..65de1006fc 100644 --- a/offline/packages/mbd/MbdSig.cc +++ b/offline/packages/mbd/MbdSig.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -49,12 +50,13 @@ void MbdSig::Init() gSubPulse->SetName(name); gSubPulse->GetHistogram()->SetXTitle("sample"); gSubPulse->GetHistogram()->SetYTitle("ADC"); + gSubPulse->GetHistogram()->SetTitle(name); hpulse = hRawPulse; // hpulse,gpulse point to raw by default gpulse = gRawPulse; // we switch to sub for default if ped is applied - //ped0stats = std::make_unique(100); // use the last 100 events for running pedestal - ped0stats = new MbdRunningStats(100); // use the last 100 events for running pedestal + ped0stats = new MbdRunningStats(8); // use the last 8 samples for running pedestal + name = "hPed0_"; name += _ch; hPed0 = new TH1F(name, name, 3000, -0.5, 2999.5); @@ -62,6 +64,15 @@ void MbdSig::Init() name = "hPedEvt_"; name += _ch; hPedEvt = new TH1F(name, name, 3000, -0.5, 2999.5); + if ( _pedstudyflag ) + { + gPedvsEvent = new TGraphErrors(); + name = "gpedvsevent"; + name += _ch; + gPedvsEvent->SetName(name); + gPedvsEvent->GetHistogram()->SetXTitle("evtnum"); + gPedvsEvent->GetHistogram()->SetYTitle("ped"); + } SetTemplateSize(900, 1000, -10., 20.); // SetTemplateSize(300,300,0.,15.); @@ -70,14 +81,13 @@ void MbdSig::Init() ped_fcn = new TF1("ped_fcn","[0]",0,2); ped_fcn->SetLineColor(3); - // Set tail function - ped_tail = new TF1("ped_tail","[0]+[1]*exp(-[2]*x)",0,2); - ped_tail->SetLineColor(2); + name = "h_chi2ndf"; name += _ch; + h_chi2ndf = new TH1F(name,name,2000,0,100); - // uncomment this to write out waveforms from events that have pileup from prev. crossing + // uncomment this to write out waveforms from events that have pileup from prev. crossing or next crossing /* name = "mbdsig"; name += _ch; name += ".txt"; - _pileupfile = new ofstream(name); + _pileupfile = new std::ofstream(name); */ } @@ -134,16 +144,22 @@ MbdSig::~MbdSig() delete hSubPulse; delete gRawPulse; delete gSubPulse; - delete hPed0; delete ped0stats; - // h2Template->Write(); + delete hPed0; + delete hPedEvt; delete h2Template; delete h2Residuals; delete hAmpl; delete hTime; delete template_fcn; + delete twotemplate_fcn; delete ped_fcn; - delete ped_tail; + delete fit_pileup; + delete h_chi2ndf; + if ( _pedstudyflag ) + { + delete gPedvsEvent; + } } void MbdSig::SetEventPed0PreSamp(const Int_t presample, const Int_t nsamps, const int max_samp) @@ -218,8 +234,6 @@ void MbdSig::SetY(const Float_t* y, const int invert) Remove_Pileup(); } } - - _evt_counter++; } void MbdSig::SetXY(const Float_t* x, const Float_t* y, const int invert) @@ -251,6 +265,7 @@ void MbdSig::SetXY(const Float_t* x, const Float_t* y, const int invert) { gRawPulse->Draw("ap"); gRawPulse->GetHistogram()->SetTitle(gRawPulse->GetName()); + gPad->SetGridx(1); gPad->SetGridy(1); PadUpdate(); } @@ -291,25 +306,26 @@ void MbdSig::SetXY(const Float_t* x, const Float_t* y, const int invert) Remove_Pileup(); } + /* if ( _verbose && _ch==9 ) { std::cout << "SetXY: ch " << _ch << std::endl; gSubPulse->Print("ALL"); } + */ } - _evt_counter++; _verbose = 0; } void MbdSig::Remove_Pileup() { - //_verbose = 100; _verbose = 0; /* - if ( (_ch==238&&_evt_counter==7104) || (_ch==255&&_evt_counter==7762) ) + if ( _ch==46 && (_evt_counter>200910 && _evt_counter<200920)) { + std::cout << PHWHERE << "\t" << _evt_counter << "\t" << _ch << std::endl; _verbose = 100; } */ @@ -321,54 +337,135 @@ void MbdSig::Remove_Pileup() if ( (_ch/8)%2 == 0 ) // time ch { - float offset = _pileup_p0*gSubPulse->GetPointY(0); + double x_at_max = TMath::LocMax( 5, gSubPulse->GetY() ); - for (int isamp = 0; isamp < _nsamples; isamp++) + if ( x_at_max != 0 ) { - double x = gSubPulse->GetPointX(isamp); - double y = gSubPulse->GetPointY(isamp); + // time hit in prev crossing + if ( fit_pileup == nullptr ) + { + TString name = "fit_pileup"; name += _ch; + fit_pileup = new TF1(name,"pol3",0,16000); + fit_pileup->SetLineColor(7); + for (int ipar=0; ipar<4; ipar++) + { + fit_pileup->SetParameter( ipar, _mbdcal->get_pileup(_ch,ipar+1) ); + } + } + + int sampmax = _mbdcal->get_sampmax(_ch); + if ( (sampmax-6) > 0 ) + { + double x_sampmax = gSubPulse->GetPointX(sampmax); + double y_sampmax = gSubPulse->GetPointY(sampmax); + double y_min6 = gSubPulse->GetPointY(sampmax-6); - hSubPulse->SetBinContent( isamp + 1, y - offset ); - gSubPulse->SetPoint( isamp, x, y - offset ); + double offset = y_min6*fit_pileup->Eval(y_min6); + + hSubPulse->SetBinContent( sampmax + 1, y_sampmax - offset ); + gSubPulse->SetPoint( sampmax, x_sampmax, y_sampmax - offset ); + } + else + { + static int ctr = 0; + if ( ctr<10 ) + { + std::cout << PHWHERE << " WARNING, sampmax too early for time pileup corr" << std::endl; + ctr++; + } + } } - } - else - { - if ( fit_pileup == nullptr ) + else { - TString name = "fit_pileup"; name += _ch; - fit_pileup = new TF1(name,"gaus",-0.1,4.1); - fit_pileup->SetLineColor(2); - } + // time hit in 2 crossings before + float offset = _pileup_p0*gSubPulse->GetPointY(0); - fit_pileup->SetRange(-0.1,4.1); - fit_pileup->SetParameters( _pileup_p0*gSubPulse->GetPointY(0), _pileup_p1, _pileup_p2 ); - - // fix par limits - double plow{0.}; - double phigh{0.}; - fit_pileup->GetParLimits(2,plow,phigh); - if ( phigh < _pileup_p2 ) - { - phigh = 2*_pileup_p2; - fit_pileup->SetParLimits(2,plow,phigh); + for (int isamp = 0; isamp < _nsamples; isamp++) + { + double x = gSubPulse->GetPointX(isamp); + double y = gSubPulse->GetPointY(isamp); + + hSubPulse->SetBinContent( isamp + 1, y - offset ); + gSubPulse->SetPoint( isamp, x, y - offset ); + } } + } + else // charge ch + { + double ymax = TMath::MaxElement( 5, gSubPulse->GetY() ); + double x_at_max = TMath::LocMax( 5, gSubPulse->GetY() ); - if ( _verbose ) + if ( x_at_max != 0 ) { - gSubPulse->Fit( fit_pileup, "R" ); - gSubPulse->Draw("ap"); - PadUpdate(); + // Fit a pulse in prev crossing + template_fcn->SetParameters(ymax, x_at_max); + template_fcn->SetRange(0, x_at_max+2.1); + + if (_verbose == 0) + { + //std::cout << PHWHERE << std::endl; + gSubPulse->Fit(template_fcn, "RNQ"); + } + else + { + std::cout << "pre-pileup " << _ch << "\t" << x_at_max << "\t" << ymax << std::endl; + gSubPulse->Fit(template_fcn, "R"); + gSubPulse->Draw("ap"); + gSubPulse->GetHistogram()->SetTitle(gSubPulse->GetName()); + gPad->SetGridy(1); + PadUpdate(); + //gSubPulse->Print("ALL"); + } } else { - gSubPulse->Fit( fit_pileup, "RNQ" ); + // Fit the tail + if ( fit_pileup == nullptr ) + { + TString name = "fit_pileup"; name += _ch; + //fit_pileup = new TF1(name,"gaus",-0.1,4.1); + fit_pileup = new TF1(name, this, &MbdSig::SignalTail, -0.1, 4.1, 3, "MbdSig", "SignalTail"); + fit_pileup->SetLineColor(6); + } + + fit_pileup->SetRange(-0.1,4.1); + fit_pileup->SetParameters( _pileup_p0*gSubPulse->GetPointY(0), _pileup_p1, _pileup_p2 ); + + // fix par limits + double plow{0.}; + double phigh{0.}; + fit_pileup->GetParLimits(2,plow,phigh); + if ( phigh < _pileup_p2 ) + { + phigh = 2*_pileup_p2; + fit_pileup->SetParLimits(2,plow,phigh); + } + + if ( _verbose ) + { + gSubPulse->Fit( fit_pileup, "R" ); + gSubPulse->Draw("ap"); + PadUpdate(); + } + else + { + gSubPulse->Fit( fit_pileup, "RNQ" ); + } } + // subtract pre-pulse for (int isamp = 0; isamp < _nsamples; isamp++) { - double bkg = fit_pileup->Eval(isamp); + double bkg = 0.; + if ( x_at_max != 0 ) + { + bkg = template_fcn->Eval(isamp); + } + else + { + bkg = fit_pileup->Eval(isamp); + } double x = gSubPulse->GetPointX(isamp); double y = gSubPulse->GetPointY(isamp); @@ -382,6 +479,7 @@ void MbdSig::Remove_Pileup() if ( _verbose ) { + std::cout << "pileup sub " << _ch << std::endl; gSubPulse->Draw("ap"); PadUpdate(); } @@ -412,11 +510,24 @@ Double_t MbdSig::GetSplineAmpl() return f_ampl; } +void MbdSig::WriteChi2Hist() +{ + h_chi2ndf->Write(); +} + void MbdSig::WritePedHist() { hPed0->Write(); } +void MbdSig::WritePedvsEvent() +{ + if ( _pedstudyflag ) + { + gPedvsEvent->Write(); + } +} + void MbdSig::FillPed0(const Int_t sampmin, const Int_t sampmax) { Double_t x; @@ -427,13 +538,6 @@ void MbdSig::FillPed0(const Int_t sampmin, const Int_t sampmax) // gRawPulse->Print("all"); hPed0->Fill(y); - /* - // chiu taken out - ped0stats->Push( y ); - ped0 = ped0stats->Mean(); - ped0rms = ped0stats->RMS(); - */ - // std::cout << "ped0 " << _ch << " " << n << "\t" << ped0 << std::endl; // std::cout << "ped0 " << _ch << "\t" << ped0 << std::endl; } @@ -452,10 +556,10 @@ void MbdSig::FillPed0(const Double_t begin, const Double_t end) hPed0->Fill(y); /* - ped0stats->Push( y ); - ped0 = ped0stats->Mean(); - ped0rms = ped0stats->RMS(); - */ + ped0stats->Push( y ); + ped0 = ped0stats->Mean(); + ped0rms = ped0stats->RMS(); + */ // std::cout << "ped0 " << _ch << " " << n << "\t" << x << "\t" << y << std::endl; } @@ -537,9 +641,7 @@ void MbdSig::CalcEventPed0(const Double_t minpedx, const Double_t maxpedx) // If a prev event pileup is detected, return 1, otherwise, return 0 int MbdSig::CalcEventPed0_PreSamp(const int presample, const int nsamps) { - //std::cout << PHWHERE << std::endl; //chiu //_verbose = 100; - //ped0stats->Clear(); int status = 0; // assume no pileup @@ -597,10 +699,16 @@ int MbdSig::CalcEventPed0_PreSamp(const int presample, const int nsamps) ped_fcn->SetRange(minsamp-0.1,maxsamp+0.1); ped_fcn->SetParameter(0,1500.); - if ( gRawPulse->GetN()==0 )//chiu + gRawPulse->Fit( ped_fcn, "RNQ" ); + double chi2 = ped_fcn->GetChisquare(); + double ndf = ped_fcn->GetNDF(); + + /* + if ( chi2/ndf>4 ) { - std::cout << PHWHERE << " gRawPulse 0" << std::endl; + _verbose=100; } + */ if ( _verbose ) { @@ -614,25 +722,6 @@ int MbdSig::CalcEventPed0_PreSamp(const int presample, const int nsamps) PadUpdate(); } } - else - { - //std::cout << PHWHERE << std::endl; - gRawPulse->Fit( ped_fcn, "RNQ" ); - - double chi2ndf = ped_fcn->GetChisquare()/ped_fcn->GetNDF(); - if ( _pileupfile != nullptr && chi2ndf > 4.0 ) - { - *_pileupfile << "ped " << _ch << " mean " << mean << "\t"; - for ( int i=0; iGetN(); i++) - { - *_pileupfile << std::setw(6) << gRawPulse->GetPointY(i); - } - *_pileupfile << std::endl; - } - } - - double chi2 = ped_fcn->GetChisquare(); - double ndf = ped_fcn->GetNDF(); if ( chi2/ndf < 4.0 ) { @@ -657,6 +746,28 @@ int MbdSig::CalcEventPed0_PreSamp(const int presample, const int nsamps) << "isamp " << isamp << "\t" << x << "\t" << y << std::endl; } } + + // study pedestal vs event + if ( _pedstudyflag ) + { + // running pedestal (replace with mean and meanerr for evt-by-evt) + double ped_evtnum = _evt_counter; + double ped_mean = ped0stats->Mean(); + double ped_meanerr = rms; + if ( ped0stats->Size()>1 ) + { + ped_meanerr = ped0stats->RMS()/std::sqrt(ped0stats->Size()); + } + else + { + ped_meanerr = _mbdcal->get_pedrms(_ch); + } + + int n = gPedvsEvent->GetN(); + gPedvsEvent->SetPoint(n,ped_evtnum,ped_mean); + gPedvsEvent->SetPointError(n,0,ped_meanerr); + } + } else { @@ -687,11 +798,18 @@ int MbdSig::CalcEventPed0_PreSamp(const int presample, const int nsamps) } } - // use straight mean for pedestal - // Could consider using fit to hPed0 to remove outliers - //rms = ped0stats->RMS(); - //Double_t mean = hPed0->GetMean(); - //Double_t rms = hPed0->GetRMS(); + // uncomment this to write out file with pileup waveforms + /* + if ( _pileupfile != nullptr ) + { + *_pileupfile << "ped " << _ch << " mean " << mean << "\t"; + for ( int i=0; iGetN(); i++) + { + *_pileupfile << std::setw(6) << gRawPulse->GetPointY(i); + } + *_pileupfile << std::endl; + } + */ } SetPed0(mean, rms); @@ -969,9 +1087,10 @@ void MbdSig::PadUpdate() const std::cout << PHWHERE << " PadUpdate\t_verbose = " << _verbose << std::endl; if ( _verbose>5 ) { + gPad->SetGridy(1); gPad->Modified(); gPad->Update(); - std::cout << _ch << " ? "; + std::cout << _evt_counter << ": " << _ch << " ? "; if ( _verbose>10 ) { std::string junk; @@ -988,6 +1107,27 @@ void MbdSig::PadUpdate() const } } +Double_t MbdSig::SignalTail(const Double_t* x, const Double_t* par) +{ + // par[0] is the amplitude (relative to the spline amplitude) + // par[1] is the time + // x[0] units are in sample number + Double_t xx = x[0]-par[1]; + if ( xx<0. ) + { + return par[0]; + } + Double_t f = par[0]*TMath::Gaus(x[0],par[1],par[2]); + + return f; +} + +Double_t MbdSig::TwoTemplateFcn(const Double_t* x, const Double_t* par) +{ + Double_t f = TemplateFcn(x,par) + TemplateFcn(x,par+2); + return f; +} + Double_t MbdSig::TemplateFcn(const Double_t* x, const Double_t* par) { // par[0] is the amplitude (relative to the spline amplitude) @@ -1081,11 +1221,13 @@ Double_t MbdSig::TemplateFcn(const Double_t* x, const Double_t* par) } // reject points with very bad rms in shape + /* if (template_yrms[ilow] >= 1.0 || template_yrms[ihigh] >= 1.0) { TF1::RejectPoint(); // return f; } + */ // Reject points where ADC saturates int samp_point = static_cast(x[0]); @@ -1103,11 +1245,29 @@ Double_t MbdSig::TemplateFcn(const Double_t* x, const Double_t* par) } // sampmax>0 means fit to the peak near sampmax +// fitmode: +// 0 - no info or no fit +// 1 - regular template fit (shortened) +// 2 - two template fit +// 3 - two template fit, neg ampl 2nd template +// 4 - saturated template fit +// 5 - saturated and shortened template fit int MbdSig::FitTemplate( const Int_t sampmax ) { - //std::cout << PHWHERE << std::endl; //chiu - //_verbose = 100; // uncomment to see fits - //_verbose = 12; // don't see pedestal fits + //_verbose = 100; + //std::cout << PHWHERE << std::endl; + /* + if ( _evt_counter==2142 && _ch==92 ) + { + _verbose = 100; // uncomment to see fits + //_verbose = 12; // don't see pedestal fits + } + */ + + // Reset Fit Quality Parameters + f_chi2 = 0.; + f_ndf = 0.; + f_fitmode = 0; // Check if channel is empty if (gSubPulse->GetN() == 0) @@ -1124,31 +1284,44 @@ int MbdSig::FitTemplate( const Int_t sampmax ) int nsaturated = 0; for (int ipt=0; ipt 16370. ) + if ( rawsamps[ipt] > 16370. ) // don't trust adc near edge { nsaturated++; } } + /* - if ( nsaturated>2 && _ch==185 ) + if ( nsaturated>0 ) { _verbose = 12; } */ - if (_verbose > 0) { - std::cout << "Fitting ch " << _ch << std::endl; + std::cout << "Fitting ch sampmax " << _ch << "\t" << sampmax << std::endl; } // Get x and y of maximum Double_t x_at_max{-1.}; Double_t ymax{0.}; - if ( sampmax>=0 ) + if ( sampmax>0 ) { - gSubPulse->GetPoint(sampmax, x_at_max, ymax); - if ( nsaturated<=3 ) + for (int isamp=sampmax-1; isamp<=sampmax+1; isamp++) + { + if ( (isamp>=gSubPulse->GetN()) ) + { + continue; + } + double adcval = gSubPulse->GetPointY(isamp); + if ( adcval>ymax ) + { + ymax = adcval; + x_at_max = isamp; + } + } + + if ( nsaturated==0 ) { x_at_max -= 2.0; } @@ -1176,6 +1349,7 @@ int MbdSig::FitTemplate( const Int_t sampmax ) gSubPulse->Draw("ap"); gSubPulse->GetHistogram()->SetTitle(gSubPulse->GetName()); gPad->SetGridy(1); + gPad->SetGridx(1); PadUpdate(); } @@ -1183,22 +1357,17 @@ int MbdSig::FitTemplate( const Int_t sampmax ) return 1; } + // Start with fit over early part of waveform to reduce pileup and afterpulse effects template_fcn->SetParameters(ymax, x_at_max); - // template_fcn->SetParLimits(1, fit_min_time, fit_max_time); - // template_fcn->SetParLimits(1, 3, 15); - // template_fcn->SetRange(template_min_xrange,template_max_xrange); - if ( nsaturated<=3 ) + if ( nsaturated==0 ) { - template_fcn->SetRange(0, _nsamples); + template_fcn->SetRange(0, x_at_max+4.2); + f_fitmode = 1; } else { - template_fcn->SetRange(0, sampmax + nsaturated - 0.5); - } - - if ( gSubPulse->GetN()==0 )//chiu - { - std::cout << PHWHERE << " gSubPulse 0" << std::endl; + template_fcn->SetRange(0, sampmax + nsaturated + 0.5); + f_fitmode = 4; } if (_verbose == 0) @@ -1214,48 +1383,133 @@ int MbdSig::FitTemplate( const Int_t sampmax ) gSubPulse->GetHistogram()->SetTitle(gSubPulse->GetName()); gPad->SetGridy(1); PadUpdate(); - //std::cout << "doing fit2 " << _verbose << std::endl; - //std::cout << "doing fit3 " << _verbose << std::endl; //gSubPulse->Print("ALL"); } // Get fit parameters f_ampl = template_fcn->GetParameter(0); f_time = template_fcn->GetParameter(1); - if ( f_time<0. || f_time>_nsamples ) + f_chi2 = template_fcn->GetChisquare(); + f_ndf = template_fcn->GetNDF(); + Double_t chi2ndf = 1e9; + if ( f_ndf>0. ) { - f_time = _nsamples*0.5; // bad fit last time + chi2ndf = f_chi2/f_ndf; } - // refit with new range to exclude after-pulses - template_fcn->SetParameters( f_ampl, f_time ); - if ( nsaturated<=3 ) + // Good fit + if ( f_ndf>6. && chi2ndf<5. ) { - template_fcn->SetRange( 0., f_time+4.0 ); + h_chi2ndf->Fill( chi2ndf ); + + _verbose = 0; + return 1; } - else + + /* + _verbose = 100; + if ( _verbose ) { - template_fcn->SetRange( 0., f_time+nsaturated+0.8 ); + PrintResiduals(gSubPulse,template_fcn); } + */ - if (_verbose == 0) + // fit was bad, refit with two templates + if ( nsaturated==0 ) { - //std::cout << PHWHERE << std::endl; - int fit_status = gSubPulse->Fit(template_fcn, "RNQ"); - if ( fit_status<0 ) + //_verbose = 100; + f_fitmode = 2; + + if ( _verbose ) { - std::cout << PHWHERE << "\t" << fit_status << std::endl; - gSubPulse->Print("ALL"); + std::cout << "BADFIT " << _evt_counter << "\t" << _ch << "\t" << sampmax << "\t" << f_ampl << "\t" << f_time + << "\t" << chi2ndf << std::endl; gSubPulse->Draw("ap"); - gSubPulse->Fit(template_fcn, "R"); - std::cout << "ampl time before refit " << f_ampl << "\t" << f_time << std::endl; - f_ampl = template_fcn->GetParameter(0); - f_time = template_fcn->GetParameter(1); - std::cout << "ampl time after refit " << f_ampl << "\t" << f_time << std::endl; + template_fcn->Draw("same"); PadUpdate(); - std::string junk; - std::cin >> junk; } + + twotemplate_fcn->SetParameters(ymax,x_at_max,ymax,10); + twotemplate_fcn->SetRange(0,_nsamples-0.9); + + if (_verbose == 0) + { + gSubPulse->Fit(twotemplate_fcn, "RNQ"); + } + else + { + std::cout << "doing 2wave fit " << x_at_max << "\t" << ymax << std::endl; + gSubPulse->Fit(twotemplate_fcn, "R"); + gSubPulse->Draw("ap"); + gSubPulse->GetHistogram()->SetTitle(gSubPulse->GetName()); + gPad->SetGridy(1); + PadUpdate(); + //gSubPulse->Print("ALL"); + } + + // Check two component fit + Double_t ampl1 = twotemplate_fcn->GetParameter(0); + Double_t time1 = twotemplate_fcn->GetParameter(1); + Double_t ampl2 = twotemplate_fcn->GetParameter(2); + Double_t time2 = twotemplate_fcn->GetParameter(3); + Double_t newchi2 = twotemplate_fcn->GetChisquare(); + Double_t newndf = twotemplate_fcn->GetNDF(); + Double_t newchi2ndf = 0.; + if ( newndf>0.) + { + newchi2ndf = newchi2/newndf; + } + + // bad two component fit, use original fit + if ( time2>15. || ampl1<0 || ampl2<0. || newchi2ndf>chi2ndf) + { + if (_verbose) + { + std::cout << "Using original " << newchi2ndf << std::endl; + PrintResiduals(gSubPulse,twotemplate_fcn); + } + f_fitmode = 3; + h_chi2ndf->Fill( chi2ndf ); + _verbose = 0; + return 1; + } + + // Get new fit parameters (pick fit closest in time to first fit + if ( std::abs(f_time-time1) < std::abs(f_time-time2) ) + { + f_ampl = ampl1; + f_time = time1; + } + else + { + f_ampl = ampl2; + f_time = time2; + } + + f_chi2 = newchi2; + f_ndf = newndf; + + // poor fit + if ( _verbose && f_ndf>6. && (f_chi2/f_ndf) > 5. ) + { + std::cout << "double fit high chi2/ndf " << f_chi2/f_ndf << std::endl; + PrintResiduals(gSubPulse,twotemplate_fcn); + PadUpdate(); + } + + h_chi2ndf->Fill( f_chi2/f_ndf ); + _verbose = 0; + return 1; + } + + // Try a refit of saturated waveform with different range + template_fcn->SetParameters(ymax, x_at_max); + template_fcn->SetRange( 0., _nsamples-0.5 ); + + if (_verbose == 0) + { + //std::cout << PHWHERE << std::endl; + gSubPulse->Fit(template_fcn, "RNQ"); } else { @@ -1267,24 +1521,34 @@ int MbdSig::FitTemplate( const Int_t sampmax ) std::cout << "ampl time after refit " << f_ampl << "\t" << f_time << std::endl; } - f_ampl = template_fcn->GetParameter(0); - f_time = template_fcn->GetParameter(1); + // pick lower chi2/ndf of two saturated fits + Double_t newchi2 = template_fcn->GetChisquare(); + Double_t newndf = template_fcn->GetNDF(); + if ( (newchi2/newndf)GetParameter(0); + f_time = template_fcn->GetParameter(1); + f_chi2 = newchi2; + f_ndf = newndf; + f_fitmode = 5; + } + + h_chi2ndf->Fill( f_chi2/f_ndf ); - //if ( f_time<0 || f_time>30 ) - //if ( (_ch==185||_ch==155||_ch==249) && (fabs(f_ampl) > 44000.) ) - //double chi2 = template_fcn->GetChisquare(); - //double ndf = template_fcn->GetNDF(); - //if ( (_ch==185||_ch==155||_ch==249) && (fabs(chi2/ndf) > 100.) && nsaturated > 3) - if (_verbose > 0 && fabs(f_ampl) > 0.) + if (_verbose > 0 && std::abs(f_ampl) > 0.) { _verbose = 12; std::cout << "FitTemplate " << _ch << "\t" << f_ampl << "\t" << f_time << std::endl; std::cout << " " << template_fcn->GetChisquare()/template_fcn->GetNDF() << std::endl; gSubPulse->Draw("ap"); gSubPulse->GetHistogram()->SetTitle(gSubPulse->GetName()); + gPad->SetGridx(1); gPad->SetGridy(1); template_fcn->SetLineColor(4); template_fcn->Draw("same"); + + PrintResiduals(gSubPulse,template_fcn); + PadUpdate(); } @@ -1323,6 +1587,16 @@ int MbdSig::SetTemplate(const std::vector& shape, const std::vectorSetParName(1, "time"); SetTemplateSize(900, 1000, -10., 20.); + name = "twotemplate_fcn"; + name += _ch; + twotemplate_fcn = new TF1(name, this, &MbdSig::TwoTemplateFcn, 0, _nsamples, 4, "MbdSig", "TwoTemplateFcn"); + twotemplate_fcn->SetLineColor(3); + twotemplate_fcn->SetParameters(1, 6, 1,8); + twotemplate_fcn->SetParName(0, "ampl"); + twotemplate_fcn->SetParName(1, "time"); + twotemplate_fcn->SetParName(2, "ampl2"); + twotemplate_fcn->SetParName(3, "time2"); + if (_verbose) { std::cout << "SHAPE " << _ch << std::endl; @@ -1334,3 +1608,22 @@ int MbdSig::SetTemplate(const std::vector& shape, const std::vectorGetRange(smin,smax); + + double x{0}; + double y{0}; + for (double samp=0; samp<=smax; samp+=1.0) + { + g->GetPoint(int(samp),x,y); + double yerr = g->GetErrorY(int(samp)); + double resid = (y - f->Eval(x))/yerr; + std::cout << samp << "\t" << x << "\t" << resid << "\t" << y << "\t" << f->Eval(x) << "\t" << yerr << std::endl; + } +} + diff --git a/offline/packages/mbd/MbdSig.h b/offline/packages/mbd/MbdSig.h index 0b8b420ffa..69d5ca7bfd 100644 --- a/offline/packages/mbd/MbdSig.h +++ b/offline/packages/mbd/MbdSig.h @@ -31,6 +31,9 @@ class MbdSig void SetNSamples( const int s ) { _nsamples = s; } void SetY(const Float_t *y, const int invert = 1); void SetXY(const Float_t *x, const Float_t *y, const int invert = 1); + void SetEvtNum(const int evtnum) { _evt_counter = evtnum; } + + int GetNSamples() { return _nsamples; } void SetCalib(MbdCalib *mcal); @@ -39,6 +42,10 @@ class MbdSig Double_t GetAmpl() { return f_ampl; } Double_t GetTime() { return f_time; } Double_t GetIntegral() { return f_integral; } + Double_t GetChi2() { return f_chi2; } + Double_t GetNDF() { return f_ndf; } + Double_t GetChi2NDF() { return (f_ndf > 0.) ? (f_chi2 / f_ndf) : std::numeric_limits::quiet_NaN(); } + UShort_t GetFitInfo() { return f_fitmode; } /** * Fill hists from data between minsamp and maxsamp bins @@ -108,11 +115,17 @@ class MbdSig // Double_t FitPulse(); void SetTimeOffset(const Double_t o) { f_time_offset = o; } + Double_t SignalTail(const Double_t *x, const Double_t *par); Double_t TemplateFcn(const Double_t *x, const Double_t *par); + Double_t TwoTemplateFcn(const Double_t *x, const Double_t *par); TF1 *GetTemplateFcn() { return template_fcn; } void SetMinMaxFitTime(const Double_t mintime, const Double_t maxtime); + void PrintResiduals(TGraphErrors *g, TF1 *f); + void WritePedHist(); + void WritePedvsEvent(); + void WriteChi2Hist(); void DrawWaveform(); /// Draw Subtracted Waveform void PadUpdate() const; @@ -142,6 +155,10 @@ class MbdSig Double_t f_integral{0.}; /** integral */ + UShort_t f_fitmode{0}; + Double_t f_chi2{0.}; + Double_t f_ndf{0.}; + TH1 *hRawPulse{nullptr}; //! TH1 *hSubPulse{nullptr}; //! TH1 *hpulse{nullptr}; //! @@ -150,22 +167,21 @@ class MbdSig TGraphErrors *gpulse{nullptr}; //! /** for CalcPed0 */ - //std::unique_ptr ped0stats{nullptr}; //! - MbdRunningStats *ped0stats{nullptr}; //! - TH1 *hPed0{nullptr}; //! all events - TH1 *hPedEvt{nullptr}; //! evt-by-event pedestal + MbdRunningStats *ped0stats{nullptr}; //! running pedestal + TH1 *hPed0{nullptr}; //! all events + TH1 *hPedEvt{nullptr}; //! evt-by-event pedestal + TGraphErrors *gPedvsEvent{nullptr}; //! Keep track of pedestal vs evtnum TF1 *ped_fcn{nullptr}; - TF1 *ped_tail{nullptr}; //! tail of prev signal Double_t ped0{0.}; //! Double_t ped0rms{0.}; //! - int use_ped0{0}; //! whether to apply ped0 - Int_t minped0samp{-9999}; //! min sample for event-by-event ped, inclusive - Int_t maxped0samp{-9999}; //! max sample for event-by-event ped, inclusive + int use_ped0{0}; //! whether to apply ped0 + Int_t minped0samp{-9999}; //! min sample for event-by-event ped, inclusive + Int_t maxped0samp{-9999}; //! max sample for event-by-event ped, inclusive Double_t minped0x{0.}; //! min x for event-by-event ped, inclusive Double_t maxped0x{0.}; //! max x for event-by-event ped, inclusive - Double_t ped_presamp{}; //! presamples for ped calculation - Double_t ped_presamp_nsamps{}; //! num of presamples for ped calculation - Double_t ped_presamp_maxsamp{-1}; //! a peak sample for ped calc (-1 = use max) + Double_t ped_presamp{}; //! presamples for ped calculation + Double_t ped_presamp_nsamps{}; //! num of presamples for ped calculation + Double_t ped_presamp_maxsamp{-1}; //! a peak sample for ped calc (-1 = use max) /** for time calibration */ // Double_t time_calib; @@ -180,21 +196,20 @@ class MbdSig Int_t template_npointsy{0}; Double_t template_begintime{0.}; Double_t template_endtime{0.}; - // Double_t template_min_good_amplitude{20.}; //! for template, in original units of waveform data - // Double_t template_max_good_amplitude{4080.}; //! for template, in original units of waveform data - // Double_t template_min_xrange{0.}; //! for template, in original units of waveform data - // Double_t template_max_xrange{0.}; //! for template, in original units of waveform data std::vector template_y; std::vector template_yrms; TF1 *template_fcn{nullptr}; + TF1 *twotemplate_fcn{nullptr}; Double_t fit_min_time{}; //! min time for fit, in original units of waveform data Double_t fit_max_time{}; //! max time for fit, in original units of waveform data std::ofstream *_pileupfile{nullptr}; // for writing out waveforms from prev. crossing pileup // use for calibrating out the tail from these events + TH1 *h_chi2ndf{nullptr}; //! for eval int _verbose{0}; + bool _pedstudyflag{false}; }; #endif // __MBDSIG_H__ diff --git a/offline/packages/micromegas/MicromegasClusterizer.cc b/offline/packages/micromegas/MicromegasClusterizer.cc index c57d6ed3f5..5da9264c11 100644 --- a/offline/packages/micromegas/MicromegasClusterizer.cc +++ b/offline/packages/micromegas/MicromegasClusterizer.cc @@ -157,8 +157,13 @@ int MicromegasClusterizer::process_event(PHCompositeNode *topNode) // geometry PHG4CylinderGeomContainer* geonode = nullptr; for( std::string geonodename: {"CYLINDERGEOM_MICROMEGAS_FULL", "CYLINDERGEOM_MICROMEGAS" } ) - { if(( geonode = findNode::getClass(topNode, geonodename.c_str()) )) { break; -}} + { + // try load node and test + geonode = findNode::getClass(topNode, geonodename); + if( geonode ) { break;} + } + + //ma assert(geonode); // hitset container @@ -182,8 +187,8 @@ int MicromegasClusterizer::process_event(PHCompositeNode *topNode) for( auto hitset_it = hitset_range.first; hitset_it != hitset_range.second; ++hitset_it ) { // get hitset, key and layer - TrkrHitSet* hitset = hitset_it->second; - const TrkrDefs::hitsetkey hitsetkey = hitset_it->first; + const auto& [hitsetkey, hitset] = *hitset_it; + const auto layer = TrkrDefs::getLayer(hitsetkey); const auto tileid = MicromegasDefs::getTileId(hitsetkey); @@ -215,17 +220,32 @@ int MicromegasClusterizer::process_event(PHCompositeNode *topNode) using range_list_t = std::vector; range_list_t ranges; - // loop over hits - const auto hit_range = hitset->getHits(); + // Make a local copy of hitsets, sorted along strips + /* when there are multiple hits on the same strip, only the first one (in time) is kept */ + class StripSortFtor + { + public: + bool operator() ( const TrkrDefs::hitkey& first, const TrkrDefs::hitkey& second ) const + { return MicromegasDefs::getStrip(first) < MicromegasDefs::getStrip(second); } + }; + + using LocalMap = std::map; + LocalMap local_hitmap; + + { + // loop over hits + const auto hit_range = hitset->getHits(); + std::copy( hit_range.first, hit_range.second, std::inserter(local_hitmap, local_hitmap.end()) ); + } // keep track of first iterator of runing cluster - auto begin = hit_range.first; + auto begin = local_hitmap.begin(); // keep track of previous strip uint16_t previous_strip = 0; bool first = true; - for( auto hit_it = hit_range.first; hit_it != hit_range.second; ++hit_it ) + for( auto hit_it = local_hitmap.begin(); hit_it != local_hitmap.end(); ++hit_it ) { // get hit key @@ -233,18 +253,11 @@ int MicromegasClusterizer::process_event(PHCompositeNode *topNode) // get strip number const auto strip = MicromegasDefs::getStrip( hitkey ); - - if( first ) + if( !first && (strip - previous_strip > 1 ) ) { - previous_strip = strip; - first = false; - continue; - - } else if( strip - previous_strip > 1 ) { - // store current cluster range - ranges.push_back( std::make_pair( begin, hit_it ) ); + ranges.emplace_back( begin, hit_it ); // reinitialize begin of next cluster range begin = hit_it; @@ -252,13 +265,13 @@ int MicromegasClusterizer::process_event(PHCompositeNode *topNode) } // update previous strip + first = false; previous_strip = strip; } // store last cluster - if( begin != hit_range.second ) { ranges.push_back( std::make_pair( begin, hit_range.second ) ); -} + if( begin != local_hitmap.end() ) { ranges.emplace_back( begin, local_hitmap.end() ); } // initialize cluster count int cluster_count = 0; diff --git a/offline/packages/micromegas/MicromegasCombinedDataDecoder.cc b/offline/packages/micromegas/MicromegasCombinedDataDecoder.cc index a5269617f7..1c34357280 100644 --- a/offline/packages/micromegas/MicromegasCombinedDataDecoder.cc +++ b/offline/packages/micromegas/MicromegasCombinedDataDecoder.cc @@ -203,13 +203,14 @@ int MicromegasCombinedDataDecoder::process_event(PHCompositeNode* topNode) // loop over sample_range find maximum const auto sample_range = std::make_pair(rawhit->get_sample_begin(), rawhit->get_sample_end()); - std::vector adc_list; + using sample_pair_t = std::pair; + std::vector adc_list; for (auto is = std::max(m_sample_min, sample_range.first); is < std::min(m_sample_max, sample_range.second); ++is) { const uint16_t adc = rawhit->get_adc(is); if (adc != MicromegasDefs::m_adc_invalid) { - adc_list.push_back(adc); + adc_list.emplace_back(is, adc); } } @@ -220,16 +221,18 @@ int MicromegasCombinedDataDecoder::process_event(PHCompositeNode* topNode) // get max adc value in range /* TODO: use more advanced signal processing */ - auto max_adc = *std::max_element(adc_list.begin(), adc_list.end()); + auto max_adc = *std::max_element(adc_list.begin(), adc_list.end(), + [](const sample_pair_t& first, const sample_pair_t& second) + { return first.second < second.second; } ); // compare to hard min_adc value - if (max_adc < m_min_adc) + if (max_adc.second < m_min_adc) { continue; } // compare to threshold - if (max_adc < pedestal + m_n_sigma * rms) + if (max_adc.second < pedestal + m_n_sigma * rms) { continue; } @@ -243,7 +246,8 @@ int MicromegasCombinedDataDecoder::process_event(PHCompositeNode* topNode) << " tile: " << tile << " channel: " << channel << " strip: " << strip - << " adc: " << max_adc + << " sample: " << max_adc.first + << " adc: " << max_adc.second << std::endl; } @@ -251,19 +255,19 @@ int MicromegasCombinedDataDecoder::process_event(PHCompositeNode* topNode) const auto hitset_it = trkrhitsetcontainer->findOrAddHitSet(hitsetkey); // generate hit key - const TrkrDefs::hitkey hitkey = MicromegasDefs::genHitKey(strip); + const TrkrDefs::hitkey hitkey = MicromegasDefs::genHitKey(strip, max_adc.first); // find existing hit, or create - auto hit = hitset_it->second->getHit(hitkey); + auto* hit = hitset_it->second->getHit(hitkey); if (hit) { - // std::cout << "MicromegasCombinedDataDecoder::process_event - duplicated hit, hitsetkey: " << hitsetkey << " strip: " << strip << std::endl; + std::cout << "MicromegasCombinedDataDecoder::process_event - duplicated hit, hitsetkey: " << hitsetkey << " strip: " << strip << std::endl; continue; } // create hit, assign adc and insert in hitset hit = new TrkrHitv2; - hit->setAdc(max_adc); + hit->setAdc(max_adc.second); hitset_it->second->addHitSpecificKey(hitkey, hit); // increment counter diff --git a/offline/packages/micromegas/MicromegasCombinedDataDecoder.h b/offline/packages/micromegas/MicromegasCombinedDataDecoder.h index 32eebc56e0..33033f1992 100644 --- a/offline/packages/micromegas/MicromegasCombinedDataDecoder.h +++ b/offline/packages/micromegas/MicromegasCombinedDataDecoder.h @@ -49,10 +49,10 @@ class MicromegasCombinedDataDecoder : public SubsysReco /** This removes faulty channels for which calibration has failed */ void set_min_adc(double value) { m_min_adc = value; } - /// set min sample for noise estimation + /// set min sample for signal hits void set_sample_min(uint16_t value) { m_sample_min = value; } - /// set min sample for noise estimation + /// set max sample for signal hits void set_sample_max(uint16_t value) { m_sample_max = value; } private: @@ -85,7 +85,7 @@ class MicromegasCombinedDataDecoder : public SubsysReco uint16_t m_sample_min = 0; /// max sample for signal - uint16_t m_sample_max = 100; + uint16_t m_sample_max = 1024; /// keep track of number of hits per hitsetid using hitcountmap_t = std::map; diff --git a/offline/packages/micromegas/MicromegasDefs.cc b/offline/packages/micromegas/MicromegasDefs.cc index 0766d78b8e..8a35461492 100644 --- a/offline/packages/micromegas/MicromegasDefs.cc +++ b/offline/packages/micromegas/MicromegasDefs.cc @@ -25,11 +25,12 @@ namespace * 8 - 16 segmentation type * 0 - 8 tile id */ - static constexpr unsigned int kBitShiftSegmentation = 8; - static constexpr unsigned int kBitShiftTileId = 0; + constexpr unsigned int kBitShiftSegmentation = 8; + constexpr unsigned int kBitShiftTileId = 0; //! bit shift for hit key - static constexpr unsigned int kBitShiftStrip = 0; + constexpr unsigned int kBitShiftStrip = 0; + constexpr unsigned int kBitShiftSample = 8; } @@ -41,10 +42,10 @@ namespace MicromegasDefs { TrkrDefs::hitsetkey key = TrkrDefs::genHitSetKey(TrkrDefs::TrkrId::micromegasId, layer); - TrkrDefs::hitsetkey tmp = to_underlying_type(type); + TrkrDefs::hitsetkey tmp = to_underlying_type(type)&0x1U; key |= (tmp << kBitShiftSegmentation); - tmp = tile; + tmp = tile&0xFFU; key |= (tmp << kBitShiftTileId); return key; @@ -54,28 +55,36 @@ namespace MicromegasDefs SegmentationType getSegmentationType(TrkrDefs::hitsetkey key) { TrkrDefs::hitsetkey tmp = (key >> kBitShiftSegmentation); - return static_cast(tmp); + return static_cast(tmp&0x1U); } //________________________________________________________________ uint8_t getTileId(TrkrDefs::hitsetkey key) { TrkrDefs::hitsetkey tmp = (key >> kBitShiftTileId); - return tmp; + return tmp&0xFFU; } //________________________________________________________________ - TrkrDefs::hitkey genHitKey(uint16_t strip) + TrkrDefs::hitkey genHitKey(uint16_t strip, uint16_t sample) { - TrkrDefs::hitkey key = strip << kBitShiftStrip; - return key; + const TrkrDefs::hitkey key = (strip&0xFFU) << kBitShiftStrip; + const TrkrDefs::hitkey tmp = (sample&0xFFFFU) << kBitShiftSample; + return key|tmp; } //________________________________________________________________ - uint16_t getStrip( TrkrDefs::hitkey key ) + uint8_t getStrip( TrkrDefs::hitkey key ) { TrkrDefs::hitkey tmp = (key >> kBitShiftStrip); - return tmp; + return tmp & 0xFFU; + } + + //________________________________________________________________ + uint16_t getSample( TrkrDefs::hitkey key ) + { + TrkrDefs::hitkey tmp = (key >> kBitShiftSample); + return tmp & 0xFFFFU; } //________________________________________________________________ diff --git a/offline/packages/micromegas/MicromegasDefs.h b/offline/packages/micromegas/MicromegasDefs.h index c95fdffd72..b206b8f895 100644 --- a/offline/packages/micromegas/MicromegasDefs.h +++ b/offline/packages/micromegas/MicromegasDefs.h @@ -60,11 +60,15 @@ namespace MicromegasDefs /*! * @brief Generate a hitkey from strip index inside tile * @param[in] strip strip index + * @param[in] sample sample index */ - TrkrDefs::hitkey genHitKey(uint16_t strip ); + TrkrDefs::hitkey genHitKey(uint16_t strip, uint16_t sample = 0 ); //! get strip from hit key - uint16_t getStrip(TrkrDefs::hitkey); + uint8_t getStrip(TrkrDefs::hitkey); + + //! get sample from hit key + uint16_t getSample(TrkrDefs::hitkey); /*! * @brief Get the segmentation type from cluster key diff --git a/offline/packages/mvtx/CylinderGeom_Mvtx.cc b/offline/packages/mvtx/CylinderGeom_Mvtx.cc index e220d1474d..ab22c80bdc 100644 --- a/offline/packages/mvtx/CylinderGeom_Mvtx.cc +++ b/offline/packages/mvtx/CylinderGeom_Mvtx.cc @@ -8,7 +8,6 @@ #include #include // for operator<<, basic_ostream::operator<<, basic_... -using namespace std; using Segmentation = SegmentationAlpide; CylinderGeom_Mvtx::CylinderGeom_Mvtx( @@ -89,7 +88,7 @@ void CylinderGeom_Mvtx::get_sensor_indices_from_world_coords(std::vector double chip_delta_z = (inner_loc_chip_in_module[8][2] - inner_loc_chip_in_module[0][2]) / 8.0; // int chip_tmp = (int) (world[2]/chip_delta_z) + 4; // 0-9 int chip_tmp = round(world[2] / chip_delta_z) + 4; // 0-9 - // std::cout << " z " << world[2] << " chip_delta_z " << chip_delta_z << " chip_tmp " << chip_tmp << endl; + // std::cout << " z " << world[2] << " chip_delta_z " << chip_delta_z << " chip_tmp " << chip_tmp << std::endl; stave_index = stave_tmp; chip_index = chip_tmp; @@ -102,15 +101,15 @@ bool CylinderGeom_Mvtx::get_pixel_from_local_coords(TVector3 sensor_local, int& double EPS = 5e-6; if (fabs(fabs(sensor_local.X()) - SegmentationAlpide::ActiveMatrixSizeRows / 2.F) < EPS) { - // cout << " Adjusting X, before X= " << sensor_local.X() << endl; + // std::cout << " Adjusting X, before X= " << sensor_local.X() << std::endl; sensor_local.SetX(((sensor_local.X() < 0) ? -1 : 1) * (SegmentationAlpide::ActiveMatrixSizeRows / 2.F - EPS)); - // cout << " Adjusting X, after X= " << sensor_local.X() << endl; + // std::cout << " Adjusting X, after X= " << sensor_local.X() << std::endl; } if (fabs(fabs(sensor_local.Z()) - SegmentationAlpide::ActiveMatrixSizeCols / 2.F) < EPS) { - // cout << " Adjusting Z, before Z= " << sensor_local.Z() << endl; + // std::cout << " Adjusting Z, before Z= " << sensor_local.Z() << std::endl; sensor_local.SetZ(((sensor_local.Z() < 0) ? -1 : 1) * (SegmentationAlpide::ActiveMatrixSizeCols / 2.F - EPS)); - // cout << " Adjusting Z, after Z= " << sensor_local.Z() << endl; + // std::cout << " Adjusting Z, after Z= " << sensor_local.Z() << std::endl; } // YCM (2020-01-02): go from sensor to chip local coords TVector3 in_chip = sensor_local; @@ -122,21 +121,22 @@ bool CylinderGeom_Mvtx::get_pixel_from_local_coords(TVector3 sensor_local, int& int CylinderGeom_Mvtx::get_pixel_from_local_coords(const TVector3& sensor_local) { - int Ngridx, Ngridz; + int Ngridx; + int Ngridz; bool px_in = get_pixel_from_local_coords(sensor_local, Ngridx, Ngridz); if (!px_in) { - cout << PHWHERE + std::cout << PHWHERE << " Pixel is out sensor. (" << sensor_local.X() << ", " << sensor_local.Y() << ", " << sensor_local.Z() << ")." - << endl; + << std::endl; } if (Ngridx < 0 || Ngridx >= get_NX() || Ngridz < 0 || Ngridz >= get_NZ()) { - cout << PHWHERE << "Wrong pixel value X= " << Ngridx << " and Z= " << Ngridz << endl; + std::cout << PHWHERE << "Wrong pixel value X= " << Ngridx << " and Z= " << Ngridz << std::endl; } // numbering starts at zero @@ -157,8 +157,8 @@ TVector3 CylinderGeom_Mvtx::get_local_coords_from_pixel(int iRow, int iCol) bool check = SegmentationAlpide::detectorToLocal((float) iRow, (float) iCol, local); if (!check) { - cout << PHWHERE << "Pixel coord ( " << iRow << ", " << iCol << " )" - << "out of range" << endl; + std::cout << PHWHERE << "Pixel coord ( " << iRow << ", " << iCol << " )" + << "out of range" << std::endl; } // Transform location in chip to location in sensors TVector3 trChipToSens(loc_sensor_in_chip[0], @@ -177,7 +177,7 @@ void CylinderGeom_Mvtx::identify(std::ostream& os) const << ", pixel_x: " << pixel_x << ", pixel_z: " << pixel_z << ", pixel_thickness: " << pixel_thickness - << endl; + << std::endl; return; } @@ -192,17 +192,17 @@ int CylinderGeom_Mvtx::get_NX() const return SegmentationAlpide::NRows; } -int CylinderGeom_Mvtx::get_pixel_X_from_pixel_number(int NXZ) +int CylinderGeom_Mvtx::get_pixel_X_from_pixel_number(int NXZ) const { return NXZ % get_NX(); } -int CylinderGeom_Mvtx::get_pixel_Z_from_pixel_number(int NXZ) +int CylinderGeom_Mvtx::get_pixel_Z_from_pixel_number(int NXZ) const { return NXZ / get_NX(); } -int CylinderGeom_Mvtx::get_pixel_number_from_xbin_zbin(int xbin, int zbin) // obsolete +int CylinderGeom_Mvtx::get_pixel_number_from_xbin_zbin(int xbin, int zbin) const // obsolete { return xbin + zbin * get_NX(); } diff --git a/offline/packages/mvtx/CylinderGeom_Mvtx.h b/offline/packages/mvtx/CylinderGeom_Mvtx.h index e28da2c594..047673a549 100644 --- a/offline/packages/mvtx/CylinderGeom_Mvtx.h +++ b/offline/packages/mvtx/CylinderGeom_Mvtx.h @@ -13,7 +13,7 @@ class CylinderGeom_Mvtx : public PHG4CylinderGeom public: CylinderGeom_Mvtx( int layer, - int in_Nstaves, + int in_N_staves, double in_layer_nominal_radius, double in_phistep, double in_phitilt, @@ -31,7 +31,7 @@ class CylinderGeom_Mvtx : public PHG4CylinderGeom { } - ~CylinderGeom_Mvtx() override {} + ~CylinderGeom_Mvtx() override = default; // from PHObject void identify(std::ostream& os = std::cout) const override; @@ -53,11 +53,11 @@ class CylinderGeom_Mvtx : public PHG4CylinderGeom TVector3 get_local_coords_from_pixel(int NXZ); TVector3 get_local_coords_from_pixel(int iRow, int iCol); - int get_pixel_X_from_pixel_number(int NXZ); + int get_pixel_X_from_pixel_number(int NXZ) const; - int get_pixel_Z_from_pixel_number(int NXZ); + int get_pixel_Z_from_pixel_number(int NXZ) const; - int get_pixel_number_from_xbin_zbin(int xbin, int zbin); // obsolete + int get_pixel_number_from_xbin_zbin(int xbin, int zbin) const; // obsolete double get_stave_phi_tilt() const { return stave_phi_tilt; } double get_stave_phi_0() const { return stave_phi_0; } diff --git a/offline/packages/mvtx/MvtxClusterPruner.cc b/offline/packages/mvtx/MvtxClusterPruner.cc index 24d41db63d..456b302dd9 100644 --- a/offline/packages/mvtx/MvtxClusterPruner.cc +++ b/offline/packages/mvtx/MvtxClusterPruner.cc @@ -12,108 +12,116 @@ #include #include -#include #include +#include -#include #include +#include namespace { //! range adaptor to be able to use range-based for loop - template class range_adaptor + template + class range_adaptor { - public: - range_adaptor( const T& range ):m_range(range){} - const typename T::first_type& begin() {return m_range.first;} - const typename T::second_type& end() {return m_range.second;} - private: + public: + explicit range_adaptor(const T& range) + : m_range(range) + { + } + const typename T::first_type& begin() { return m_range.first; } + const typename T::second_type& end() { return m_range.second; } + + private: T m_range; }; // print cluster information - void print_cluster_information( TrkrDefs::cluskey ckey, TrkrCluster* cluster ) + void print_cluster_information(TrkrDefs::cluskey ckey, TrkrCluster* cluster) { - if( cluster ) + if (cluster) { std::cout << " MVTX cluster: " << ckey - << " position: (" << cluster->getLocalX() << ", " << cluster->getLocalY() << ")" - << " size: " << (int)cluster->getSize() - << " layer: " << (int)TrkrDefs::getLayer(ckey) - << " stave: " << (int) MvtxDefs::getStaveId(ckey) - << " chip: " << (int)MvtxDefs::getChipId(ckey) - << " strobe: " << (int)MvtxDefs::getStrobeId(ckey) - << " index: " << (int)TrkrDefs::getClusIndex(ckey) - << std::endl; - } else { + << " position: (" << cluster->getLocalX() << ", " << cluster->getLocalY() << ")" + << " size: " << (int) cluster->getSize() + << " layer: " << (int) TrkrDefs::getLayer(ckey) + << " stave: " << (int) MvtxDefs::getStaveId(ckey) + << " chip: " << (int) MvtxDefs::getChipId(ckey) + << " strobe: " << MvtxDefs::getStrobeId(ckey) + << " index: " << (int) TrkrDefs::getClusIndex(ckey) + << std::endl; + } + else + { std::cout << " MVTX cluster: " << ckey - << " layer: " << (int)TrkrDefs::getLayer(ckey) - << " stave: " << (int) MvtxDefs::getStaveId(ckey) - << " chip: " << (int)MvtxDefs::getChipId(ckey) - << " strobe: " << (int)MvtxDefs::getStrobeId(ckey) - << " index: " << (int)TrkrDefs::getClusIndex(ckey) - << std::endl; + << " layer: " << (int) TrkrDefs::getLayer(ckey) + << " stave: " << (int) MvtxDefs::getStaveId(ckey) + << " chip: " << (int) MvtxDefs::getChipId(ckey) + << " strobe: " << MvtxDefs::getStrobeId(ckey) + << " index: " << (int) TrkrDefs::getClusIndex(ckey) + << std::endl; } } using hitkeyset_t = std::set; - using clustermap_t = std::map; + using clustermap_t = std::map; -} +} // namespace //_____________________________________________________________________________ -MvtxClusterPruner::MvtxClusterPruner(const std::string &name) +MvtxClusterPruner::MvtxClusterPruner(const std::string& name) : SubsysReco(name) { } //_____________________________________________________________________________ -int MvtxClusterPruner::InitRun(PHCompositeNode * /*topNode*/) +int MvtxClusterPruner::InitRun(PHCompositeNode* /*topNode*/) { std::cout << "MvtxClusterPruner::InitRun - m_use_strict_matching: " << m_use_strict_matching << std::endl; return Fun4AllReturnCodes::EVENT_OK; } //_____________________________________________________________________________ -int MvtxClusterPruner::process_event(PHCompositeNode *topNode) +int MvtxClusterPruner::process_event(PHCompositeNode* topNode) { // load relevant nodes - auto trkrclusters = findNode::getClass(topNode, "TRKR_CLUSTER"); - if( !trkrclusters ) + auto* trkrclusters = findNode::getClass(topNode, "TRKR_CLUSTER"); + if (!trkrclusters) { std::cout << "MvtxClusterPruner::process_event - TRKR_CLUSTER not found. Doing nothing" << std::endl; return Fun4AllReturnCodes::EVENT_OK; } - auto clusterhitassoc = findNode::getClass(topNode, "TRKR_CLUSTERHITASSOC"); - if( !clusterhitassoc ) + auto* clusterhitassoc = findNode::getClass(topNode, "TRKR_CLUSTERHITASSOC"); + if (!clusterhitassoc) { std::cout << "MvtxClusterPruner::process_event - TRKR_CLUSTERHITASSOC not found. Doing nothing" << std::endl; return Fun4AllReturnCodes::EVENT_OK; } // lambda method to create map of cluster keys and associated hits - auto get_cluster_map = [trkrclusters,clusterhitassoc]( TrkrDefs::hitsetkey key ) + auto get_cluster_map = [trkrclusters, clusterhitassoc](TrkrDefs::hitsetkey key) { clustermap_t out; // get all clusters for this hitsetkey - const auto cluster_range= trkrclusters->getClusters(key); - for( const auto& [ckey,cluster]:range_adaptor(cluster_range) ) + const auto cluster_range = trkrclusters->getClusters(key); + for (const auto& [ckey, cluster] : range_adaptor(cluster_range)) { // get associated hits const auto& hit_range = clusterhitassoc->getHits(ckey); hitkeyset_t hitkeys; - std::transform(hit_range.first, hit_range.second, std::inserter(hitkeys,hitkeys.end()), - [](const TrkrClusterHitAssoc::Map::value_type& pair ){ return pair.second; }); - out.emplace(ckey,std::move(hitkeys)); + std::transform(hit_range.first, hit_range.second, std::inserter(hitkeys, hitkeys.end()), + [](const TrkrClusterHitAssoc::Map::value_type& pair) + { return pair.second; }); + out.emplace(ckey, std::move(hitkeys)); } return out; }; // loop over MVTX hitset keys const auto hitsetkeys = trkrclusters->getHitSetKeys(TrkrDefs::mvtxId); - for( const auto& hitsetkey:hitsetkeys ) + for (const auto& hitsetkey : hitsetkeys) { // get layer, stave, chip and current strobe const auto layer = TrkrDefs::getLayer(hitsetkey); @@ -125,111 +133,109 @@ int MvtxClusterPruner::process_event(PHCompositeNode *topNode) const auto cluster_map1 = get_cluster_map(hitsetkey); // get clusters for the next strobe - int next_strobe = current_strobe+1; + int next_strobe = current_strobe + 1; const auto hitsetkey_next_strobe = MvtxDefs::genHitSetKey(layer, stave, chip, next_strobe); const auto clusterk_map2 = get_cluster_map(hitsetkey_next_strobe); // loop over clusters from first range - for( auto [ckey1,hitkeys1]:cluster_map1) + for (auto [ckey1, hitkeys1] : cluster_map1) { // increment counter ++m_cluster_counter_total; // get correcponding cluser - auto cluster1 = Verbosity() ? trkrclusters->findCluster(ckey1):nullptr; + auto* cluster1 = Verbosity() ? trkrclusters->findCluster(ckey1) : nullptr; // loop over clusters from second range - for( auto [ckey2,hitkeys2]:clusterk_map2) + for (auto [ckey2, hitkeys2] : clusterk_map2) { - auto cluster2 = Verbosity() ? trkrclusters->findCluster(ckey2):nullptr; + auto* cluster2 = Verbosity() ? trkrclusters->findCluster(ckey2) : nullptr; - if( m_use_strict_matching ) + if (m_use_strict_matching) { // see if hitsets are identical - if(hitkeys1 == hitkeys2) + if (hitkeys1 == hitkeys2) { // increment counter ++m_cluster_counter_deleted; - if( Verbosity() ) + if (Verbosity()) { std::cout << "Removing cluster "; - print_cluster_information( ckey2, cluster2); + print_cluster_information(ckey2, cluster2); std::cout << "Keeping cluster "; - print_cluster_information( ckey1, cluster1); + print_cluster_information(ckey1, cluster1); } // always remove second cluster trkrclusters->removeCluster(ckey2); break; } - - } else { - + } + else + { // make sure first set is larger than second const bool swapped = hitkeys2.size() > hitkeys1.size(); - if( swapped ) { std::swap(hitkeys2,hitkeys1); } + if (swapped) + { + std::swap(hitkeys2, hitkeys1); + } // see if hitkeys2 is a subset of hitkeys1 - if( std::includes(hitkeys1.begin(), hitkeys1.end(), hitkeys2.begin(), hitkeys2.end()) ) + if (std::includes(hitkeys1.begin(), hitkeys1.end(), hitkeys2.begin(), hitkeys2.end())) { // increment counter ++m_cluster_counter_deleted; - if( swapped ) + if (swapped) { - - if( Verbosity() ) + if (Verbosity()) { std::cout << "Removing cluster "; - print_cluster_information( ckey1, cluster1); + print_cluster_information(ckey1, cluster1); std::cout << "Keeping cluster "; - print_cluster_information( ckey2, cluster2); + print_cluster_information(ckey2, cluster2); } // remove first cluster trkrclusters->removeCluster(ckey1); break; - } else { - - if( Verbosity() ) - { - std::cout << "Removing cluster "; - print_cluster_information( ckey2, cluster2); - - std::cout << "Keeping cluster "; - print_cluster_information( ckey1, cluster1); - } + } + if (Verbosity()) + { + std::cout << "Removing cluster "; + print_cluster_information(ckey2, cluster2); - // remove second cluster - trkrclusters->removeCluster(ckey2); + std::cout << "Keeping cluster "; + print_cluster_information(ckey1, cluster1); } + + // remove second cluster + trkrclusters->removeCluster(ckey2); } - } // strict matching + } // strict matching - } // second cluster loop - } // first cluster loop - } // hitsetkey loop + } // second cluster loop + } // first cluster loop + } // hitsetkey loop return Fun4AllReturnCodes::EVENT_OK; - } //_____________________________________________________________________________ -int MvtxClusterPruner::End(PHCompositeNode * /*topNode*/) +int MvtxClusterPruner::End(PHCompositeNode* /*topNode*/) { - std::cout << "MvtxClusterPruner::End -" - << " m_cluster_counter_total: " << m_cluster_counter_total - << std::endl; - std::cout << "MvtxClusterPruner::End -" - << " m_cluster_counter_deleted: " << m_cluster_counter_deleted - << " fraction: " << double( m_cluster_counter_deleted )/m_cluster_counter_total - << std::endl; + << " m_cluster_counter_total: " << m_cluster_counter_total + << std::endl; + std::cout << "MvtxClusterPruner::End -" + << " m_cluster_counter_deleted: " << m_cluster_counter_deleted + << " fraction: " << double(m_cluster_counter_deleted) / m_cluster_counter_total + << std::endl; return Fun4AllReturnCodes::EVENT_OK; } diff --git a/offline/packages/mvtx/MvtxClusterizer.cc b/offline/packages/mvtx/MvtxClusterizer.cc index 7970b369eb..eb54930acd 100644 --- a/offline/packages/mvtx/MvtxClusterizer.cc +++ b/offline/packages/mvtx/MvtxClusterizer.cc @@ -63,7 +63,7 @@ namespace /// convenience square method template - inline constexpr T square(const T &x) + constexpr T square(const T &x) { return x * x; } @@ -71,65 +71,45 @@ namespace bool MvtxClusterizer::are_adjacent( const std::pair &lhs, - const std::pair &rhs) + const std::pair &rhs) const { if (GetZClustering()) { return - // column adjacent - ( (MvtxDefs::getCol(lhs.first) > MvtxDefs::getCol(rhs.first)) ? - MvtxDefs::getCol(lhs.first)<=MvtxDefs::getCol(rhs.first)+1: - MvtxDefs::getCol(rhs.first)<=MvtxDefs::getCol(lhs.first)+1) && + // column adjacent + ((MvtxDefs::getCol(lhs.first) > MvtxDefs::getCol(rhs.first)) ? MvtxDefs::getCol(lhs.first) <= MvtxDefs::getCol(rhs.first) + 1 : MvtxDefs::getCol(rhs.first) <= MvtxDefs::getCol(lhs.first) + 1) && - // row adjacent - ( (MvtxDefs::getRow(lhs.first) > MvtxDefs::getRow(rhs.first)) ? - MvtxDefs::getRow(lhs.first)<=MvtxDefs::getRow(rhs.first)+1: - MvtxDefs::getRow(rhs.first)<=MvtxDefs::getRow(lhs.first)+1); - - } else { - - return + // row adjacent + ((MvtxDefs::getRow(lhs.first) > MvtxDefs::getRow(rhs.first)) ? MvtxDefs::getRow(lhs.first) <= MvtxDefs::getRow(rhs.first) + 1 : MvtxDefs::getRow(rhs.first) <= MvtxDefs::getRow(lhs.first) + 1); + } + return // column identical - MvtxDefs::getCol(rhs.first)==MvtxDefs::getCol(lhs.first) && + MvtxDefs::getCol(rhs.first) == MvtxDefs::getCol(lhs.first) && // row adjacent - ( (MvtxDefs::getRow(lhs.first) > MvtxDefs::getRow(rhs.first)) ? - MvtxDefs::getRow(lhs.first)<=MvtxDefs::getRow(rhs.first)+1: - MvtxDefs::getRow(rhs.first)<=MvtxDefs::getRow(lhs.first)+1); - - } + ((MvtxDefs::getRow(lhs.first) > MvtxDefs::getRow(rhs.first)) ? MvtxDefs::getRow(lhs.first) <= MvtxDefs::getRow(rhs.first) + 1 : MvtxDefs::getRow(rhs.first) <= MvtxDefs::getRow(lhs.first) + 1); } -bool MvtxClusterizer::are_adjacent(RawHit *lhs, RawHit *rhs) +bool MvtxClusterizer::are_adjacent(RawHit *lhs, RawHit *rhs) const { if (GetZClustering()) { return - // phi adjacent (== column) - ((lhs->getPhiBin() > rhs->getPhiBin()) ? - lhs->getPhiBin() <= rhs->getPhiBin()+1: - rhs->getPhiBin() <= lhs->getPhiBin()+1) && + // phi adjacent (== column) + ((lhs->getPhiBin() > rhs->getPhiBin()) ? lhs->getPhiBin() <= rhs->getPhiBin() + 1 : rhs->getPhiBin() <= lhs->getPhiBin() + 1) && - // time adjacent (== row) - ((lhs->getTBin() > rhs->getTBin()) ? - lhs->getTBin() <= rhs->getTBin()+1: - rhs->getTBin() <= lhs->getTBin()+1); - - } else { - - return + // time adjacent (== row) + ((lhs->getTBin() > rhs->getTBin()) ? lhs->getTBin() <= rhs->getTBin() + 1 : rhs->getTBin() <= lhs->getTBin() + 1); + } + return // phi identical (== column) lhs->getPhiBin() == rhs->getPhiBin() && // time adjacent (== row) - ((lhs->getTBin() > rhs->getTBin()) ? - lhs->getTBin() <= rhs->getTBin()+1: - rhs->getTBin() <= lhs->getTBin()+1); - - } + ((lhs->getTBin() > rhs->getTBin()) ? lhs->getTBin() <= rhs->getTBin() + 1 : rhs->getTBin() <= lhs->getTBin() + 1); } MvtxClusterizer::MvtxClusterizer(const std::string &name) @@ -165,7 +145,7 @@ int MvtxClusterizer::InitRun(PHCompositeNode *topNode) } // Create the Cluster node if required - auto trkrclusters = + auto *trkrclusters = findNode::getClass(dstNode, "TRKR_CLUSTER"); if (!trkrclusters) { @@ -183,7 +163,7 @@ int MvtxClusterizer::InitRun(PHCompositeNode *topNode) DetNode->addNode(TrkrClusterContainerNode); } - auto clusterhitassoc = + auto *clusterhitassoc = findNode::getClass(topNode, "TRKR_CLUSTERHITASSOC"); if (!clusterhitassoc) { @@ -208,14 +188,14 @@ int MvtxClusterizer::InitRun(PHCompositeNode *topNode) if (!mClusHitsVerbose) { PHNodeIterator dstiter(dstNode); - auto DetNode = dynamic_cast(dstiter.findFirst("PHCompositeNode", "TRKR")); + auto *DetNode = dynamic_cast(dstiter.findFirst("PHCompositeNode", "TRKR")); if (!DetNode) { DetNode = new PHCompositeNode("TRKR"); dstNode->addNode(DetNode); } mClusHitsVerbose = new ClusHitsVerbosev1(); - auto newNode = new PHIODataNode(mClusHitsVerbose, "Trkr_SvtxClusHitsVerbose", "PHObject"); + auto *newNode = new PHIODataNode(mClusHitsVerbose, "Trkr_SvtxClusHitsVerbose", "PHObject"); DetNode->addNode(newNode); } } @@ -227,13 +207,13 @@ int MvtxClusterizer::InitRun(PHCompositeNode *topNode) if (Verbosity() > 0) { std::cout << "====================== MvtxClusterizer::InitRun() " - "=====================" - << std::endl; + "=====================" + << std::endl; std::cout << " Z-dimension Clustering = " << std::boolalpha << m_makeZClustering - << std::noboolalpha << std::endl; + << std::noboolalpha << std::endl; std::cout << "==================================================================" - "=========" - << std::endl; + "=========" + << std::endl; } return Fun4AllReturnCodes::EVENT_OK; @@ -283,7 +263,7 @@ int MvtxClusterizer::process_event(PHCompositeNode *topNode) // reset MVTX clusters and cluster associations const auto hitsetkeys = m_clusterlist->getHitSetKeys(TrkrDefs::mvtxId); - for( const auto& hitsetkey:hitsetkeys) + for (const auto &hitsetkey : hitsetkeys) { m_clusterlist->removeClusters(hitsetkey); m_clusterhitassoc->removeAssocs(hitsetkey); @@ -337,8 +317,8 @@ void MvtxClusterizer::ClusterMvtx(PHCompositeNode *topNode) unsigned int chip = MvtxDefs::getChipId(hitsetitr->first); unsigned int strobe = MvtxDefs::getStrobeId(hitsetitr->first); std::cout << "MvtxClusterizer found hitsetkey " << hitsetitr->first - << " layer " << layer << " stave " << stave << " chip " << chip - << " strobe " << strobe << std::endl; + << " layer " << layer << " stave " << stave << " chip " << chip + << " strobe " << strobe << std::endl; } if (Verbosity() > 2) @@ -394,7 +374,7 @@ void MvtxClusterizer::ClusterMvtx(PHCompositeNode *topNode) std::vector component(num_vertices(G)); // this is the actual clustering, performed by boost - boost::connected_components(G, &component[0]); + boost::connected_components(G, component.data()); // Loop over the components(hits) compiling a list of the // unique connected groups (ie. clusters). @@ -405,7 +385,7 @@ void MvtxClusterizer::ClusterMvtx(PHCompositeNode *topNode) cluster_ids.insert(component[i]); clusters.insert(make_pair(component[i], hitvec[i])); } - for (const auto& clusid:cluster_ids) + for (const auto &clusid : cluster_ids) { auto clusrange = clusters.equal_range(clusid); auto ckey = TrkrDefs::genClusKey(hitset->getHitSetKey(), clusid); @@ -413,7 +393,8 @@ void MvtxClusterizer::ClusterMvtx(PHCompositeNode *topNode) // determine the size of the cluster in phi and z std::set phibins; std::set zbins; - std::map m_phi, m_z; // Note, there are no "cut" bins for Svtx Clusters + std::map m_phi; + std::map m_z; // Note, there are no "cut" bins for Svtx Clusters // determine the cluster position... double locxsum = 0.; @@ -426,7 +407,7 @@ void MvtxClusterizer::ClusterMvtx(PHCompositeNode *topNode) // we need the geometry object for this layer to get the global positions int layer = TrkrDefs::getLayer(ckey); - auto layergeom = dynamic_cast(geom_container->GetLayerGeom(layer)); + auto *layergeom = dynamic_cast(geom_container->GetLayerGeom(layer)); if (!layergeom) { exit(1); @@ -574,11 +555,11 @@ void MvtxClusterizer::ClusterMvtx(PHCompositeNode *topNode) if (Verbosity() > 0) { std::cout << " MvtxClusterizer: cluskey " << ckey << " layer " << layer - << " rad " << layergeom->get_radius() << " phibins " - << phibins.size() << " pitch " << pitch << " phisize " << phisize - << " zbins " << zbins.size() << " length " << length << " zsize " - << zsize << " local x " << locclusx << " local y " << locclusz - << std::endl; + << " rad " << layergeom->get_radius() << " phibins " + << phibins.size() << " pitch " << pitch << " phisize " << phisize + << " zbins " << zbins.size() << " length " << length << " zsize " + << zsize << " local x " << locclusx << " local y " << locclusz + << std::endl; } auto clus = std::make_unique(); @@ -605,7 +586,7 @@ void MvtxClusterizer::ClusterMvtx(PHCompositeNode *topNode) } } // clusitr loop - } // loop over hitsets + } // loop over hitsets if (Verbosity() > 1) { @@ -650,8 +631,8 @@ void MvtxClusterizer::ClusterMvtxRaw(PHCompositeNode *topNode) unsigned int chip = MvtxDefs::getChipId(hitsetitr->first); unsigned int strobe = MvtxDefs::getStrobeId(hitsetitr->first); std::cout << "MvtxClusterizer found hitsetkey " << hitsetitr->first - << " layer " << layer << " stave " << stave << " chip " << chip - << " strobe " << strobe << std::endl; + << " layer " << layer << " stave " << stave << " chip " << chip + << " strobe " << strobe << std::endl; } if (Verbosity() > 2) @@ -695,7 +676,7 @@ void MvtxClusterizer::ClusterMvtxRaw(PHCompositeNode *topNode) std::vector component(num_vertices(G)); // this is the actual clustering, performed by boost - boost::connected_components(G, &component[0]); + boost::connected_components(G, component.data()); // Loop over the components(hits) compiling a list of the // unique connected groups (ie. clusters). @@ -709,7 +690,7 @@ void MvtxClusterizer::ClusterMvtxRaw(PHCompositeNode *topNode) } // std::cout << "found cluster #: "<< clusters.size()<< std::endl; // loop over the componenets and make clusters - for( const auto& clusid:cluster_ids) + for (const auto &clusid : cluster_ids) { auto clusrange = clusters.equal_range(clusid); @@ -731,7 +712,7 @@ void MvtxClusterizer::ClusterMvtxRaw(PHCompositeNode *topNode) // we need the geometry object for this layer to get the global positions int layer = TrkrDefs::getLayer(ckey); - auto layergeom = dynamic_cast( + auto *layergeom = dynamic_cast( geom_container->GetLayerGeom(layer)); if (!layergeom) { @@ -845,11 +826,11 @@ void MvtxClusterizer::ClusterMvtxRaw(PHCompositeNode *topNode) if (Verbosity() > 0) { std::cout << " MvtxClusterizer: cluskey " << ckey << " layer " << layer - << " rad " << layergeom->get_radius() << " phibins " - << phibins.size() << " pitch " << pitch << " phisize " << phisize - << " zbins " << zbins.size() << " length " << length << " zsize " - << zsize << " local x " << locclusx << " local y " << locclusz - << std::endl; + << " rad " << layergeom->get_radius() << " phibins " + << phibins.size() << " pitch " << pitch << " phisize " << phisize + << " zbins " << zbins.size() << " length " << length << " zsize " + << zsize << " local x " << locclusx << " local y " << locclusz + << std::endl; } auto clus = std::make_unique(); @@ -875,7 +856,7 @@ void MvtxClusterizer::ClusterMvtxRaw(PHCompositeNode *topNode) m_clusterlist->addClusterSpecifyKey(ckey, clus.release()); } } // clusitr loop - } // loop over hitsets + } // loop over hitsets if (Verbosity() > 1) { @@ -898,11 +879,11 @@ void MvtxClusterizer::PrintClusters(PHCompositeNode *topNode) } std::cout << "================= After MvtxClusterizer::process_event() " - "====================" - << std::endl; + "====================" + << std::endl; std::cout << " There are " << clusterlist->size() - << " clusters recorded: " << std::endl; + << " clusters recorded: " << std::endl; if (Verbosity() > 3) { @@ -910,8 +891,8 @@ void MvtxClusterizer::PrintClusters(PHCompositeNode *topNode) } std::cout << "==================================================================" - "=========" - << std::endl; + "=========" + << std::endl; } return; diff --git a/offline/packages/mvtx/MvtxClusterizer.h b/offline/packages/mvtx/MvtxClusterizer.h index ce4794b5d1..10c65914cd 100644 --- a/offline/packages/mvtx/MvtxClusterizer.h +++ b/offline/packages/mvtx/MvtxClusterizer.h @@ -65,8 +65,8 @@ class MvtxClusterizer : public SubsysReco private: // bool are_adjacent(const pixel lhs, const pixel rhs); bool record_ClusHitsVerbose{false}; - bool are_adjacent(const std::pair &lhs, const std::pair &rhs); - bool are_adjacent(RawHit *lhs, RawHit *rhs); + bool are_adjacent(const std::pair &lhs, const std::pair &rhs) const; + bool are_adjacent(RawHit *lhs, RawHit *rhs) const; void ClusterMvtx(PHCompositeNode *topNode); void ClusterMvtxRaw(PHCompositeNode *topNode); diff --git a/offline/packages/mvtx/MvtxHitPruner.cc b/offline/packages/mvtx/MvtxHitPruner.cc index 4f141a4c3f..58cbb423c4 100644 --- a/offline/packages/mvtx/MvtxHitPruner.cc +++ b/offline/packages/mvtx/MvtxHitPruner.cc @@ -51,26 +51,33 @@ namespace { //! range adaptor to be able to use range-based for loop - template class range_adaptor + template + class range_adaptor { - public: - range_adaptor( const T& range ):m_range(range){} - const typename T::first_type& begin() {return m_range.first;} - const typename T::second_type& end() {return m_range.second;} - private: + public: + explicit range_adaptor(const T& range) + : m_range(range) + { + } + const typename T::first_type& begin() { return m_range.first; } + const typename T::second_type& end() { return m_range.second; } + + private: T m_range; }; -} +} // namespace -MvtxHitPruner::MvtxHitPruner(const std::string &name) +MvtxHitPruner::MvtxHitPruner(const std::string& name) : SubsysReco(name) { } -int MvtxHitPruner::InitRun(PHCompositeNode * /*topNode*/) -{ return Fun4AllReturnCodes::EVENT_OK; } +int MvtxHitPruner::InitRun(PHCompositeNode* /*topNode*/) +{ + return Fun4AllReturnCodes::EVENT_OK; +} -int MvtxHitPruner::process_event(PHCompositeNode *topNode) +int MvtxHitPruner::process_event(PHCompositeNode* topNode) { // get node containing the digitized hits m_hits = findNode::getClass(topNode, "TRKR_HITSET"); @@ -93,12 +100,14 @@ int MvtxHitPruner::process_event(PHCompositeNode *topNode) std::set bare_hitset_set; const auto hitsetrange = m_hits->getHitSets(TrkrDefs::TrkrId::mvtxId); - for( const auto& [hitsetkey,hitset]:range_adaptor(hitsetrange) ) + for (const auto& [hitsetkey, hitset] : range_adaptor(hitsetrange)) { - // get strobe, skip if already zero const int strobe = MvtxDefs::getStrobeId(hitsetkey); - if( strobe == 0 ) continue; + if (strobe == 0) + { + continue; + } // get the hitsetkey value for strobe 0 const auto bare_hitsetkey = MvtxDefs::resetStrobe(hitsetkey); @@ -117,43 +126,46 @@ int MvtxHitPruner::process_event(PHCompositeNode *topNode) for (const auto& bare_hitsetkey : bare_hitset_set) { // find matching hitset of creater - auto bare_hitset = (m_hits->findOrAddHitSet(bare_hitsetkey))->second; + auto* bare_hitset = (m_hits->findOrAddHitSet(bare_hitsetkey))->second; if (Verbosity()) { std::cout - << "MvtxHitPruner::process_event - bare_hitset " << bare_hitsetkey - << " initially has " << bare_hitset->size() << " hits " - << std::endl; + << "MvtxHitPruner::process_event - bare_hitset " << bare_hitsetkey + << " initially has " << bare_hitset->size() << " hits " + << std::endl; } // get all hitsets with non-zero strobe that match the bare hitset key auto bare_hitsetrange = hitset_multimap.equal_range(bare_hitsetkey); - for( const auto& [unused,hitsetkey]:range_adaptor(bare_hitsetrange) ) + for (const auto& [unused, hitsetkey] : range_adaptor(bare_hitsetrange)) { const int strobe = MvtxDefs::getStrobeId(hitsetkey); - if( strobe == 0 ) continue; + if (strobe == 0) + { + continue; + } if (Verbosity()) { std::cout << "MvtxHitPruner::process_event -" - << " process hitsetkey " << hitsetkey - << " from strobe " << strobe - << " for bare_hitsetkey " << bare_hitsetkey - << std::endl; + << " process hitsetkey " << hitsetkey + << " from strobe " << strobe + << " for bare_hitsetkey " << bare_hitsetkey + << std::endl; } // copy all hits to the hitset with strobe 0 - auto hitset = m_hits->findHitSet(hitsetkey); + auto* hitset = m_hits->findHitSet(hitsetkey); if (Verbosity()) { std::cout << "MvtxHitPruner::process_event - hitsetkey " << hitsetkey - << " has strobe " << strobe << " and has " << hitset->size() - << " hits, so copy it" << std::endl; + << " has strobe " << strobe << " and has " << hitset->size() + << " hits, so copy it" << std::endl; } TrkrHitSet::ConstRange hitrangei = hitset->getHits(); - for( const auto& [hitkey,old_hit]:range_adaptor(hitrangei) ) + for (const auto& [hitkey, old_hit] : range_adaptor(hitrangei)) { if (Verbosity()) { @@ -166,9 +178,9 @@ int MvtxHitPruner::process_event(PHCompositeNode *topNode) if (Verbosity()) { std::cout - << "MvtxHitPruner::process_event - hitkey " << hitkey - << " is already in bare hitsest, do not copy" - << std::endl; + << "MvtxHitPruner::process_event - hitkey " << hitkey + << " is already in bare hitsest, do not copy" + << std::endl; } continue; } @@ -177,11 +189,11 @@ int MvtxHitPruner::process_event(PHCompositeNode *topNode) if (Verbosity()) { std::cout - << "MvtxHitPruner::process_event - copying over hitkey " - << hitkey << std::endl; + << "MvtxHitPruner::process_event - copying over hitkey " + << hitkey << std::endl; } - auto new_hit = new TrkrHitv2; + auto* new_hit = new TrkrHitv2; new_hit->CopyFrom(old_hit); bare_hitset->addHitSpecificKey(hitkey, new_hit); } diff --git a/offline/packages/mvtx/SegmentationAlpide.cc b/offline/packages/mvtx/SegmentationAlpide.cc index 6b9aecddd0..0b1aae48cf 100644 --- a/offline/packages/mvtx/SegmentationAlpide.cc +++ b/offline/packages/mvtx/SegmentationAlpide.cc @@ -5,16 +5,15 @@ */ #include "SegmentationAlpide.h" -#include - #include +#include void SegmentationAlpide::print() { - std::cout << (boost::format("Pixel size: %.2f (along %d rows) %.2f (along %d columns) microns") % (PitchRow * 1e4) % NRows % (PitchCol * 1e4) % NCols).str() + std::cout << std::format("Pixel size: {:.2f} (along {} rows) {:.2f} (along {} columns) microns", (PitchRow * 1e4), NRows, (PitchCol * 1e4), NCols) << std::endl; - std::cout << (boost::format("Passive edges: bottom: %.2f, top: %.2f, left/right: %.2f microns") % (PassiveEdgeReadOut * 1e4) % (PassiveEdgeTop * 1e4) % (PassiveEdgeSide * 1e4)).str() + std::cout << std::format("Passive edges: bottom: {:.2f}, top: {:.2f}, left/right: {:.2f} microns", (PassiveEdgeReadOut * 1e4), (PassiveEdgeTop * 1e4), (PassiveEdgeSide * 1e4)) << std::endl; - std::cout << (boost::format("Active/Total size: %.6f/%.6f (rows) %.6f/%.6f (cols) cm") % ActiveMatrixSizeRows % SensorSizeRows % ActiveMatrixSizeCols % SensorSizeCols).str() + std::cout << std::format("Active/Total size: {:.6f}/{:.6f} (rows) {:.6f}/{:.6f} (cols) cm", ActiveMatrixSizeRows, SensorSizeRows, ActiveMatrixSizeCols, SensorSizeCols) << std::endl; } diff --git a/offline/packages/tpc/LaserClusterizer.cc b/offline/packages/tpc/LaserClusterizer.cc index 170f95944d..8ecd28688e 100644 --- a/offline/packages/tpc/LaserClusterizer.cc +++ b/offline/packages/tpc/LaserClusterizer.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -31,13 +32,10 @@ #include #include +#include #include #include #include -//#include -//#include -#include -//#include #include #include @@ -46,34 +44,33 @@ #include #include // for sqrt, cos, sin +#include #include #include #include // for _Rb_tree_cons... +#include +#include +#include #include +#include #include // for pair #include -#include -#include -#include #include namespace bg = boost::geometry; namespace bgi = boost::geometry::index; -using point = bg::model::point; +using point = bg::model::point; using box = bg::model::box; using specHitKey = std::pair; using adcKey = std::pair; using pointKeyLaser = std::pair; using hitData = std::pair; - -int layerMins[3] = {7,23,39}; +int layerMins[3] = {7, 23, 39}; int layerMaxes[3] = {22, 38, 54}; - - namespace { struct thread_data @@ -101,28 +98,25 @@ namespace pthread_mutex_t mythreadlock; const std::vector neighborOffsets = { - point(1, 0, 0), point(-1, 0, 0), - point(0, 1, 0), point(0, -1, 0), - point(0, 0, 1), point(0, 0, -1), - point(0, 0, 2), point(0, 0, -2) - }; + point(1, 0, 0), point(-1, 0, 0), + point(0, 1, 0), point(0, -1, 0), + point(0, 0, 1), point(0, 0, -1), + point(0, 0, 2), point(0, 0, -2)}; - - double layerFunction(double *x, double *par) + double layerFunction(double *x, const double *par) { double A = par[0]; double mu = par[1]; - double binCenter = round(x[0]); double overlapLow = std::max(binCenter - 0.5, mu - 0.5); double overlapHigh = std::min(binCenter + 0.5, mu + 0.5); double overlap = overlapHigh - overlapLow; - if(overlap <= 0.0) + if (overlap <= 0.0) { return 0.0; } - return A*overlap; + return A * overlap; /* if(fabs(x[0] - mu) < 1) { @@ -131,50 +125,187 @@ namespace } return 0.0; */ - - } double phiFunction(double *x, double *par) { - if(par[2] < 0.0) + if (par[2] < 0.0) { return 0.0; } - return par[0] * TMath::Gaus(x[0],par[1],par[2],false); + return par[0] * TMath::Gaus(x[0], par[1], par[2], false); } double timeFunction(double *x, double *par) { - if(par[2] < 0.0) + if (par[2] < 0.0) { return 0.0; } - double g = TMath::Gaus(x[0],par[1],par[2],true); - double cdf = 1 + TMath::Erfc(par[3]*(x[0]-par[1])/(sqrt(2.0)*par[2])); - return par[0]*g*cdf; + double g = TMath::Gaus(x[0], par[1], par[2], true); + double cdf = 1 + TMath::Erfc(par[3] * (x[0] - par[1]) / (sqrt(2.0) * par[2])); + return par[0] * g * cdf; } - void findConnectedRegions3(std::vector &clusHits, std::pair &maxKey) + void splitWeaklyConnectedRegion(const std::vector ®ion, std::vector> &outputRegions, int aVerbosity) + { + int N = region.size(); + /* + std::vector> adj(N); + for(int i=0; i() + neigh.get<0>() - region[j].first.get<0>()) < 0.01 && + fabs(region[i].first.get<1>() + neigh.get<1>() - region[j].first.get<1>()) < 0.01 && + fabs(region[i].first.get<2>() + neigh.get<2>() - region[j].first.get<2>()) < 0.01) + { + adj[i].push_back(j); + adj[j].push_back(i); + break; + } + } + } + } + */ + std::map, int> coordIndex; + for(int i=0; i(std::round(region[i].first.get<0>())); + int p = static_cast(std::round(region[i].first.get<1>())); + int t = static_cast(std::round(region[i].first.get<2>())); + coordIndex[{l,p,t}] = i; + } + std::vector> adj(N); + for(int i=0; i(std::round(region[i].first.get<0>())); + int p = static_cast(std::round(region[i].first.get<1>())); + int t = static_cast(std::round(region[i].first.get<2>())); + for(const auto &neigh : neighborOffsets) + { + int nl = l + static_cast(neigh.get<0>()); + int np = p + static_cast(neigh.get<1>()); + int nt = t + static_cast(neigh.get<2>()); + auto it = coordIndex.find({nl,np,nt}); + if(it != coordIndex.end()) + { + adj[i].push_back(it->second); + } + } + } + + if(aVerbosity > 3) { std::cout << " constructed adjacency list, average degree = " << std::accumulate(adj.begin(), adj.end(), 0.0, [](double s, auto &v) { return s + v.size(); }) / N << ")" << std::endl; +} + + std::vector disc(N, -1); + std::vector low(N, -1); + std::vector parent(N, -1); + std::vector> bridges; + int time=0; + + std::function dfs = [&](int u) + { + disc[u] = low[u] = ++time; + for(auto v : adj[u]) + { + if(disc[v] == -1) + { + parent[v] = u; + dfs(v); + low[u] = std::min(low[u], low[v]); + if(low[v] > disc[u]) + { + bridges.emplace_back(u,v); + } + } + else if(v != parent[u]) + { + low[u] = std::min(low[u], disc[v]); + } + } + }; + + for(int i=0; i 2) { std::cout << " Found " << bridges.size() << " bridges in region of size " << N << std::endl; +} + + std::vector> adj2 = adj; + int removed = 0; + for(auto [u,v] : bridges) + { + if(adj[u].size() > 2 && adj[v].size() > 2) + { + adj2[u].erase(std::remove(adj2[u].begin(), adj2[u].end(), v), adj2[u].end()); + adj2[v].erase(std::remove(adj2[v].begin(), adj2[v].end(), u), adj2[v].end()); + removed++; + if(aVerbosity > 3) { std::cout << " removed weak bridge between nodes " << u << " (deg = " << adj[u].size() << ") and " << v << " (deg = " << adj[v].size() << ")" << std::endl; +} + } + } + + if(aVerbosity > 3) { std::cout << " Removed " << removed << " weak bridges, now finding connected components" << std::endl; +} + + std::vector visited(N, false); + for(int i=0; i sub; + std::queue q; + q.push(i); + visited[i] = true; + while(!q.empty()) + { + int u = q.front(); + q.pop(); + sub.push_back(region[u]); + for(auto v : adj2[u]) + { + if(!visited[v]) + { + visited[v] = true; + q.push(v); + } + } + } + outputRegions.push_back(sub); + if(aVerbosity > 3) { std::cout << " found subregion of size " << sub.size() << std::endl; +} + } + if(aVerbosity > 2) { std::cout << " finished splitting region into " << outputRegions.size() << " subregions" << std::endl; +} +} + + void findConnectedRegions3(std::vector &clusHits, std::pair &maxKey, int aVerbosity) { std::vector> regions; std::vector unvisited; - for(auto &clusHit : clusHits) + unvisited.reserve(clusHits.size()); + for (auto &clusHit : clusHits) { unvisited.push_back(clusHit); } - while(!unvisited.empty()) + while (!unvisited.empty()) { std::vector region; std::queue q; unsigned int mIndex = 0; - int i=0; - for(auto hit : unvisited) + int i = 0; + for (auto hit : unvisited) { - if(hit.second.second.first == maxKey.first && hit.second.second.second == maxKey.second) + if (hit.second.second.first == maxKey.first && hit.second.second.second == maxKey.second) { mIndex = i; break; @@ -183,30 +314,29 @@ namespace } auto seed = unvisited[mIndex]; - unvisited.erase(unvisited.begin()+mIndex); + unvisited.erase(unvisited.begin() + mIndex); q.push(seed); region.push_back(seed); - while(!q.empty()) + while (!q.empty()) { - float ix = q.front().first.get<0>(); - float iy = q.front().first.get<1>(); - float iz = q.front().first.get<2>(); + double ix = q.front().first.get<0>(); + double iy = q.front().first.get<1>(); + double iz = q.front().first.get<2>(); q.pop(); for (auto neigh : neighborOffsets) { - float nx = ix + neigh.get<0>(); - float ny = iy + neigh.get<1>(); - float nz = iz + neigh.get<2>(); + double nx = ix + neigh.get<0>(); + double ny = iy + neigh.get<1>(); + double nz = iz + neigh.get<2>(); - for(unsigned int v=0; v() - nx) < 0.01 && fabs(unvisited[v].first.get<1>() - ny) < 0.01 && fabs(unvisited[v].first.get<2>() - nz) < 0.01) + if (fabs(unvisited[v].first.get<0>() - nx) < 0.01 && fabs(unvisited[v].first.get<1>() - ny) < 0.01 && fabs(unvisited[v].first.get<2>() - nz) < 0.01) { auto newSeed = unvisited[v]; - unvisited.erase(unvisited.begin()+v); + unvisited.erase(unvisited.begin() + v); q.push(newSeed); region.push_back(newSeed); break; @@ -215,18 +345,68 @@ namespace } } regions.push_back(region); + } + if(aVerbosity > 2) { std::cout << "finished with normal region finding, now splitting weakly connected regions" << std::endl; +} + + std::vector> refinedRegions; + int regionNum = 0; + for(auto ®ion : regions) + { + std::vector> tmpRefinedRegions; + if(aVerbosity > 2) { std::cout << "starting to split region " << regionNum << " with " << region.size() << " hits" << std::endl; +} + regionNum++; + splitWeaklyConnectedRegion(region, tmpRefinedRegions, aVerbosity); + if(aVerbosity > 2) { std::cout << "finished splitting region into " << tmpRefinedRegions.size() << std::endl; +} + for(auto &subregion : tmpRefinedRegions) + { + refinedRegions.push_back(subregion); + } + if(aVerbosity > 2) { std::cout << "total refined regions so far: " << refinedRegions.size() << std::endl; +} } + std::sort(refinedRegions.begin(), refinedRegions.end(), [&](const auto &a, const auto &b) + { + bool a_has = false; + bool b_has = false; + for(auto &h : a) + { + if(h.second.second.first == maxKey.first && h.second.second.second == maxKey.second) + { + a_has = true; + break; + } + } + for(auto &h : b) + { + if(h.second.second.first == maxKey.first && h.second.second.second == maxKey.second) + { + b_has = true; + break; + } + } + if(a_has != b_has) + { + return a_has; + } + return a.size() > b.size(); + }); + clusHits.clear(); - for(auto hit : regions[0]) + if(refinedRegions.empty() || refinedRegions[0].empty()) + { + return; + } + for(auto hit : refinedRegions[0]) { clusHits.push_back(hit); } - } - void remove_hits(std::vector &clusHits, bgi::rtree> &rtree, std::multimap &adcMap) { for (auto &clusHit : clusHits) @@ -237,169 +417,170 @@ namespace for (auto iterAdc = adcMap.begin(); iterAdc != adcMap.end();) { - if(iterAdc->second.second == spechitkey) - { - iterAdc = adcMap.erase(iterAdc); - break; - } - else - { - ++iterAdc; - } + if (iterAdc->second.second == spechitkey) + { + iterAdc = adcMap.erase(iterAdc); + break; + } + + ++iterAdc; } } - } void calc_cluster_parameter(std::vector &clusHits, thread_data &my_data, std::pair maxADCKey) { - - - - findConnectedRegions3(clusHits, maxADCKey); - + findConnectedRegions3(clusHits, maxADCKey, my_data.Verbosity); double rSum = 0.0; double phiSum = 0.0; double tSum = 0.0; - + double layerSum = 0.0; double iphiSum = 0.0; double itSum = 0.0; - + double adcSum = 0.0; - + double maxAdc = 0.0; TrkrDefs::hitsetkey maxKey = 0; - + double secondmaxAdc = 0.0; + TrkrDefs::hitsetkey secondmaxKey = 0; + unsigned int nHits = clusHits.size(); - + auto *clus = new LaserClusterv2; - + int meanSide = 0; - - std::vector usedLayer; - std::vector usedIPhi; - std::vector usedIT; - + + std::vector usedLayer; + std::vector usedIPhi; + std::vector usedIT; + double meanLayer = 0.0; double meanIPhi = 0.0; double meanIT = 0.0; for (auto &clusHit : clusHits) { - float coords[3] = {clusHit.first.get<0>(), clusHit.first.get<1>(), clusHit.first.get<2>()}; + double coords[3] = {clusHit.first.get<0>(), clusHit.first.get<1>(), clusHit.first.get<2>()}; std::pair spechitkey = clusHit.second.second; unsigned int adc = clusHit.second.first; int side = TpcDefs::getSide(spechitkey.second); - + if (side) { - meanSide++; + meanSide++; } else { - meanSide--; + meanSide--; } - + PHG4TpcGeom *layergeom = my_data.geom_container->GetLayerCellGeom((int) coords[0]); - + double r = layergeom->get_radius(); double phi = layergeom->get_phi(coords[1], side); double t = layergeom->get_zcenter(fabs(coords[2])); - + double hitzdriftlength = t * my_data.tGeometry->get_drift_velocity(); double hitZ = my_data.tdriftmax * my_data.tGeometry->get_drift_velocity() - hitzdriftlength; - - - bool foundLayer = false; - for (float i : usedLayer) - { - if (coords[0] == i) - { - foundLayer = true; - break; - } - } - - if (!foundLayer) - { - usedLayer.push_back(coords[0]); - } - - bool foundIPhi = false; - for (float i : usedIPhi) - { - if (coords[1] == i) - { - foundIPhi = true; - break; - } - } - - if (!foundIPhi) - { - usedIPhi.push_back(coords[1]); - } - - bool foundIT = false; - for (float i : usedIT) - { - if (coords[2] == i) - { - foundIT = true; - break; - } - } - - if (!foundIT) - { - usedIT.push_back(coords[2]); - } - - clus->addHit(); - clus->setHitLayer(clus->getNhits() - 1, coords[0]); - clus->setHitIPhi(clus->getNhits() - 1, coords[1]); - clus->setHitIT(clus->getNhits() - 1, coords[2]); - clus->setHitX(clus->getNhits() - 1, r * cos(phi)); - clus->setHitY(clus->getNhits() - 1, r * sin(phi)); - clus->setHitZ(clus->getNhits() - 1, hitZ); - clus->setHitAdc(clus->getNhits() - 1, (float) adc); - - rSum += r * adc; - phiSum += phi * adc; - tSum += t * adc; - - layerSum += coords[0] * adc; - iphiSum += coords[1] * adc; - itSum += coords[2] * adc; - - meanLayer += coords[0]; - meanIPhi += coords[1]; - meanIT += coords[2]; - - adcSum += adc; - - if (adc > maxAdc) - { - maxAdc = adc; - maxKey = spechitkey.second; - } - - } - + + bool foundLayer = false; + for (double i : usedLayer) + { + if (coords[0] == i) + { + foundLayer = true; + break; + } + } + + if (!foundLayer) + { + usedLayer.push_back(coords[0]); + } + + bool foundIPhi = false; + for (double i : usedIPhi) + { + if (coords[1] == i) + { + foundIPhi = true; + break; + } + } + + if (!foundIPhi) + { + usedIPhi.push_back(coords[1]); + } + + bool foundIT = false; + for (double i : usedIT) + { + if (coords[2] == i) + { + foundIT = true; + break; + } + } + + if (!foundIT) + { + usedIT.push_back(coords[2]); + } + + clus->addHit(); + clus->setHitLayer(clus->getNhits() - 1, coords[0]); + clus->setHitIPhi(clus->getNhits() - 1, coords[1]); + clus->setHitIT(clus->getNhits() - 1, coords[2]); + clus->setHitX(clus->getNhits() - 1, r * cos(phi)); + clus->setHitY(clus->getNhits() - 1, r * sin(phi)); + clus->setHitZ(clus->getNhits() - 1, hitZ); + clus->setHitAdc(clus->getNhits() - 1, (double) adc); + + rSum += r * adc; + phiSum += phi * adc; + tSum += t * adc; + + layerSum += coords[0] * adc; + iphiSum += coords[1] * adc; + itSum += coords[2] * adc; + + meanLayer += coords[0]; + meanIPhi += coords[1]; + meanIT += coords[2]; + + adcSum += adc; + + if (adc > maxAdc) + { + secondmaxAdc = maxAdc; + secondmaxKey = maxKey; + maxAdc = adc; + maxKey = spechitkey.second; + } + else if (adc > secondmaxAdc) + { + secondmaxAdc = adc; + secondmaxKey = spechitkey.second; + } + + + } + if (nHits == 0) { return; } - double clusR = rSum / adcSum; double clusPhi = phiSum / adcSum; double clusT = tSum / adcSum; double zdriftlength = clusT * my_data.tGeometry->get_drift_velocity(); - + double clusX = clusR * cos(clusPhi); double clusY = clusR * sin(clusPhi); double clusZ = my_data.tdriftmax * my_data.tGeometry->get_drift_velocity() - zdriftlength; @@ -408,10 +589,10 @@ namespace clusZ = -clusZ; for (int i = 0; i < (int) clus->getNhits(); i++) { - clus->setHitZ(i, -1 * clus->getHitZ(i)); + clus->setHitZ(i, -1 * clus->getHitZ(i)); } } - + std::sort(usedLayer.begin(), usedLayer.end()); std::sort(usedIPhi.begin(), usedIPhi.end()); std::sort(usedIT.begin(), usedIT.end()); @@ -419,30 +600,28 @@ namespace meanLayer = meanLayer / nHits; meanIPhi = meanIPhi / nHits; meanIT = meanIT / nHits; - + double sigmaLayer = 0.0; double sigmaIPhi = 0.0; double sigmaIT = 0.0; - + double sigmaWeightedLayer = 0.0; double sigmaWeightedIPhi = 0.0; double sigmaWeightedIT = 0.0; - - pthread_mutex_lock(&mythreadlock); - my_data.hitHist = new TH3D(Form("hitHist_event%d_side%d_sector%d_module%d_cluster%d",my_data.eventNum,(int)my_data.side,(int)my_data.sector,(int)my_data.module,(int)my_data.cluster_vector.size()),";layer;iphi;it",usedLayer.size()+2,usedLayer[0]-1.5,*usedLayer.rbegin()+1.5,usedIPhi.size()+2,usedIPhi[0]-1.5,*usedIPhi.rbegin()+1.5,usedIT.size()+2,usedIT[0]-1.5,*usedIT.rbegin()+1.5); + pthread_mutex_lock(&mythreadlock); + my_data.hitHist = new TH3D(std::format("hitHist_event{}_side{}_sector{}_module{}_cluster{}", my_data.eventNum, (int) my_data.side, (int) my_data.sector, (int) my_data.module, (int) my_data.cluster_vector.size()).c_str(), ";layer;iphi;it", usedLayer.size() + 2, usedLayer[0] - 1.5, *usedLayer.rbegin() + 1.5, usedIPhi.size() + 2, usedIPhi[0] - 1.5, *usedIPhi.rbegin() + 1.5, usedIT.size() + 2, usedIT[0] - 1.5, *usedIT.rbegin() + 1.5); - //TH3D *hitHist = new TH3D(Form("hitHist_event%d_side%d_sector%d_module%d_cluster%d",my_data.eventNum,(int)my_data.side,(int)my_data.sector,(int)my_data.module,(int)my_data.cluster_vector.size()),";layer;iphi;it",usedLayer.size()+2,usedLayer[0]-1.5,*usedLayer.rbegin()+1.5,usedIPhi.size()+2,usedIPhi[0]-1.5,*usedIPhi.rbegin()+1.5,usedIT.size()+2,usedIT[0]-1.5,*usedIT.rbegin()+1.5); + // TH3D *hitHist = new TH3D(Form("hitHist_event%d_side%d_sector%d_module%d_cluster%d",my_data.eventNum,(int)my_data.side,(int)my_data.sector,(int)my_data.module,(int)my_data.cluster_vector.size()),";layer;iphi;it",usedLayer.size()+2,usedLayer[0]-1.5,*usedLayer.rbegin()+1.5,usedIPhi.size()+2,usedIPhi[0]-1.5,*usedIPhi.rbegin()+1.5,usedIT.size()+2,usedIT[0]-1.5,*usedIT.rbegin()+1.5); for (int i = 0; i < (int) clus->getNhits(); i++) { - my_data.hitHist->Fill(clus->getHitLayer(i), clus->getHitIPhi(i), clus->getHitIT(i), clus->getHitAdc(i)); sigmaLayer += pow(clus->getHitLayer(i) - meanLayer, 2); sigmaIPhi += pow(clus->getHitIPhi(i) - meanIPhi, 2); sigmaIT += pow(clus->getHitIT(i) - meanIT, 2); - + sigmaWeightedLayer += clus->getHitAdc(i) * pow(clus->getHitLayer(i) - (layerSum / adcSum), 2); sigmaWeightedIPhi += clus->getHitAdc(i) * pow(clus->getHitIPhi(i) - (iphiSum / adcSum), 2); sigmaWeightedIT += clus->getHitAdc(i) * pow(clus->getHitIT(i) - (itSum / adcSum), 2); @@ -451,20 +630,18 @@ namespace bool fitSuccess = false; ROOT::Fit::Fitter *fit3D = new ROOT::Fit::Fitter; - if(my_data.doFitting) + if (my_data.doFitting) { - double par_init[7] = { - maxAdc, - meanLayer, - meanIPhi, 0.75, - meanIT, 0.5, 1 - }; + maxAdc, + meanLayer, + meanIPhi, 0.75, + meanIT, 0.5, 1}; double satThreshold = 900.0; double sigma_ADC = 20.0; - auto nll = [&](const double* par) + auto nll = [&](const double *par) { double nll_val = 0.0; @@ -472,37 +649,37 @@ namespace int ny = my_data.hitHist->GetNbinsY(); int nz = my_data.hitHist->GetNbinsZ(); - double parLayer[2] = {1.0,par[1]}; - double parPhi[4] = {1.0,par[2],par[3]}; - double parTime[4] = {1.0,par[4],par[5],par[6]}; + double parLayer[2] = {1.0, par[1]}; + double parPhi[4] = {1.0, par[2], par[3]}; + double parTime[4] = {1.0, par[4], par[5], par[6]}; double xyz[3]; for (int i = 1; i <= nx; ++i) { - xyz[0] = my_data.hitHist->GetXaxis()->GetBinCenter(i); + xyz[0] = my_data.hitHist->GetXaxis()->GetBinCenter(i); for (int j = 1; j <= ny; ++j) { - xyz[1] = my_data.hitHist->GetYaxis()->GetBinCenter(j); + xyz[1] = my_data.hitHist->GetYaxis()->GetBinCenter(j); for (int k = 1; k <= nz; ++k) { xyz[2] = my_data.hitHist->GetZaxis()->GetBinCenter(k); double observed = my_data.hitHist->GetBinContent(i, j, k); - double expected = par[0]*layerFunction(&xyz[0], parLayer)*phiFunction(&xyz[1], parPhi)*timeFunction(&xyz[2], parTime); + double expected = par[0] * layerFunction(&xyz[0], parLayer) * phiFunction(&xyz[1], parPhi) * timeFunction(&xyz[2], parTime); - if(observed <= my_data.adc_threshold) + if (observed <= my_data.adc_threshold) { double arg = (expected - my_data.adc_threshold) / (sqrt(2.0) * sigma_ADC); double tail_prob = 0.5 * TMath::Erfc(arg); nll_val -= log(tail_prob + 1e-12); } - else if(observed < satThreshold) + else if (observed < satThreshold) { double resid = (observed - expected) / sigma_ADC; nll_val += 0.5 * (resid * resid + log(2 * TMath::Pi() * sigma_ADC * sigma_ADC)); } - else if(observed >= satThreshold) + else if (observed >= satThreshold) { double arg = (satThreshold - expected) / (sqrt(2.0) * sigma_ADC); double tail_prob = 0.5 * TMath::Erfc(arg); @@ -518,35 +695,33 @@ namespace fit3D->Config().ParSettings(0).SetName("amp"); fit3D->Config().ParSettings(0).SetStepSize(10); - fit3D->Config().ParSettings(0).SetLimits(0,5000); + fit3D->Config().ParSettings(0).SetLimits(0, 5000); fit3D->Config().ParSettings(1).SetName("mu_layer"); fit3D->Config().ParSettings(1).SetStepSize(0.1); - fit3D->Config().ParSettings(1).SetLimits(usedLayer[0],*usedLayer.rbegin()); + fit3D->Config().ParSettings(1).SetLimits(usedLayer[0], *usedLayer.rbegin()); fit3D->Config().ParSettings(2).SetName("mu_phi"); fit3D->Config().ParSettings(2).SetStepSize(0.1); - fit3D->Config().ParSettings(2).SetLimits(usedIPhi[0],*usedIPhi.rbegin()); + fit3D->Config().ParSettings(2).SetLimits(usedIPhi[0], *usedIPhi.rbegin()); fit3D->Config().ParSettings(3).SetName("sig_phi"); fit3D->Config().ParSettings(3).SetStepSize(0.1); - fit3D->Config().ParSettings(3).SetLimits(0.01,2); + fit3D->Config().ParSettings(3).SetLimits(0.01, 2); fit3D->Config().ParSettings(4).SetName("mu_t"); fit3D->Config().ParSettings(4).SetStepSize(0.1); - fit3D->Config().ParSettings(4).SetLimits(usedIT[0],*usedIT.rbegin()); + fit3D->Config().ParSettings(4).SetLimits(usedIT[0], *usedIT.rbegin()); fit3D->Config().ParSettings(5).SetName("sig_t"); fit3D->Config().ParSettings(5).SetStepSize(0.1); - fit3D->Config().ParSettings(5).SetLimits(0.01,10); + fit3D->Config().ParSettings(5).SetLimits(0.01, 10); fit3D->Config().ParSettings(6).SetName("lambda_t"); fit3D->Config().ParSettings(6).SetStepSize(0.01); - fit3D->Config().ParSettings(6).SetLimits(0,5); + fit3D->Config().ParSettings(6).SetLimits(0, 5); - - if(usedLayer.size() == 1) + if (usedLayer.size() == 1) { fit3D->Config().ParSettings(1).Fix(); } fitSuccess = fit3D->FitFCN(); - if (my_data.Verbosity > 2) { std::cout << "fit success: " << fitSuccess << std::endl; @@ -554,13 +729,9 @@ namespace } pthread_mutex_unlock(&mythreadlock); - - - if(my_data.doFitting && fitSuccess) + if (my_data.doFitting && fitSuccess) { - - const ROOT::Fit::FitResult& result = fit3D->Result(); - + const ROOT::Fit::FitResult &result = fit3D->Result(); PHG4TpcGeom *layergeomLow = my_data.geom_container->GetLayerCellGeom((int) floor(result.Parameter(1))); PHG4TpcGeom *layergeomHigh = my_data.geom_container->GetLayerCellGeom((int) ceil(result.Parameter(1))); @@ -569,12 +740,12 @@ namespace double RHigh = layergeomHigh->get_radius(); double phiHigh_RLow = -999.0; - if(ceil(result.Parameter(2)) < layergeomLow->get_phibins()) + if (ceil(result.Parameter(2)) < layergeomLow->get_phibins()) { phiHigh_RLow = layergeomLow->get_phi(ceil(result.Parameter(2)), (meanSide < 0 ? 0 : 1)); } double phiHigh_RHigh = -999.0; - if(ceil(result.Parameter(2)) < layergeomHigh->get_phibins()) + if (ceil(result.Parameter(2)) < layergeomHigh->get_phibins()) { phiHigh_RHigh = layergeomHigh->get_phi(ceil(result.Parameter(2)), (meanSide < 0 ? 0 : 1)); } @@ -587,18 +758,17 @@ namespace double meanPhi_RLow = ((result.Parameter(2) - floor(result.Parameter(2)))) * (phiHigh_RLow - phiLow_RLow) + phiLow_RLow; double meanPhi_RHigh = ((result.Parameter(2) - floor(result.Parameter(2)))) * (phiHigh_RHigh - phiLow_RHigh) + phiLow_RHigh; - double meanPhi = 0.5*(meanPhi_RLow + meanPhi_RHigh); - if(phiHigh_RLow == -999.0 && phiHigh_RHigh != -999.0) + double meanPhi = 0.5 * (meanPhi_RLow + meanPhi_RHigh); + if (phiHigh_RLow == -999.0 && phiHigh_RHigh != -999.0) { meanPhi = meanPhi_RHigh; } - else if(phiHigh_RLow != -999.0 && phiHigh_RHigh == -999.0) + else if (phiHigh_RLow != -999.0 && phiHigh_RHigh == -999.0) { meanPhi = meanPhi_RLow; } - - if(phiHigh_RLow == -999.0 && phiHigh_RHigh == -999.0) + if (phiHigh_RLow == -999.0 && phiHigh_RHigh == -999.0) { clus->setAdc(adcSum); clus->setX(clusX); @@ -619,10 +789,10 @@ namespace clus->setSDWeightedIT(sqrt(sigmaWeightedIT / adcSum)); } else - { + { clus->setAdc(adcSum); - clus->setX(meanR*cos(meanPhi)); - clus->setY(meanR*sin(meanPhi)); + clus->setX(meanR * cos(meanPhi)); + clus->setY(meanR * sin(meanPhi)); clus->setZ(clusZ); clus->setFitMode(true); clus->setLayer(result.Parameter(1)); @@ -660,28 +830,79 @@ namespace clus->setSDWeightedIT(sqrt(sigmaWeightedIT / adcSum)); } + + pthread_mutex_lock(&mythreadlock); + // Get surface of max ADC hit + bool alignmentflag = alignmentTransformationContainer::use_alignment; + alignmentTransformationContainer::use_alignment = false; + Acts::Vector3 ideal(clus->getX(), clus->getY(), clus->getZ()); + TrkrDefs::subsurfkey subsurfkey = 0; + + Surface surface = my_data.tGeometry->get_tpc_surface_from_coords( + maxKey, + ideal, + subsurfkey); + + if (!surface) + { + // try second maximum ADC hit + if (secondmaxKey != 0) + { + surface = my_data.tGeometry->get_tpc_surface_from_coords( + secondmaxKey, + ideal, + subsurfkey); + } + + // if still no surface, skip this cluster + if (!surface) + { + // clean up + alignmentTransformationContainer::use_alignment = alignmentflag; + delete clus; + delete fit3D; + if (my_data.hitHist) + { + delete my_data.hitHist; + my_data.hitHist = nullptr; + } + pthread_mutex_unlock(&mythreadlock); + return; + } + } + + // Convert from ideal TPC coordinates to surface coordinates + Acts::Vector3 local = surface->transform(my_data.tGeometry->geometry().getGeoContext()).inverse() * (ideal * Acts::UnitConstants::cm); + local /= Acts::UnitConstants::cm; + + // Convert back to TPC coordinates with alignment applied + alignmentTransformationContainer::use_alignment = true; + Acts::Vector3 global = surface->transform(my_data.tGeometry->geometry().getGeoContext()) * (local * Acts::UnitConstants::cm); + global /= Acts::UnitConstants::cm; + clus->setX(global(0)); + clus->setY(global(1)); + clus->setZ(global(2)); + + alignmentTransformationContainer::use_alignment = alignmentflag; + pthread_mutex_unlock(&mythreadlock); + + const auto ckey = TrkrDefs::genClusKey(maxKey, my_data.cluster_vector.size()); my_data.cluster_vector.push_back(clus); my_data.cluster_key_vector.push_back(ckey); + - if(fit3D) - { - delete fit3D; - } + delete fit3D; - if(my_data.hitHist) + if (my_data.hitHist) { delete my_data.hitHist; my_data.hitHist = nullptr; } - - } - void ProcessModuleData(thread_data *my_data) { - if (my_data->Verbosity > 2) { pthread_mutex_lock(&mythreadlock); @@ -693,85 +914,84 @@ namespace std::multimap adcMap; - if (my_data->hitsets.size() == 0) + if (my_data->hitsets.empty()) { return; } - for(int i=0; i<(int)my_data->hitsets.size(); i++) + for (int i = 0; i < (int) my_data->hitsets.size(); i++) { auto *hitset = my_data->hitsets[i]; unsigned int layer = my_data->layers[i]; bool side = my_data->side; unsigned int sector = my_data->sector; - TrkrDefs::hitsetkey hitsetKey = TpcDefs::genHitSetKey(layer, sector, (int)side); + TrkrDefs::hitsetkey hitsetKey = TpcDefs::genHitSetKey(layer, sector, (int) side); TrkrHitSet::ConstRange hitrangei = hitset->getHits(); for (TrkrHitSet::ConstIterator hitr = hitrangei.first; hitr != hitrangei.second; ++hitr) { - float_t fadc = hitr->second->getAdc(); - unsigned short adc = 0; - if (fadc > my_data->adc_threshold) - { - adc = (unsigned short) fadc; - } - else - { - continue; - } - - int iphi = TpcDefs::getPad(hitr->first); - int it = TpcDefs::getTBin(hitr->first); - - if(fabs(it - my_data->peakTimeBin) > 5) - { - continue; - } - - point coords = point((int) layer, iphi, it); - - std::vector testduplicate; - rtree.query(bgi::intersects(box(point(layer - 0.001, iphi - 0.001, it - 0.001), - point(layer + 0.001, iphi + 0.001, it + 0.001))), - std::back_inserter(testduplicate)); - if (!testduplicate.empty()) - { - testduplicate.clear(); - continue; - } - - TrkrDefs::hitkey hitKey = TpcDefs::genHitKey(iphi, it); - - auto spechitkey = std::make_pair(hitKey, hitsetKey); - pointKeyLaser coordsKey = std::make_pair(coords, spechitkey); - adcMap.insert(std::make_pair(adc, coordsKey)); + double_t fadc = hitr->second->getAdc(); + unsigned short adc = 0; + if (fadc > my_data->adc_threshold) + { + adc = (unsigned short) fadc; + } + else + { + continue; + } + + int iphi = TpcDefs::getPad(hitr->first); + int it = TpcDefs::getTBin(hitr->first); + + if (fabs(it - my_data->peakTimeBin) > 5) + { + continue; + } + + point coords = point((int) layer, iphi, it); + + std::vector testduplicate; + rtree.query(bgi::intersects(box(point(layer - 0.001, iphi - 0.001, it - 0.001), + point(layer + 0.001, iphi + 0.001, it + 0.001))), + std::back_inserter(testduplicate)); + if (!testduplicate.empty()) + { + testduplicate.clear(); + continue; + } + + TrkrDefs::hitkey hitKey = TpcDefs::genHitKey(iphi, it); + + auto spechitkey = std::make_pair(hitKey, hitsetKey); + pointKeyLaser coordsKey = std::make_pair(coords, spechitkey); + adcMap.insert(std::make_pair(adc, coordsKey)); auto adckey = std::make_pair(adc, spechitkey); - rtree.insert(std::make_pair(point(1.0*layer, 1.0*iphi, 1.0*it), adckey)); + rtree.insert(std::make_pair(point(1.0 * layer, 1.0 * iphi, 1.0 * it), adckey)); } } - //finished filling rtree + // finished filling rtree - while (adcMap.size() > 0) + while (!adcMap.empty()) { auto iterKey = adcMap.rbegin(); - if(iterKey == adcMap.rend()) + if (iterKey == adcMap.rend()) { - break; + break; } - auto coords = iterKey->second.first; int layer = coords.get<0>(); int iphi = coords.get<1>(); int it = coords.get<2>(); - + if (my_data->Verbosity > 2) { pthread_mutex_lock(&mythreadlock); - std::cout << "working on cluster " << my_data->cluster_vector.size() << " side: " << my_data->side << " sector: " << my_data->sector << " module: " << (layer<23 ? 1 : (layer<39 ? 2 : 3) ) << std::endl; + // NOLINTNEXTLINE (readability-avoid-nested-conditional-operator) + std::cout << "working on cluster " << my_data->cluster_vector.size() << " side: " << my_data->side << " sector: " << my_data->sector << " module: " << (layer < 23 ? 1 : (layer < 39 ? 2 : 3)) << std::endl; pthread_mutex_unlock(&mythreadlock); - } std::vector clusHits; @@ -781,17 +1001,16 @@ namespace calc_cluster_parameter(clusHits, *my_data, iterKey->second.second); remove_hits(clusHits, rtree, adcMap); - } } void *ProcessModule(void *threadarg) { - auto my_data = static_cast(threadarg); + auto *my_data = static_cast(threadarg); ProcessModuleData(my_data); pthread_exit(nullptr); } -} //namespace +} // namespace LaserClusterizer::LaserClusterizer(const std::string &name) : SubsysReco(name) @@ -818,7 +1037,7 @@ int LaserClusterizer::InitRun(PHCompositeNode *topNode) { laserClusterNodeName = "LAMINATION_CLUSTER"; } - auto laserclusters = findNode::getClass(dstNode, laserClusterNodeName); + auto *laserclusters = findNode::getClass(dstNode, laserClusterNodeName); if (!laserclusters) { PHNodeIterator dstiter(dstNode); @@ -835,7 +1054,7 @@ int LaserClusterizer::InitRun(PHCompositeNode *topNode) new PHIODataNode(laserclusters, laserClusterNodeName, "PHObject"); DetNode->addNode(LaserClusterContainerNode); } - + m_geom_container = findNode::getClass(topNode, "TPCGEOMCONTAINER"); if (!m_geom_container) @@ -846,6 +1065,7 @@ int LaserClusterizer::InitRun(PHCompositeNode *topNode) // get the first layer to get the clock freq AdcClockPeriod = m_geom_container->GetFirstLayerCellGeom()->get_zstep(); m_tdriftmax = AdcClockPeriod * NZBinsSide; + return Fun4AllReturnCodes::EVENT_OK; } @@ -873,7 +1093,7 @@ int LaserClusterizer::process_event(PHCompositeNode *topNode) return Fun4AllReturnCodes::ABORTRUN; } - if((eventHeader->get_RunNumber() > 66153 && !m_laserEventInfo->isGl1LaserEvent()) || (eventHeader->get_RunNumber() <= 66153 && !m_laserEventInfo->isLaserEvent())) + if ((eventHeader->get_RunNumber() > 66153 && !m_laserEventInfo->isGl1LaserEvent()) || (eventHeader->get_RunNumber() <= 66153 && !m_laserEventInfo->isLaserEvent())) { return Fun4AllReturnCodes::EVENT_OK; } @@ -897,7 +1117,7 @@ int LaserClusterizer::process_event(PHCompositeNode *topNode) std::cout << PHWHERE << "ERROR: Can't find node TRKR_HITSET" << std::endl; return Fun4AllReturnCodes::ABORTRUN; } - + // get node for clusters std::string laserClusterNodeName = "LASER_CLUSTER"; if (m_lamination) @@ -921,8 +1141,8 @@ int LaserClusterizer::process_event(PHCompositeNode *topNode) return Fun4AllReturnCodes::ABORTRUN; } - TrkrHitSetContainer::ConstRange hitsetrange = m_hits->getHitSets(TrkrDefs::TrkrId::tpcId);; - + TrkrHitSetContainer::ConstRange hitsetrange = m_hits->getHitSets(TrkrDefs::TrkrId::tpcId); + struct thread_pair_t { pthread_t thread{}; @@ -938,123 +1158,122 @@ int LaserClusterizer::process_event(PHCompositeNode *topNode) if (pthread_mutex_init(&mythreadlock, nullptr) != 0) { - std::cout << std::endl << " mutex init failed" << std::endl; + std::cout << std::endl + << " mutex init failed" << std::endl; return 1; } - - for (unsigned int sec=0; sec<12; sec++) + + for (unsigned int sec = 0; sec < 12; sec++) { - for (int s=0; s<2; s++) + for (int s = 0; s < 2; s++) { - for (unsigned int mod=0; mod<3; mod++) + for (unsigned int mod = 0; mod < 3; mod++) { - - if(Verbosity() > 2) + if (Verbosity() > 2) { std::cout << "making thread for side: " << s << " sector: " << sec << " module: " << mod << std::endl; } - thread_pair_t &thread_pair = threads.emplace_back(); - - std::vector hitsets; - std::vector layers; - - std::vector cluster_vector; - std::vector cluster_key_vector; - - for (TrkrHitSetContainer::ConstIterator hitsetitr = hitsetrange.first; - hitsetitr != hitsetrange.second; - ++hitsetitr) - { - unsigned int layer = TrkrDefs::getLayer(hitsetitr->first); - int side = TpcDefs::getSide(hitsetitr->first); - unsigned int sector = TpcDefs::getSectorId(hitsetitr->first); - if (sector != sec || side != s) - { - continue; - } - if ((mod==0 && (layer<7 || layer>22)) || (mod==1 && (layer<=22 || layer>38) ) || (mod==2 && (layer<=38 || layer>54))) - { - continue; - } - - TrkrHitSet *hitset = hitsetitr->second; - - hitsets.push_back(hitset); - layers.push_back(layer); - - } - - thread_pair.data.geom_container = m_geom_container; - thread_pair.data.tGeometry = m_tGeometry; - thread_pair.data.hitsets = hitsets; - thread_pair.data.layers = layers; - thread_pair.data.side = (bool)s; - thread_pair.data.sector = sec; + thread_pair_t &thread_pair = threads.emplace_back(); + + std::vector hitsets; + std::vector layers; + + std::vector cluster_vector; + std::vector cluster_key_vector; + + for (TrkrHitSetContainer::ConstIterator hitsetitr = hitsetrange.first; + hitsetitr != hitsetrange.second; + ++hitsetitr) + { + unsigned int layer = TrkrDefs::getLayer(hitsetitr->first); + int side = TpcDefs::getSide(hitsetitr->first); + unsigned int sector = TpcDefs::getSectorId(hitsetitr->first); + if (sector != sec || side != s) + { + continue; + } + if ((mod == 0 && (layer < 7 || layer > 22)) || (mod == 1 && (layer <= 22 || layer > 38)) || (mod == 2 && (layer <= 38 || layer > 54))) + { + continue; + } + + TrkrHitSet *hitset = hitsetitr->second; + + hitsets.push_back(hitset); + layers.push_back(layer); + } + + thread_pair.data.geom_container = m_geom_container; + thread_pair.data.tGeometry = m_tGeometry; + thread_pair.data.hitsets = hitsets; + thread_pair.data.layers = layers; + thread_pair.data.side = (bool) s; + thread_pair.data.sector = sec; thread_pair.data.module = mod; - thread_pair.data.cluster_vector = cluster_vector; - thread_pair.data.cluster_key_vector = cluster_key_vector; - thread_pair.data.adc_threshold = m_adc_threshold; - thread_pair.data.peakTimeBin = m_laserEventInfo->getPeakSample(s); - thread_pair.data.layerMin = 3; - thread_pair.data.layerMax = 3; - thread_pair.data.tdriftmax = m_tdriftmax; + thread_pair.data.cluster_vector = cluster_vector; + thread_pair.data.cluster_key_vector = cluster_key_vector; + thread_pair.data.adc_threshold = m_adc_threshold; + thread_pair.data.peakTimeBin = m_laserEventInfo->getPeakSample(s); + thread_pair.data.layerMin = 3; + thread_pair.data.layerMax = 3; + thread_pair.data.tdriftmax = m_tdriftmax; thread_pair.data.eventNum = m_event; thread_pair.data.Verbosity = Verbosity(); thread_pair.data.hitHist = nullptr; thread_pair.data.doFitting = m_do_fitting; - int rc; - rc = pthread_create(&thread_pair.thread, &attr, ProcessModule, (void *) &thread_pair.data); - - if (rc) - { - std::cout << "Error:unable to create thread," << rc << std::endl; - } - - if (m_do_sequential) - { - //wait for termination of thread - int rc2 = pthread_join(thread_pair.thread, nullptr); - if (rc2) - { - std::cout << "Error:unable to join," << rc2 << std::endl; - } - - //add clusters from thread to laserClusterContainer - const auto &data(thread_pair.data); - for(int index = 0; index < (int) data.cluster_vector.size(); ++index) - { - auto cluster = data.cluster_vector[index]; - const auto ckey = data.cluster_key_vector[index]; - - m_clusterlist->addClusterSpecifyKey(ckey, cluster); - } - } + int rc; + rc = pthread_create(&thread_pair.thread, &attr, ProcessModule, (void *) &thread_pair.data); + + if (rc) + { + std::cout << "Error:unable to create thread," << rc << std::endl; + } + + if (m_do_sequential) + { + // wait for termination of thread + int rc2 = pthread_join(thread_pair.thread, nullptr); + if (rc2) + { + std::cout << "Error:unable to join," << rc2 << std::endl; + } + + // add clusters from thread to laserClusterContainer + const auto &data(thread_pair.data); + for (int index = 0; index < (int) data.cluster_vector.size(); ++index) + { + auto *cluster = data.cluster_vector[index]; + const auto ckey = data.cluster_key_vector[index]; + + m_clusterlist->addClusterSpecifyKey(ckey, cluster); + } + } } } } - + pthread_attr_destroy(&attr); if (!m_do_sequential) { - for (const auto & thread_pair : threads) + for (const auto &thread_pair : threads) { int rc2 = pthread_join(thread_pair.thread, nullptr); if (rc2) { - std::cout << "Error:unable to join," << rc2 << std::endl; + std::cout << "Error:unable to join," << rc2 << std::endl; } - - //const auto &data(thread_pair.data); - - for(int index = 0; index < (int) thread_pair.data.cluster_vector.size(); ++index) + + // const auto &data(thread_pair.data); + + for (int index = 0; index < (int) thread_pair.data.cluster_vector.size(); ++index) { - auto cluster = thread_pair.data.cluster_vector[index]; - const auto ckey = thread_pair.data.cluster_key_vector[index]; - - m_clusterlist->addClusterSpecifyKey(ckey, cluster); + auto *cluster = thread_pair.data.cluster_vector[index]; + const auto ckey = thread_pair.data.cluster_key_vector[index]; + + m_clusterlist->addClusterSpecifyKey(ckey, cluster); } } } @@ -1067,5 +1286,4 @@ int LaserClusterizer::process_event(PHCompositeNode *topNode) } return Fun4AllReturnCodes::EVENT_OK; - } diff --git a/offline/packages/tpc/LaserClusterizer.h b/offline/packages/tpc/LaserClusterizer.h index 8dc501a64f..28e4aaac73 100644 --- a/offline/packages/tpc/LaserClusterizer.h +++ b/offline/packages/tpc/LaserClusterizer.h @@ -40,9 +40,9 @@ class LaserClusterizer : public SubsysReco //void calc_cluster_parameter(std::vector &clusHits, std::multimap, std::array>> &adcMap, bool isLamination); //void remove_hits(std::vector &clusHits, boost::geometry::index::rtree> &rtree, std::multimap, std::array>> &adcMap); - void set_adc_threshold(float val) { m_adc_threshold = val; } - void set_min_clus_size(float val) { min_clus_size = val; } - void set_min_adc_sum(float val) { min_adc_sum = val; } + void set_adc_threshold(double val) { m_adc_threshold = val; } + void set_min_clus_size(double val) { min_clus_size = val; } + void set_min_adc_sum(double val) { min_adc_sum = val; } void set_max_time_samples(int val) { m_time_samples_max = val; } void set_lamination(bool val) { m_lamination = val; } void set_do_sequential(bool val) { m_do_sequential = val; } diff --git a/offline/packages/tpc/LaserEventIdentifier.cc b/offline/packages/tpc/LaserEventIdentifier.cc index 8b6035db05..3c214161ae 100644 --- a/offline/packages/tpc/LaserEventIdentifier.cc +++ b/offline/packages/tpc/LaserEventIdentifier.cc @@ -89,7 +89,7 @@ int LaserEventIdentifier::InitRun(PHCompositeNode *topNode) { m_debugFile = new TFile(m_debugFileName.c_str(), "RECREATE"); } - float timeHistMax = m_time_samples_max; + double timeHistMax = m_time_samples_max; timeHistMax -= 0.5; m_itHist_0 = new TH1I("m_itHist_0", "side 0;it", m_time_samples_max, -0.5, timeHistMax); m_itHist_1 = new TH1I("m_itHist_1", "side 1;it", m_time_samples_max, -0.5, timeHistMax); @@ -130,7 +130,7 @@ int LaserEventIdentifier::process_event(PHCompositeNode *topNode) } else if(m_runnumber > 66153) { - if ((gl1pkt->getGTMAllBusyVector() & (1<<14)) == 0) + if ((gl1pkt->getGTMAllBusyVector() & (1U<<14U)) == 0) { m_laserEventInfo->setIsGl1LaserEvent(true); m_laserEventInfo->setIsGl1LaserPileupEvent(false); diff --git a/offline/packages/tpc/LaserEventIdentifier.h b/offline/packages/tpc/LaserEventIdentifier.h index 5c0c5faf54..fa4f43733f 100644 --- a/offline/packages/tpc/LaserEventIdentifier.h +++ b/offline/packages/tpc/LaserEventIdentifier.h @@ -53,8 +53,8 @@ class LaserEventIdentifier : public SubsysReco bool isGl1LaserPileupEvent = false; int peakSample0 = -999; int peakSample1 = -999; - float peakWidth0 = -999; - float peakWidth1 = -999; + double peakWidth0 = -999; + double peakWidth1 = -999; int m_runnumber = 0; uint64_t prev_BCO = 0; diff --git a/offline/packages/tpc/Tpc3DClusterizer.cc b/offline/packages/tpc/Tpc3DClusterizer.cc index e19cbf507f..71a0b0f7c0 100644 --- a/offline/packages/tpc/Tpc3DClusterizer.cc +++ b/offline/packages/tpc/Tpc3DClusterizer.cc @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -49,7 +50,7 @@ namespace bg = boost::geometry; namespace bgi = boost::geometry::index; -using point = bg::model::point; +using point = bg::model::point; using box = bg::model::box; using specHitKey = std::pair; using pointKeyLaser = std::pair; @@ -72,7 +73,7 @@ int Tpc3DClusterizer::InitRun(PHCompositeNode *topNode) } // Create the Cluster node if required - auto laserclusters = findNode::getClass(dstNode, "LASER_CLUSTER"); + auto *laserclusters = findNode::getClass(dstNode, "LASER_CLUSTER"); if (!laserclusters) { PHNodeIterator dstiter(dstNode); @@ -111,13 +112,14 @@ int Tpc3DClusterizer::InitRun(PHCompositeNode *topNode) m_clusterTree->Branch("time_erase", &time_erase); m_clusterTree->Branch("time_all", &time_all); } - - if (m_output){ + + if (m_output) + { m_outputFile = new TFile(m_outputFileName.c_str(), "RECREATE"); - m_clusterNT = new TNtuple("clus3D", "clus3D","event:seed:x:y:z:r:phi:phibin:tbin:adc:maxadc:layer:phielem:zelem:size:phisize:tsize:lsize"); + m_clusterNT = new TNtuple("clus3D", "clus3D", "event:seed:x:y:z:r:phi:phibin:tbin:adc:maxadc:layer:phielem:zelem:size:phisize:tsize:lsize"); } - + m_geom_container = findNode::getClass(topNode, "TPCGEOMCONTAINER"); if (!m_geom_container) @@ -145,10 +147,13 @@ int Tpc3DClusterizer::InitRun(PHCompositeNode *topNode) int Tpc3DClusterizer::process_event(PHCompositeNode *topNode) { ++m_event; - recoConsts* rc = recoConsts::instance(); - if (rc->FlagExist("RANDOMSEED")){ - m_seed = (int)rc->get_IntFlag("RANDOMSEED"); - } else { + recoConsts *rc = recoConsts::instance(); + if (rc->FlagExist("RANDOMSEED")) + { + m_seed = rc->get_IntFlag("RANDOMSEED"); + } + else + { m_seed = std::numeric_limits::quiet_NaN(); } @@ -163,11 +168,12 @@ int Tpc3DClusterizer::process_event(PHCompositeNode *topNode) } // get node containing the digitized hits m_hits = findNode::getClass(topNode, "TRKR_HITSET"); - if (!m_hits){ + if (!m_hits) + { std::cout << PHWHERE << "ERROR: Can't find node TRKR_HITSET" << std::endl; return Fun4AllReturnCodes::ABORTRUN; } - + // get node for clusters m_clusterlist = findNode::getClass(topNode, "LASER_CLUSTER"); if (!m_clusterlist) @@ -193,7 +199,8 @@ int Tpc3DClusterizer::process_event(PHCompositeNode *topNode) bgi::rtree> rtree_reject; for (TrkrHitSetContainer::ConstIterator hitsetitr = hitsetrange.first; hitsetitr != hitsetrange.second; - ++hitsetitr){ + ++hitsetitr) + { TrkrHitSet *hitset = hitsetitr->second; unsigned int layer = TrkrDefs::getLayer(hitsetitr->first); int side = TpcDefs::getSide(hitsetitr->first); @@ -202,49 +209,54 @@ int Tpc3DClusterizer::process_event(PHCompositeNode *topNode) TrkrHitSet::ConstRange hitrangei = hitset->getHits(); for (TrkrHitSet::ConstIterator hitr = hitrangei.first; - hitr != hitrangei.second; - ++hitr){ + hitr != hitrangei.second; + ++hitr) + { int iphi = TpcDefs::getPad(hitr->first); int it = TpcDefs::getTBin(hitr->first); // std::cout << " iphi: " << iphi << " it: " << it << std::endl; - float_t fadc = (hitr->second->getAdc());// - m_pedestal; // proper int rounding +0.5 + double_t fadc = (hitr->second->getAdc()); // - m_pedestal; // proper int rounding +0.5 unsigned short adc = 0; - if (fadc > 0){ - adc = (unsigned short) fadc; + if (fadc > 0) + { + adc = (unsigned short) fadc; } - if (adc <= 0){ - continue; + if (adc <= 0) + { + continue; } - + std::vector testduplicate; rtree.query(bgi::intersects(box(point(layer - 0.001, iphi - 0.001, it - 0.001), - point(layer + 0.001, iphi + 0.001, it + 0.001))), - std::back_inserter(testduplicate)); - if (!testduplicate.empty()){ - testduplicate.clear(); - continue; + point(layer + 0.001, iphi + 0.001, it + 0.001))), + std::back_inserter(testduplicate)); + if (!testduplicate.empty()) + { + testduplicate.clear(); + continue; } TrkrDefs::hitkey hitKey = TpcDefs::genHitKey(iphi, it); - + auto spechitkey = std::make_pair(hitKey, hitsetKey); rtree_reject.insert(std::make_pair(point(1.0 * layer, 1.0 * iphi, 1.0 * it), spechitkey)); } } - + std::multimap, std::array>> adcMap; // std::cout << "n hitsets: " << std::distance(hitsetrange.first,hitsetrange.second) // << std::endl; for (TrkrHitSetContainer::ConstIterator hitsetitr = hitsetrange.first; hitsetitr != hitsetrange.second; - ++hitsetitr){ + ++hitsetitr) + { TrkrHitSet *hitset = hitsetitr->second; unsigned int layer = TrkrDefs::getLayer(hitsetitr->first); int side = TpcDefs::getSide(hitsetitr->first); unsigned int sector = TpcDefs::getSectorId(hitsetitr->first); - //PHG4TpcGeom *layergeom = m_geom_container->GetLayerCellGeom(layer); - // double r = layergeom->get_radius(); - + // PHG4TpcGeom *layergeom = m_geom_container->GetLayerCellGeom(layer); + // double r = layergeom->get_radius(); + TrkrDefs::hitsetkey hitsetKey = TpcDefs::genHitSetKey(layer, sector, side); TrkrHitSet::ConstRange hitrangei = hitset->getHits(); @@ -252,74 +264,122 @@ int Tpc3DClusterizer::process_event(PHCompositeNode *topNode) // << std::endl; // int nhits = 0; for (TrkrHitSet::ConstIterator hitr = hitrangei.first; - hitr != hitrangei.second; - ++hitr){ + hitr != hitrangei.second; + ++hitr) + { int iphi = TpcDefs::getPad(hitr->first); int it = TpcDefs::getTBin(hitr->first); // std::cout << " iphi: " << iphi << " it: " << it << std::endl; - float_t fadc = (hitr->second->getAdc());// - m_pedestal; // proper int rounding +0.5 + double_t fadc = (hitr->second->getAdc()); // - m_pedestal; // proper int rounding +0.5 unsigned short adc = 0; // std::cout << " nhit: " << nhits++ << "adc: " << fadc << " phi: " << iphi << " it: " << it << std::endl; - if (fadc > 0){ - adc = (unsigned short) fadc; + if (fadc > 0) + { + adc = (unsigned short) fadc; } - if (adc <= 0){ - continue; + if (adc <= 0) + { + continue; } - if(layer>=7+32){ - //if(side==1)continue; - if(abs(iphi-0)<=2) continue; - if(abs(iphi-191)<=2) continue; - if(abs(iphi-206)<=1) continue; - if(abs(iphi-383)<=2) continue; - if(abs(iphi-576)<=2) continue; - if(abs(iphi-767)<=2) continue; - if(abs(iphi-960)<=2) continue; - if(abs(iphi-1522)<=2) continue; - if(abs(iphi-1344)<=2) continue; - if(abs(iphi-1536)<=2) continue; - if(abs(iphi-1728)<=2) continue; - if(abs(iphi-1920)<=2) continue; - if(abs(iphi-2111)<=2) continue; - if(abs(iphi-2303)<=2) continue; + if (layer >= 7 + 32) + { + // if(side==1)continue; + if (abs(iphi - 0) <= 2) + { + continue; + } + if (abs(iphi - 191) <= 2) + { + continue; + } + if (abs(iphi - 206) <= 1) + { + continue; + } + if (abs(iphi - 383) <= 2) + { + continue; + } + if (abs(iphi - 576) <= 2) + { + continue; + } + if (abs(iphi - 767) <= 2) + { + continue; + } + if (abs(iphi - 960) <= 2) + { + continue; + } + if (abs(iphi - 1522) <= 2) + { + continue; + } + if (abs(iphi - 1344) <= 2) + { + continue; + } + if (abs(iphi - 1536) <= 2) + { + continue; + } + if (abs(iphi - 1728) <= 2) + { + continue; + } + if (abs(iphi - 1920) <= 2) + { + continue; + } + if (abs(iphi - 2111) <= 2) + { + continue; + } + if (abs(iphi - 2303) <= 2) + { + continue; + } } /* double phi = layergeom->get_phi(iphi); double m_sampa_tbias = 39.6; double zdriftlength = (layergeom->get_zcenter(it)+ m_sampa_tbias) * m_tGeometry->get_drift_velocity(); - - float x = r * cos(phi); - float y = r * sin(phi); - float z = m_tdriftmax * m_tGeometry->get_drift_velocity() - zdriftlength; + + double x = r * cos(phi); + double y = r * sin(phi); + double z = m_tdriftmax * m_tGeometry->get_drift_velocity() - zdriftlength; if (side == 0){ - z = -z; - it = -it; + z = -z; + it = -it; } */ std::array coords = {(int) layer, iphi, it}; - + std::vector testduplicate; rtree.query(bgi::intersects(box(point(layer - 0.001, iphi - 0.001, it - 0.001), - point(layer + 0.001, iphi + 0.001, it + 0.001))), - std::back_inserter(testduplicate)); - if (!testduplicate.empty()){ - testduplicate.clear(); - continue; + point(layer + 0.001, iphi + 0.001, it + 0.001))), + std::back_inserter(testduplicate)); + if (!testduplicate.empty()) + { + testduplicate.clear(); + continue; } - - //test for isolated hit + + // test for isolated hit std::vector testisolated; rtree_reject.query(bgi::intersects(box(point(layer - 1.001, iphi - 1.001, it - 1.001), - point(layer + 1.001, iphi + 1.001, it + 1.001))), - std::back_inserter(testisolated)); - if(testisolated.size()==1){ - //testisolated.clear(); - continue; + point(layer + 1.001, iphi + 1.001, it + 1.001))), + std::back_inserter(testisolated)); + if (testisolated.size() == 1) + { + // testisolated.clear(); + continue; } - + TrkrDefs::hitkey hitKey = TpcDefs::genHitKey(iphi, it); - + auto spechitkey = std::make_pair(hitKey, hitsetKey); auto keyCoords = std::make_pair(spechitkey, coords); adcMap.insert(std::make_pair(adc, keyCoords)); @@ -327,38 +387,43 @@ int Tpc3DClusterizer::process_event(PHCompositeNode *topNode) rtree.insert(std::make_pair(point(1.0 * layer, 1.0 * iphi, 1.0 * it), spechitkey)); } } - - if (Verbosity() > 1){ + + if (Verbosity() > 1) + { std::cout << "finished looping over hits" << std::endl; std::cout << "map size: " << adcMap.size() << std::endl; std::cout << "rtree size: " << rtree.size() << std::endl; } - + // done filling rTree - + t_all->restart(); - - while (adcMap.size() > 0){ + + while (!adcMap.empty()) + { auto iterKey = adcMap.rbegin(); - if (iterKey == adcMap.rend()){ + if (iterKey == adcMap.rend()) + { break; } - + auto coords = iterKey->second.second; int layer = coords[0]; int iphi = coords[1]; int it = coords[2]; - + int layerMax = layer + 1; - if (layer == 22 || layer == 38 || layer == 54){ + if (layer == 22 || layer == 38 || layer == 54) + { layerMax = layer; } int layerMin = layer - 1; - if (layer == 7 || layer == 23 || layer == 39){ + if (layer == 7 || layer == 23 || layer == 39) + { layerMin = layer; } - + std::vector clusHits; t_search->restart(); @@ -376,21 +441,24 @@ int Tpc3DClusterizer::process_event(PHCompositeNode *topNode) clusHits.clear(); } - if (m_debug){ + if (m_debug) + { m_nClus = (int) m_eventClusters.size(); } t_all->stop(); - if (m_debug){ + if (m_debug) + { time_search = t_search->get_accumulated_time() / 1000.; time_clus = t_clus->get_accumulated_time() / 1000.; time_erase = t_erase->get_accumulated_time() / 1000.; time_all = t_all->get_accumulated_time() / 1000.; - + m_clusterTree->Fill(); } - - if (Verbosity()){ + + if (Verbosity()) + { std::cout << "rtree search time: " << t_search->get_accumulated_time() / 1000. << " sec" << std::endl; std::cout << "clustering time: " << t_clus->get_accumulated_time() / 1000. << " sec" << std::endl; std::cout << "erasing time: " << t_erase->get_accumulated_time() / 1000. << " sec" << std::endl; @@ -401,30 +469,33 @@ int Tpc3DClusterizer::process_event(PHCompositeNode *topNode) return Fun4AllReturnCodes::EVENT_OK; } -int Tpc3DClusterizer::ResetEvent(PHCompositeNode * /*topNode*/){ +int Tpc3DClusterizer::ResetEvent(PHCompositeNode * /*topNode*/) +{ m_itHist_0->Reset(); m_itHist_1->Reset(); - + if (m_debug) - { - m_tHist_0->Reset(); - m_tHist_1->Reset(); - - m_eventClusters.clear(); - } - + { + m_tHist_0->Reset(); + m_tHist_1->Reset(); + + m_eventClusters.clear(); + } + return Fun4AllReturnCodes::EVENT_OK; } int Tpc3DClusterizer::End(PHCompositeNode * /*topNode*/) { - if (m_debug){ + if (m_debug) + { m_debugFile->cd(); m_clusterTree->Write(); m_debugFile->Close(); } - if (m_output){ + if (m_output) + { m_outputFile->cd(); m_clusterNT->Write(); m_outputFile->Close(); @@ -434,7 +505,7 @@ int Tpc3DClusterizer::End(PHCompositeNode * /*topNode*/) void Tpc3DClusterizer::calc_cluster_parameter(std::vector &clusHits, std::multimap, std::array>> &adcMap) { - //std::cout << "nu clus" << std::endl; + // std::cout << "nu clus" << std::endl; double rSum = 0.0; double phiSum = 0.0; double tSum = 0.0; @@ -449,14 +520,17 @@ void Tpc3DClusterizer::calc_cluster_parameter(std::vector &clusHi TrkrDefs::hitsetkey maxKey = 0; unsigned int nHits = clusHits.size(); - int iphimin = 6666, iphimax = -1; - int ilaymin = 6666, ilaymax = -1; - float itmin = 66666666.6, itmax = -6666666666.6; + int iphimin = 6666; + int iphimax = -1; + int ilaymin = 6666; + int ilaymax = -1; + double itmin = 66666666.6; + double itmax = -6666666666.6; auto *clus = new LaserClusterv1; for (auto &clusHit : clusHits) { - float coords[3] = {clusHit.first.get<0>(), clusHit.first.get<1>(), clusHit.first.get<2>()}; + double coords[3] = {clusHit.first.get<0>(), clusHit.first.get<1>(), clusHit.first.get<2>()}; std::pair spechitkey = clusHit.second; int side = TpcDefs::getSide(spechitkey.second); @@ -468,21 +542,21 @@ void Tpc3DClusterizer::calc_cluster_parameter(std::vector &clusHi double phi = layergeom->get_phi(coords[1], side); double t = layergeom->get_zcenter(fabs(coords[2])); int tbin = coords[2]; - int lay = coords[0];//TrkrDefs::getLayer(spechitkey.second); + int lay = coords[0]; // TrkrDefs::getLayer(spechitkey.second); double hitzdriftlength = t * m_tGeometry->get_drift_velocity(); double hitZ = m_tdriftmax * m_tGeometry->get_drift_velocity() - hitzdriftlength; /*std::cout << " lay: " << lay - << " phi: " << phi - << " t: " << t - << " side: " << side - << std::endl; + << " phi: " << phi + << " t: " << t + << " side: " << side + << std::endl; */ - if(phiiphimax){iphimax = phi;} - if(layilaymax){ilaymax = lay;} - if(tbinitmax){itmax = tbin;} + iphimin = std::min(phi, iphimin); + iphimax = std::max(phi, iphimax); + ilaymin = std::min(lay, ilaymin); + ilaymax = std::max(lay, ilaymax); + itmin = std::min(tbin, itmin); + itmax = std::max(tbin, itmax); for (auto &iterKey : adcMap) { @@ -497,7 +571,7 @@ void Tpc3DClusterizer::calc_cluster_parameter(std::vector &clusHi clus->setHitX(clus->getNhits() - 1, r * cos(phi)); clus->setHitY(clus->getNhits() - 1, r * sin(phi)); clus->setHitZ(clus->getNhits() - 1, hitZ); - clus->setHitAdc(clus->getNhits() - 1, (float) adc); + clus->setHitAdc(clus->getNhits() - 1, adc); rSum += r * adc; phiSum += phi * adc; @@ -522,7 +596,7 @@ void Tpc3DClusterizer::calc_cluster_parameter(std::vector &clusHi if (nHits == 0) { - std::cout << "no hits"<< std::endl; + std::cout << "no hits" << std::endl; return; } @@ -554,55 +628,57 @@ void Tpc3DClusterizer::calc_cluster_parameter(std::vector &clusHi clus->setLayer(layerSum / adcSum); clus->setIPhi(iphiSum / adcSum); clus->setIT(itSum / adcSum); - int phisize = iphimax - iphimin + 1; - int lsize = ilaymax - ilaymin + 1; - int tsize = itmax - itmin +1; + int phisize = iphimax - iphimin + 1; + int lsize = ilaymax - ilaymin + 1; + int tsize = itmax - itmin + 1; if (m_debug) { m_currentCluster = (LaserCluster *) clus->CloneMe(); m_eventClusters.push_back((LaserCluster *) m_currentCluster->CloneMe()); } // if(nHits>1&&tsize>5){ - if(nHits>=1){ + if (nHits >= 1) + { const auto ckey = TrkrDefs::genClusKey(maxKey, m_clusterlist->size()); m_clusterlist->addClusterSpecifyKey(ckey, clus); - } else { + } + else + { delete clus; } - - //event:seed:x:y:z:r:phi:phibin:tbin::adc:maxadc:layer:phielem:zelem:size:phisize:tsize:lsize + // event:seed:x:y:z:r:phi:phibin:tbin::adc:maxadc:layer:phielem:zelem:size:phisize:tsize:lsize //"event:seed:x:y:z:r:phi:phibin:tbin::adc:maxadc:layer:phielem:zelem:size:phisize:tsize:lsize" /* std::cout << " l size: " << lsize - << " phisize : " << phisize - << " tsize: " << tsize - << " maxside: " << maxside - << std::endl; + << " phisize : " << phisize + << " tsize: " << tsize + << " maxside: " << maxside + << std::endl; */ // if (m_output){ - float fX[20] = {0}; - int n = 0; - fX[n++] = m_event; - fX[n++] = m_seed; - fX[n++] = clusX; - fX[n++] = clusY; - fX[n++] = clusZ; - fX[n++] = clusR; - fX[n++] = clusPhi; - fX[n++] = clusiPhi; - fX[n++] = clusT; - fX[n++] = adcSum; - fX[n++] = maxAdc; - fX[n++] = (layerSum/adcSum); - fX[n++] = maxsector; - fX[n++] = maxside; - fX[n++] = nHits; - fX[n++] = phisize; - fX[n++] = tsize; - fX[n++] = lsize; - m_clusterNT->Fill(fX); - // } + float fX[20] = {0}; + int n = 0; + fX[n++] = m_event; + fX[n++] = m_seed; + fX[n++] = clusX; + fX[n++] = clusY; + fX[n++] = clusZ; + fX[n++] = clusR; + fX[n++] = clusPhi; + fX[n++] = clusiPhi; + fX[n++] = clusT; + fX[n++] = adcSum; + fX[n++] = maxAdc; + fX[n++] = (layerSum / adcSum); + fX[n++] = maxsector; + fX[n++] = maxside; + fX[n++] = nHits; + fX[n++] = phisize; + fX[n++] = tsize; + fX[n++] = lsize; + m_clusterNT->Fill(fX); + // } } void Tpc3DClusterizer::remove_hits(std::vector &clusHits, bgi::rtree> &rtree, std::multimap, std::array>> &adcMap) @@ -611,10 +687,11 @@ void Tpc3DClusterizer::remove_hits(std::vector &clusHits, bgi::rt { auto spechitkey = clusHit.second; - if(rtree.size()==0){ + if (rtree.empty()) + { std::cout << "not good" << std::endl; } - //rtree.remove(clusHit); + // rtree.remove(clusHit); for (auto iterAdc = adcMap.begin(); iterAdc != adcMap.end();) { @@ -623,10 +700,8 @@ void Tpc3DClusterizer::remove_hits(std::vector &clusHits, bgi::rt iterAdc = adcMap.erase(iterAdc); break; } - else - { - ++iterAdc; - } + + ++iterAdc; } } } diff --git a/offline/packages/tpc/Tpc3DClusterizer.h b/offline/packages/tpc/Tpc3DClusterizer.h index 54175a3c9a..3e6ad621a9 100644 --- a/offline/packages/tpc/Tpc3DClusterizer.h +++ b/offline/packages/tpc/Tpc3DClusterizer.h @@ -34,7 +34,7 @@ class PHG4TpcGeomContainer; class Tpc3DClusterizer : public SubsysReco { public: -typedef boost::geometry::model::point point; +typedef boost::geometry::model::point point; typedef boost::geometry::model::box box; typedef std::pair specHitKey; typedef std::pair pointKeyLaser; @@ -49,7 +49,7 @@ typedef std::pair pointKeyLaser; // void calc_cluster_parameter(std::vector &clusHits, std::multimap> &adcMap); void calc_cluster_parameter(std::vector &clusHits, std::multimap, std::array>> &adcMap); - // void remove_hits(std::vector &clusHits, boost::geometry::index::rtree > &rtree, std::multimap > &adcMap, std::multimap &adcCoords); + // void remove_hits(std::vector &clusHits, boost::geometry::index::rtree > &rtree, std::multimap > &adcMap, std::multimap &adcCoords); void remove_hits(std::vector &clusHits, boost::geometry::index::rtree> &rtree, std::multimap, std::array>> &adcMap); void set_debug(bool debug) { m_debug = debug; } @@ -57,9 +57,9 @@ typedef std::pair pointKeyLaser; void set_output(bool output) { m_output = output; } void set_output_name(const std::string &name) { m_outputFileName = name; } - void set_pedestal(float val) { pedestal = val; } - void set_min_clus_size(float val) { min_clus_size = val; } - void set_min_adc_sum(float val) { min_adc_sum = val; } + void set_pedestal(double val) { pedestal = val; } + void set_min_clus_size(double val) { min_clus_size = val; } + void set_min_adc_sum(double val) { min_adc_sum = val; } private: int m_event {-1}; @@ -106,8 +106,8 @@ typedef std::pair pointKeyLaser; LaserCluster *m_currentCluster {nullptr}; std::vector m_eventClusters; - std::vector m_currentHit; - std::vector m_currentHit_hardware; + std::vector m_currentHit; + std::vector m_currentHit_hardware; std::unique_ptr t_all; std::unique_ptr t_search; diff --git a/offline/packages/tpc/TpcClusterMover.cc b/offline/packages/tpc/TpcClusterMover.cc index 643fe5587f..39c5e156d4 100644 --- a/offline/packages/tpc/TpcClusterMover.cc +++ b/offline/packages/tpc/TpcClusterMover.cc @@ -17,19 +17,20 @@ namespace { - [[maybe_unused]] std::ostream& operator << (std::ostream& out, const Acts::Vector3& v ) + [[maybe_unused]] std::ostream& operator<<(std::ostream& out, const Acts::Vector3& v) { out << "(" << v.x() << ", " << v.y() << ", " << v.z() << ")"; return out; } -} +} // namespace TpcClusterMover::TpcClusterMover() + : inner_tpc_spacing((mid_tpc_min_radius - inner_tpc_min_radius) / 16.0) + , mid_tpc_spacing((outer_tpc_min_radius - mid_tpc_min_radius) / 16.0) + , outer_tpc_spacing((outer_tpc_max_radius - outer_tpc_min_radius) / 16.0) { // initialize layer radii - inner_tpc_spacing = (mid_tpc_min_radius - inner_tpc_min_radius) / 16.0; - mid_tpc_spacing = (outer_tpc_min_radius - mid_tpc_min_radius) / 16.0; - outer_tpc_spacing = (outer_tpc_max_radius - outer_tpc_min_radius) / 16.0; + for (int i = 0; i < 16; ++i) { layer_radius[i] = inner_tpc_min_radius + (double) i * inner_tpc_spacing + 0.5 * inner_tpc_spacing; @@ -44,7 +45,7 @@ TpcClusterMover::TpcClusterMover() } } -void TpcClusterMover::initialize_geometry(PHG4TpcGeomContainer *cellgeo) +void TpcClusterMover::initialize_geometry(PHG4TpcGeomContainer* cellgeo) { if (_verbosity > 0) { @@ -65,7 +66,6 @@ void TpcClusterMover::initialize_geometry(PHG4TpcGeomContainer *cellgeo) //____________________________________________________________________________.. std::vector> TpcClusterMover::processTrack(const std::vector>& global_in) { - // Get the global positions of the TPC clusters for this track, already corrected for distortions, and move them to the surfaces // The input object contains all clusters for the track @@ -74,7 +74,7 @@ std::vector> TpcClusterMover::proces std::vector tpc_global_vec; std::vector tpc_cluskey_vec; - for (const auto& [ckey,global]:global_in) + for (const auto& [ckey, global] : global_in) { const auto trkrid = TrkrDefs::getTrkrId(ckey); if (trkrid == TrkrDefs::tpcId) @@ -85,7 +85,7 @@ std::vector> TpcClusterMover::proces else { // si clusters stay where they are - global_moved.emplace_back(ckey,global); + global_moved.emplace_back(ckey, global); } } @@ -158,7 +158,7 @@ std::vector> TpcClusterMover::proces return global_moved; } -int TpcClusterMover::get_circle_circle_intersection(double target_radius, double R, double X0, double Y0, double xclus, double yclus, double &x, double &y) +int TpcClusterMover::get_circle_circle_intersection(double target_radius, double R, double X0, double Y0, double xclus, double yclus, double& x, double& y) const { // finds the intersection of the fitted circle with the cylinder having radius = target_radius const auto [xplus, yplus, xminus, yminus] = TrackFitUtils::circle_circle_intersection(target_radius, R, X0, Y0); diff --git a/offline/packages/tpc/TpcClusterMover.h b/offline/packages/tpc/TpcClusterMover.h index dc67312f7f..92a053e990 100644 --- a/offline/packages/tpc/TpcClusterMover.h +++ b/offline/packages/tpc/TpcClusterMover.h @@ -27,7 +27,7 @@ class TpcClusterMover void initialize_geometry(PHG4TpcGeomContainer *cellgeo); private: - int get_circle_circle_intersection(double target_radius, double R, double X0, double Y0, double xclus, double yclus, double &x, double &y); + int get_circle_circle_intersection(double target_radius, double R, double X0, double Y0, double xclus, double yclus, double &x, double &y) const; double _z_start = 0.0; double _y_start = 0.0; diff --git a/offline/packages/tpc/TpcClusterZCrossingCorrection.cc b/offline/packages/tpc/TpcClusterZCrossingCorrection.cc index 24c2552f55..dc4f8589fc 100644 --- a/offline/packages/tpc/TpcClusterZCrossingCorrection.cc +++ b/offline/packages/tpc/TpcClusterZCrossingCorrection.cc @@ -13,32 +13,32 @@ #include // default value, override from macro (cm/ns) -float TpcClusterZCrossingCorrection::_vdrift = 8.0e-03; +double TpcClusterZCrossingCorrection::_vdrift = 8.0e-03; // ns, same value as in pileup generator -float TpcClusterZCrossingCorrection::_time_between_crossings = sphenix_constants::time_between_crossings; +double TpcClusterZCrossingCorrection::_time_between_crossings = sphenix_constants::time_between_crossings; //______________________________________________________________________________________________ -float TpcClusterZCrossingCorrection::correctZ(float zinit, unsigned int side, short int crossing) +double TpcClusterZCrossingCorrection::correctZ(double zinit, unsigned int side, short int crossing) { if (crossing == std::numeric_limits::max()) { - return std::numeric_limits::quiet_NaN(); + return std::numeric_limits::quiet_NaN(); } - float z_bunch_separation = _time_between_crossings * _vdrift; + double z_bunch_separation = _time_between_crossings * _vdrift; // +ve crossing occurs in the future relative to time zero // -ve z side (south, side 0), cluster arrives late, so z seems more positive // +ve z side (north, side 1), cluster arrives late, so z seems more negative - float corrected_z; + double corrected_z; if (side == 0) { - corrected_z = zinit - (float) crossing * z_bunch_separation; + corrected_z = zinit - (double) crossing * z_bunch_separation; } else { - corrected_z = zinit + (float) crossing * z_bunch_separation; + corrected_z = zinit + (double) crossing * z_bunch_separation; } // std::cout << " TpcClusterZCrossingCorrection: crossing " << crossing << " _vdrift " << _vdrift << " zinit " << zinit << " side " << side << " z_bunch_separation " << z_bunch_separation << " corrected_z " << corrected_z << std::endl; diff --git a/offline/packages/tpc/TpcClusterZCrossingCorrection.h b/offline/packages/tpc/TpcClusterZCrossingCorrection.h index 5a95ca7f86..8321d31f7d 100644 --- a/offline/packages/tpc/TpcClusterZCrossingCorrection.h +++ b/offline/packages/tpc/TpcClusterZCrossingCorrection.h @@ -15,34 +15,34 @@ class TpcClusterZCrossingCorrection //@{ //! drift velocity (cm/ns) - static float get_vdrift() { return _vdrift; } + static double get_vdrift() { return _vdrift; } //! time between crossing (ns) - static float get_time_between_crossings() { return _time_between_crossings; } + static double get_time_between_crossings() { return _time_between_crossings; } //! apply correction on a given z - static float correctZ(float zinit, unsigned int side, short int crossing); + static double correctZ(double zinit, unsigned int side, short int crossing); //@} //!@name modifiers //@{ //! drift velocity (cm/ns) - static void set_vdrift( float value ) { _vdrift = value; } + static void set_vdrift( double value ) { _vdrift = value; } //! time between crossing (ns) - static void set_time_between_crossings( float value ) { _time_between_crossings = value; } + static void set_time_between_crossings( double value ) { _time_between_crossings = value; } //@} // TODO: move to private //!@name parameters //@{ //! drift velocity (cm/ns) - static float _vdrift; + static double _vdrift; private: //! time between crossing (ns) - static float _time_between_crossings; + static double _time_between_crossings; //@} diff --git a/offline/packages/tpc/TpcClusterizer.cc b/offline/packages/tpc/TpcClusterizer.cc index bd5fc3c340..dc815eacae 100644 --- a/offline/packages/tpc/TpcClusterizer.cc +++ b/offline/packages/tpc/TpcClusterizer.cc @@ -25,7 +25,6 @@ #include #include #include -#include #include #include // for SubsysReco @@ -36,6 +35,9 @@ #include #include +#include +#include + #include #include // for PHIODataNode #include // for PHNode @@ -50,6 +52,8 @@ #include +#include +#include #include #include // for sqrt, cos, sin #include @@ -58,13 +62,14 @@ #include #include // for pair #include +#include // Terra incognita.... #include namespace { template - inline constexpr T square(const T &x) + constexpr T square(const T &x) { return x * x; } @@ -96,16 +101,16 @@ namespace unsigned int layer = 0; int side = 0; unsigned int sector = 0; - float radius = 0; - float drift_velocity = 0; + double radius = 0; + double drift_velocity = 0; unsigned short pads_per_sector = 0; - float phistep = 0; - float pedestal = 0; - float seed_threshold = 0; - float edge_threshold = 0; - float min_err_squared = 0; - float min_clus_size = 0; - float min_adc_sum = 0; + double phistep = 0; + double pedestal = 0; + double seed_threshold = 0; + double edge_threshold = 0; + double min_err_squared = 0; + double min_clus_size = 0; + double min_adc_sum = 0; bool do_assoc = true; bool do_wedge_emulation = true; bool do_singles = true; @@ -118,6 +123,13 @@ namespace unsigned short maxHalfSizeT = 0; unsigned short maxHalfSizePhi = 0; double m_tdriftmax = 0; + + // --- new members for dead/hot map --- + hitMaskTpcSet *deadMap = nullptr; + hitMaskTpcSet *hotMap = nullptr; + bool maskDead = false; + bool maskHot = false; + std::vector association_vector; std::vector cluster_vector; std::vector v_hits; @@ -360,25 +372,19 @@ namespace int is_hit_isolated(int iphi, int it, int NPhiBinsMax, int NTBinsMax, const std::vector> &adcval) { // check isolated hits - // const int NPhiBinsMax = (int) my_data.phibins; + // const int NPhiBinsMax = (int) my_data.phibins; // const int NTBinsMax = (int) my_data.tbins; int isosum = 0; int isophimin = iphi - 1; - if (isophimin < 0) - { - isophimin = 0; - } + isophimin = std::max(isophimin, 0); int isophimax = iphi + 1; if (!(isophimax < NPhiBinsMax)) { isophimax = NPhiBinsMax - 1; } int isotmin = it - 1; - if (isotmin < 0) - { - isotmin = 0; - } + isotmin = std::max(isotmin, 0); int isotmax = it + 1; if (!(isotmax < NTBinsMax)) { @@ -490,6 +496,7 @@ namespace int tbinlo = 666666; int clus_size = ihit_list.size(); int max_adc = 0; + if (clus_size <= my_data.min_clus_size) { return; @@ -519,7 +526,7 @@ namespace training_hits->v_adc.fill(0); } - // std::cout << "process list" << std::endl; + // std::cout << "process list" << std::endl; std::vector hitkeyvec; // keep track of the hit locations in a given cluster @@ -537,30 +544,11 @@ namespace continue; } - if (adc > max_adc) - { - max_adc = adc; - } - - if (iphi > phibinhi) - { - phibinhi = iphi; - } - - if (iphi < phibinlo) - { - phibinlo = iphi; - } - - if (it > tbinhi) - { - tbinhi = it; - } - - if (it < tbinlo) - { - tbinlo = it; - } + max_adc = std::max(max_adc, static_cast(std::round(adc))); // preserves rounding (0.5 -> 1) + phibinhi = std::max(iphi, phibinhi); + phibinlo = std::min(iphi, phibinlo); + tbinhi = std::max(it, tbinhi); + tbinlo = std::min(it, tbinlo); // if(it==it_center){ yg_sum += adc; } // update phi sums @@ -617,12 +605,64 @@ namespace return; // skip obvious noise "clusters" } + TrkrDefs::hitsetkey tpcHitSetKey = TpcDefs::genHitSetKey(my_data.layer, my_data.sector, my_data.side); + + // pads just outside the cluster in phi + const int left_pad = phibinlo - 1; + const int right_pad = phibinhi + 1; + + // --- Dead channels --- + if (my_data.maskDead) + { + auto it = my_data.deadMap->find(tpcHitSetKey); + if (it != my_data.deadMap->end()) + { + const auto &deadset = it->second; + + if (left_pad >= 0 && + left_pad >= my_data.phioffset && + deadset.contains(TpcDefs::genHitKey(left_pad, 0))) + { + nedge++; + } + + if (right_pad < (my_data.phibins + my_data.phioffset) && + deadset.contains(TpcDefs::genHitKey(right_pad, 0))) + { + nedge++; + } + } + } + + // --- Hot channels --- + if (my_data.maskHot) + { + auto it = my_data.hotMap->find(tpcHitSetKey); + if (it != my_data.hotMap->end()) + { + const auto &hotset = it->second; + + if (left_pad >= 0 && + left_pad >= my_data.phioffset && + hotset.contains(TpcDefs::genHitKey(left_pad, 0))) + { + nedge++; + } + + if (right_pad < (my_data.phibins + my_data.phioffset) && + hotset.contains(TpcDefs::genHitKey(right_pad, 0))) + { + nedge++; + } + } + } + // This is the global position double clusiphi = iphi_sum / adc_sum; double clusphi = my_data.layergeom->get_phi(clusiphi, my_data.side); - float clusx = radius * cos(clusphi); - float clusy = radius * sin(clusphi); + double clusx = radius * cos(clusphi); + double clusy = radius * sin(clusphi); double clust = t_sum / adc_sum; // needed for surface identification double zdriftlength = clust * my_data.tGeometry->get_drift_velocity(); @@ -637,7 +677,7 @@ namespace const double t_cov = t2_sum / adc_sum - square(clust); // Get the surface key to find the surface from the - TrkrDefs::hitsetkey tpcHitSetKey = TpcDefs::genHitSetKey(my_data.layer, my_data.sector, my_data.side); + // TrkrDefs::hitsetkey tpcHitSetKey = TpcDefs::genHitSetKey(my_data.layer, my_data.sector, my_data.side); Acts::Vector3 global(clusx, clusy, clusz); TrkrDefs::subsurfkey subsurfkey = 0; @@ -686,7 +726,7 @@ namespace // std::cout << "clus num" << my_data.cluster_vector.size() << " X " << local(0) << " Y " << clust << std::endl; if (sqrt(phi_err_square) > my_data.min_err_squared) { - auto clus = new TrkrClusterv5; + auto *clus = new TrkrClusterv5; // auto clus = std::make_unique(); clus_base = clus; clus->setAdc(adc_sum); @@ -710,22 +750,22 @@ namespace { // Create a vector of inputs std::vector inputs; - inputs.emplace_back(torch::stack({torch::from_blob(std::vector(training_hits->v_adc.begin(), training_hits->v_adc.end()).data(), {1, 2 * nd + 1, 2 * nd + 1}, torch::kFloat32), + inputs.emplace_back(torch::stack({torch::from_blob(std::vector(training_hits->v_adc.begin(), training_hits->v_adc.end()).data(), {1, 2 * nd + 1, 2 * nd + 1}, torch::kFloat32), torch::full({1, 2 * nd + 1, 2 * nd + 1}, std::clamp((training_hits->layer - 7) / 16, 0, 2), torch::kFloat32), torch::full({1, 2 * nd + 1, 2 * nd + 1}, training_hits->z / radius, torch::kFloat32)}, 1)); // Execute the model and turn its output into a tensor at::Tensor ten_pos = module_pos.forward(inputs).toTensor(); - float nn_phi = training_hits->phi + std::clamp(ten_pos[0][0][0].item(), -(float) nd, (float) nd) * training_hits->phistep; - float nn_z = training_hits->z + std::clamp(ten_pos[0][1][0].item(), -(float) nd, (float) nd) * training_hits->zstep; - float nn_x = radius * std::cos(nn_phi); - float nn_y = radius * std::sin(nn_phi); + double nn_phi = training_hits->phi + std::clamp(ten_pos[0][0][0].item(), -(double) nd, (double) nd) * training_hits->phistep; + double nn_z = training_hits->z + std::clamp(ten_pos[0][1][0].item(), -(double) nd, (double) nd) * training_hits->zstep; + double nn_x = radius * std::cos(nn_phi); + double nn_y = radius * std::sin(nn_phi); Acts::Vector3 nn_global(nn_x, nn_y, nn_z); nn_global *= Acts::UnitConstants::cm; Acts::Vector3 nn_local = surface->transform(my_data.tGeometry->geometry().geoContext).inverse() * nn_global; nn_local /= Acts::UnitConstants::cm; - float nn_t = my_data.m_tdriftmax - std::fabs(nn_z) / my_data.tGeometry->get_drift_velocity(); + double nn_t = my_data.m_tdriftmax - std::fabs(nn_z) / my_data.tGeometry->get_drift_velocity(); clus_base->setLocalX(nn_local(0)); clus_base->setLocalY(nn_t); } @@ -738,19 +778,19 @@ namespace if (my_data.fillClusHitsVerbose && b_made_cluster) { // push the data back to - my_data.phivec_ClusHitsVerbose.push_back(std::vector>{}); - my_data.zvec_ClusHitsVerbose.push_back(std::vector>{}); + my_data.phivec_ClusHitsVerbose.emplace_back(); + my_data.zvec_ClusHitsVerbose.emplace_back(); auto &vphi = my_data.phivec_ClusHitsVerbose.back(); auto &vz = my_data.zvec_ClusHitsVerbose.back(); for (auto &entry : m_phi) { - vphi.push_back({entry.first, entry.second}); + vphi.emplace_back(entry.first, entry.second); } for (auto &entry : m_z) { - vz.push_back({entry.first, entry.second}); + vz.emplace_back(entry.first, entry.second); } } @@ -809,7 +849,38 @@ namespace tbinmax -= etacut; } } - // std::cout << PHWHERE << " maxz " << maxz << " tbinmin " << tbinmin << " tbinmax " << tbinmax << std::endl; + // std::cout << PHWHERE << " maxz " << maxz << " tbinmin " << tbinmin << " tbinmax " << tbinmax << std::endl; + + TrkrDefs::hitsetkey tpcHitSetKey = + TpcDefs::genHitSetKey(my_data->layer, my_data->sector, my_data->side); + + // Helper function to check if a pad is masked + auto is_pad_masked = [&](int abs_pad) -> bool + { + TrkrDefs::hitkey key = TpcDefs::genHitKey(abs_pad, 0); + + if (my_data->maskDead) + { + auto it = my_data->deadMap->find(tpcHitSetKey); + if (it != my_data->deadMap->end() && + it->second.contains(key)) + { + return true; + } + } + + if (my_data->maskHot) + { + auto it = my_data->hotMap->find(tpcHitSetKey); + if (it != my_data->hotMap->end() && + it->second.contains(key)) + { + return true; + } + } + + return false; + }; if (my_data->hitset != nullptr) { @@ -846,21 +917,16 @@ namespace { continue; } - float_t fadc = (hitr->second->getAdc()) - pedestal; // proper int rounding +0.5 + if (is_pad_masked(phibin + phioffset)) + { + continue; + } + double_t fadc = (hitr->second->getAdc()) - pedestal; // proper int rounding +0.5 unsigned short adc = 0; if (fadc > 0) { adc = (unsigned short) fadc; } - if (phibin >= phibins) - { - continue; - } - if (tbin >= tbins) - { - continue; // tbin is unsigned int, <0 cannot happen - } - if (adc > 0) { if (adc > (my_data->seed_threshold)) @@ -875,7 +941,7 @@ namespace } if (adc > my_data->edge_threshold) { - adcval[phibin][tbin] = (unsigned short) adc; + adcval[phibin][tbin] = adc; } } } @@ -897,7 +963,12 @@ namespace continue; } - int pindex = 0; + if (is_pad_masked(nphi + phioffset)) + { + continue; + } + + int pindex = 0; for (unsigned int nt = 0; nt < hitset->size(nphi); nt++) { unsigned short val = (*(hitset->getHits(nphi)))[nt]; @@ -967,7 +1038,7 @@ namespace } */ // std::cout << "done filling " << std::endl; - while (all_hit_map.size() > 0) + while (!all_hit_map.empty()) { // std::cout << "all hit map size: " << all_hit_map.size() << std::endl; auto iter = all_hit_map.rbegin(); @@ -1013,22 +1084,10 @@ namespace { continue; } - if (wiphi > wphibinhi) - { - wphibinhi = wiphi; - } - if (wiphi < wphibinlo) - { - wphibinlo = wiphi; - } - if (wit > wtbinhi) - { - wtbinhi = wit; - } - if (wit < wtbinlo) - { - wtbinlo = wit; - } + wphibinhi = std::max(wiphi, wphibinhi); + wphibinlo = std::min(wiphi, wphibinlo); + wtbinhi = std::max(wit, wtbinhi); + wtbinlo = std::min(wit, wtbinlo); } char wtsize = wtbinhi - wtbinlo + 1; char wphisize = wphibinhi - wphibinlo + 1; @@ -1075,9 +1134,10 @@ namespace */ // pthread_exit(nullptr); } + void *ProcessSector(void *threadarg) { - auto my_data = static_cast(threadarg); + auto *my_data = static_cast(threadarg); ProcessSectorData(my_data); pthread_exit(nullptr); } @@ -1133,7 +1193,7 @@ int TpcClusterizer::InitRun(PHCompositeNode *topNode) } // Create the Cluster node if required - auto trkrclusters = findNode::getClass(dstNode, "TRKR_CLUSTER"); + auto *trkrclusters = findNode::getClass(dstNode, "TRKR_CLUSTER"); if (!trkrclusters) { PHNodeIterator dstiter(dstNode); @@ -1151,7 +1211,7 @@ int TpcClusterizer::InitRun(PHCompositeNode *topNode) DetNode->addNode(TrkrClusterContainerNode); } - auto clusterhitassoc = findNode::getClass(topNode, "TRKR_CLUSTERHITASSOC"); + auto *clusterhitassoc = findNode::getClass(topNode, "TRKR_CLUSTERHITASSOC"); if (!clusterhitassoc) { PHNodeIterator dstiter(dstNode); @@ -1168,7 +1228,7 @@ int TpcClusterizer::InitRun(PHCompositeNode *topNode) DetNode->addNode(newNode); } - auto training_container = findNode::getClass(dstNode, "TRAINING_HITSET"); + auto *training_container = findNode::getClass(dstNode, "TRAINING_HITSET"); if (!training_container) { PHNodeIterator dstiter(dstNode); @@ -1217,18 +1277,18 @@ int TpcClusterizer::InitRun(PHCompositeNode *topNode) if (!mClusHitsVerbose) { PHNodeIterator dstiter(dstNode); - auto DetNode = dynamic_cast(dstiter.findFirst("PHCompositeNode", "TRKR")); + auto *DetNode = dynamic_cast(dstiter.findFirst("PHCompositeNode", "TRKR")); if (!DetNode) { DetNode = new PHCompositeNode("TRKR"); dstNode->addNode(DetNode); } mClusHitsVerbose = new ClusHitsVerbosev1(); - auto newNode = new PHIODataNode(mClusHitsVerbose, "Trkr_SvtxClusHitsVerbose", "PHObject"); + auto *newNode = new PHIODataNode(mClusHitsVerbose, "Trkr_SvtxClusHitsVerbose", "PHObject"); DetNode->addNode(newNode); } } - auto geom = + auto *geom = findNode::getClass(topNode, "TPCGEOMCONTAINER"); if (!geom) { @@ -1239,15 +1299,26 @@ int TpcClusterizer::InitRun(PHCompositeNode *topNode) AdcClockPeriod = geom->GetFirstLayerCellGeom()->get_zstep(); std::cout << "FirstLayerCellGeomv1 streamer: " << std::endl; - auto *g1 = (PHG4TpcGeomv1*) geom->GetFirstLayerCellGeom(); // cast because << not in the base class + auto *g1 = static_cast (geom->GetFirstLayerCellGeom()); // cast because << not in the base class std::cout << *g1 << std::endl; std::cout << "LayerCellGeomv1 streamer for layer 24: " << std::endl; - auto *g2 = (PHG4TpcGeomv1*) geom->GetLayerCellGeom(24); // cast because << not in the base class + auto *g2 = static_cast (geom->GetLayerCellGeom(24)); // cast because << not in the base class std::cout << *g2 << std::endl; std::cout << "LayerCellGeomv1 streamer for layer 40: " << std::endl; - auto *g3 = (PHG4TpcGeomv1*) geom->GetLayerCellGeom(40); // cast because << not in the base class + auto *g3 = static_cast (geom->GetLayerCellGeom(40)); // cast because << not in the base class std::cout << *g3 << std::endl; + if (m_maskDeadChannels) + { + m_deadChannelMap.clear(); + makeChannelMask(m_deadChannelMap, m_deadChannelMapName, "TotalDeadChannels"); + } + if (m_maskHotChannels) + { + m_hotChannelMap.clear(); + makeChannelMask(m_hotChannelMap, m_hotChannelMapName, "TotalHotChannels"); + } + return Fun4AllReturnCodes::EVENT_OK; } @@ -1434,6 +1505,13 @@ int TpcClusterizer::process_event(PHCompositeNode *topNode) thread_pair.data.min_err_squared = min_err_squared; thread_pair.data.min_clus_size = min_clus_size; thread_pair.data.min_adc_sum = min_adc_sum; + + // --- pass dead/hot map info --- + thread_pair.data.deadMap = &m_deadChannelMap; + thread_pair.data.hotMap = &m_hotChannelMap; + thread_pair.data.maskDead = m_maskDeadChannels; + thread_pair.data.maskHot = m_maskHotChannels; + unsigned short NPhiBins = (unsigned short) layergeom->get_phibins(); unsigned short NPhiBinsSector = NPhiBins / 12; unsigned short NTBins = 0; @@ -1489,18 +1567,18 @@ int TpcClusterizer::process_event(PHCompositeNode *topNode) const auto ckey = TrkrDefs::genClusKey(hitsetkey, index); // get cluster - auto cluster = data.cluster_vector[index]; + auto *cluster = data.cluster_vector[index]; // insert in map m_clusterlist->addClusterSpecifyKey(ckey, cluster); if (mClusHitsVerbose) { - for (auto &hit : data.phivec_ClusHitsVerbose[index]) + for (const auto &hit : data.phivec_ClusHitsVerbose[index]) { mClusHitsVerbose->addPhiHit(hit.first, hit.second); } - for (auto &hit : data.zvec_ClusHitsVerbose[index]) + for (const auto &hit : data.zvec_ClusHitsVerbose[index]) { mClusHitsVerbose->addZHit(hit.first, hit.second); } @@ -1554,6 +1632,12 @@ int TpcClusterizer::process_event(PHCompositeNode *topNode) thread_pair.data.maxHalfSizePhi = MaxClusterHalfSizePhi; thread_pair.data.verbosity = Verbosity(); + // --- pass dead/hot map info --- + thread_pair.data.deadMap = &m_deadChannelMap; + thread_pair.data.hotMap = &m_hotChannelMap; + thread_pair.data.maskDead = m_maskDeadChannels; + thread_pair.data.maskHot = m_maskHotChannels; + unsigned short NPhiBins = (unsigned short) layergeom->get_phibins(); unsigned short NPhiBinsSector = NPhiBins / 12; unsigned short NTBins = (unsigned short) layergeom->get_zbins(); @@ -1573,13 +1657,13 @@ int TpcClusterizer::process_event(PHCompositeNode *topNode) /* PHG4TpcGeom *testlayergeom = geom_container->GetLayerCellGeom(32); - for( float iphi = 1408; iphi < 1408+ 128;iphi+=0.1){ + for( double iphi = 1408; iphi < 1408+ 128;iphi+=0.1){ double clusiphi = iphi; double clusphi = testlayergeom->get_phi(clusiphi); double radius = layergeom->get_radius(); - float clusx = radius * cos(clusphi); - float clusy = radius * sin(clusphi); - float clusz = -37.524; + double clusx = radius * cos(clusphi); + double clusy = radius * sin(clusphi); + double clusz = -37.524; TrkrDefs::hitsetkey tpcHitSetKey = TpcDefs::genHitSetKey( 32,11, 0 ); Acts::Vector3 global(clusx, clusy, clusz); @@ -1624,7 +1708,7 @@ int TpcClusterizer::process_event(PHCompositeNode *topNode) const auto ckey = TrkrDefs::genClusKey(hitsetkey, index); // get cluster - auto cluster = data.cluster_vector[index]; + auto *cluster = data.cluster_vector[index]; // insert in map m_clusterlist->addClusterSpecifyKey(ckey, cluster); @@ -1668,7 +1752,7 @@ int TpcClusterizer::process_event(PHCompositeNode *topNode) const auto ckey = TrkrDefs::genClusKey(hitsetkey, index); // get cluster - auto cluster = data.cluster_vector[index]; + auto *cluster = data.cluster_vector[index]; // insert in map // std::cout << "X: " << cluster->getLocalX() << "Y: " << cluster->getLocalY() << std::endl; @@ -1676,13 +1760,13 @@ int TpcClusterizer::process_event(PHCompositeNode *topNode) if (mClusHitsVerbose) { - for (auto &hit : data.phivec_ClusHitsVerbose[index]) + for (const auto &hit : data.phivec_ClusHitsVerbose[index]) { - mClusHitsVerbose->addPhiHit(hit.first, (float) hit.second); + mClusHitsVerbose->addPhiHit(hit.first, (double) hit.second); } - for (auto &hit : data.zvec_ClusHitsVerbose[index]) + for (const auto &hit : data.zvec_ClusHitsVerbose[index]) { - mClusHitsVerbose->addZHit(hit.first, (float) hit.second); + mClusHitsVerbose->addZHit(hit.first, (double) hit.second); } mClusHitsVerbose->push_hits(ckey); } @@ -1698,7 +1782,7 @@ int TpcClusterizer::process_event(PHCompositeNode *topNode) m_clusterhitassoc->addAssoc(ckey, hkey); } - for (auto v_hit : thread_pair.data.v_hits) + for (auto *v_hit : thread_pair.data.v_hits) { if (_store_hits) { @@ -1739,3 +1823,88 @@ int TpcClusterizer::End(PHCompositeNode * /*topNode*/) { return Fun4AllReturnCodes::EVENT_OK; } + +void TpcClusterizer::makeChannelMask(hitMaskTpcSet &aMask, const std::string &dbName, const std::string &totalChannelsToMask) +{ + std::unique_ptr cdbttree; + if (m_maskFromFile) + { + cdbttree = std::make_unique(dbName); + } + else // mask using CDB TTree, default + { + std::string database = CDBInterface::instance()->getUrl(dbName); + + if (database.empty()) + { + std::cout << PHWHERE << "ERROR: CDB URL not found for " << dbName + << ". Masking disabled for this map." << std::endl; + return; + } + + cdbttree = std::make_unique(database); + } + + std::cout << "Masking TPC Channel Map: " << dbName << std::endl; + + int NChan = -1; + NChan = cdbttree->GetSingleIntValue(totalChannelsToMask); + + if (NChan < 0) + { + std::cout << PHWHERE << "ERROR: Invalid or missing " << totalChannelsToMask + << " for " << dbName << ". Masking disabled for this map." << std::endl; + return; + } + + for (int i = 0; i < NChan; i++) + { + int Layer = cdbttree->GetIntValue(i, "layer"); + int Sector = cdbttree->GetIntValue(i, "sector"); + int Side = cdbttree->GetIntValue(i, "side"); + int Pad = cdbttree->GetIntValue(i, "pad"); + + if (Sector < 0 || Sector >= 12) + { + if (Verbosity() > VERBOSITY_A_LOT) + { + std::cout << PHWHERE << "WARNING: sector index " << Sector + << " out of range [0,11] in " << dbName + << ", skipping channel " << i << std::endl; + } + continue; + } + + if (Layer < 7 || Layer > 54) + { + if (Verbosity() > VERBOSITY_A_LOT) + { + std::cout << PHWHERE << "WARNING: layer " << Layer + << " out of TPC range [7,54] in " << dbName + << ", skipping channel " << i << std::endl; + } + continue; + } + + if (Side < 0 || Side > 1) + { + if (Verbosity() > VERBOSITY_A_LOT) + { + std::cout << PHWHERE << "WARNING: side " << Side + << " out of range [0,1] in " << dbName + << ", skipping channel " << i << std::endl; + } + continue; + } + + if (Verbosity() > VERBOSITY_A_LOT) + { + std::cout << dbName << ": Will mask layer: " << Layer << ", sector: " << Sector << ", side: " << Side << ", Pad: " << Pad << std::endl; + } + + TrkrDefs::hitsetkey DeadChannelHitKey = TpcDefs::genHitSetKey(Layer, Sector, Side); + TrkrDefs::hitkey DeadHitKey = TpcDefs::genHitKey((unsigned int) Pad, 0); + aMask[DeadChannelHitKey].insert(DeadHitKey); + } + +} diff --git a/offline/packages/tpc/TpcClusterizer.h b/offline/packages/tpc/TpcClusterizer.h index e7dd61f0bc..801207654e 100644 --- a/offline/packages/tpc/TpcClusterizer.h +++ b/offline/packages/tpc/TpcClusterizer.h @@ -4,10 +4,13 @@ #include #include #include +#include #include #include -#include +#include + +typedef std::map> hitMaskTpcSet; class ClusHitsVerbosev1; class PHCompositeNode; @@ -41,12 +44,12 @@ class TpcClusterizer : public SubsysReco void set_do_sequential(bool do_seq) { do_sequential = do_seq; } void set_do_split(bool split) { do_split = split; } void set_fixed_window(int fixed) { do_fixed_window = fixed; } - void set_pedestal(float val) { pedestal = val; } - void set_seed_threshold(float val) { seed_threshold = val; } - void set_edge_threshold(float val) { edge_threshold = val; } - void set_min_err_squared(float val) { min_err_squared = val; } - void set_min_clus_size(float val) { min_clus_size = val; } - void set_min_adc_sum(float val) { min_adc_sum = val; } + void set_pedestal(double val) { pedestal = val; } + void set_seed_threshold(double val) { seed_threshold = val; } + void set_edge_threshold(double val) { edge_threshold = val; } + void set_min_err_squared(double val) { min_err_squared = val; } + void set_min_clus_size(double val) { min_clus_size = val; } + void set_min_adc_sum(double val) { min_adc_sum = val; } void set_remove_singles(bool do_sing) { do_singles = do_sing; } void set_read_raw(bool read_raw) { do_read_raw = read_raw; } void set_max_cluster_half_size_phi(unsigned short size) { MaxClusterHalfSizePhi = size; } @@ -69,13 +72,31 @@ class TpcClusterizer : public SubsysReco set_max_cluster_half_size_z(20); set_fixed_window(3); }; - + ClusHitsVerbosev1 *mClusHitsVerbose{nullptr}; - + + void SetMaskChannelsFromFile() + { + m_maskFromFile = true; + } + + void SetDeadChannelMapName(const std::string& dcmap) + { + m_maskDeadChannels = true; + m_deadChannelMapName = dcmap; + } + void SetHotChannelMapName(const std::string& hmap) + { + m_maskHotChannels = true; + m_hotChannelMapName = hmap; + } + private: bool is_in_sector_boundary(int phibin, int sector, PHG4TpcGeom *layergeom) const; bool record_ClusHitsVerbose{false}; + void makeChannelMask(hitMaskTpcSet& aMask, const std::string& dbName, const std::string& totalChannelsToMask); + TrkrHitSetContainer *m_hits = nullptr; RawHitSetContainer *m_rawhits = nullptr; TrkrClusterContainer *m_clusterlist = nullptr; @@ -105,8 +126,17 @@ class TpcClusterizer : public SubsysReco double m_tdriftmax = 0; double AdcClockPeriod = 53.0; // ns double NZBinsSide = 249; - + TrainingHitsContainer *m_training; + + hitMaskTpcSet m_deadChannelMap; + hitMaskTpcSet m_hotChannelMap; + + bool m_maskDeadChannels {false}; + bool m_maskHotChannels {false}; + bool m_maskFromFile {false}; + std::string m_deadChannelMapName; + std::string m_hotChannelMapName; }; #endif diff --git a/offline/packages/tpc/TpcCombinedRawDataUnpacker.cc b/offline/packages/tpc/TpcCombinedRawDataUnpacker.cc index c194567d58..f5e436c6d7 100644 --- a/offline/packages/tpc/TpcCombinedRawDataUnpacker.cc +++ b/offline/packages/tpc/TpcCombinedRawDataUnpacker.cc @@ -57,7 +57,7 @@ void TpcCombinedRawDataUnpacker::ReadZeroSuppressedData() { m_do_zs_emulation = true; m_do_baseline_corr = false; - auto cdb = CDBInterface::instance(); + auto *cdb = CDBInterface::instance(); std::string dir = cdb->getUrl("TPC_ZS_THRESHOLDS"); auto cdbtree = std::make_unique(dir); @@ -75,7 +75,7 @@ void TpcCombinedRawDataUnpacker::ReadZeroSuppressedData() { name.str(""); name << "R"<GetSingleFloatValue(name.str().c_str()); + m_zs_threshold[i] = cdbtree->GetSingleFloatValue(name.str()); if(Verbosity() > 1) { std::cout << "Loading ADU threshold of " << m_zs_threshold[i] << " for region " << i << std::endl; @@ -324,8 +324,8 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) hit_set_key = TpcDefs::genHitSetKey(layer, (mc_sectors[sector % 12]), side); hit_set_container_itr = trkr_hit_set_container->findOrAddHitSet(hit_set_key); - float hpedestal = 0; - float hpedwidth = 0; + double hpedestal = 0; + double hpedwidth = 0; if (Verbosity() > 2) { @@ -372,7 +372,7 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) auto fee_entries_it = feeentries_map.find(fee_key); std::vector& fee_entries_vec = (*fee_entries_it).second; - float threshold_cut = m_zs_threshold[region]; + double threshold_cut = m_zs_threshold[region]; int nhitschan = 0; @@ -391,7 +391,7 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) { if (adc > 0) { - if ((float(adc) - hpedestal) > threshold_cut) + if ((double(adc) - hpedestal) > threshold_cut) { nhitschan++; } @@ -424,7 +424,7 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) { if (adc > 0) { - if ((float(adc) - hpedestal) > threshold_cut) + if ((double(adc) - hpedestal) > threshold_cut) { feehist->Fill(t, adc - hpedestal); if (t < (int) fee_entries_vec.size()) @@ -435,7 +435,7 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) } } - if ((float(adc) - hpedestal) > threshold_cut) + if ((double(adc) - hpedestal) > threshold_cut) { hit_key = TpcDefs::genHitKey(phibin, (unsigned int) t); // find existing hit, or create new one @@ -443,7 +443,7 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) if (!hit) { hit = new TrkrHitv2(); - hit->setAdc(float(adc) - hpedestal); + hit->setAdc(double(adc) - hpedestal); hit_set_container_itr->second->addHitSpecificKey(hit_key, hit); } @@ -462,10 +462,10 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) fXh[nh++] = channel; // channel; fXh[nh++] = sampadd; // sampadd; fXh[nh++] = sampch; // sampch; - fXh[nh++] = (float) phibin; - fXh[nh++] = (float) t; + fXh[nh++] = (double) phibin; + fXh[nh++] = (double) t; fXh[nh++] = layer; - fXh[nh++] = (float(adc) - hpedestal); + fXh[nh++] = (double(adc) - hpedestal); fXh[nh++] = hpedestal; fXh[nh++] = hpedwidth; m_ntup_hits->Fill(fXh); @@ -499,18 +499,18 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) } std::vector::iterator fee_entries_vec_it = (*fee_entries_it).second.begin(); - std::vector pedvec(hist2d->GetNbinsX(), 0); + std::vector pedvec(hist2d->GetNbinsX(), 0); feebaseline_map.insert(std::make_pair(hiter.first, pedvec)); - std::map>::iterator fee_blm_it = feebaseline_map.find(hiter.first); + std::map>::iterator fee_blm_it = feebaseline_map.find(hiter.first); (*fee_blm_it).second.resize(hist2d->GetNbinsX(), 0); for (int binx = 1; binx < hist2d->GetNbinsX(); binx++) { double timebin = (hist2d->GetXaxis())->GetBinCenter(binx); std::string histname1d = "h" + std::to_string(hiter.first) + "_" + std::to_string((int) timebin); nhisttotal++; - float local_ped = 0; - float local_width = 0; - float entries = fee_entries_vec_it[timebin]; + double local_ped = 0; + double local_width = 0; + double entries = fee_entries_vec_it[timebin]; if (fee_entries_vec_it[timebin] > 100) { nhistfilled++; @@ -532,8 +532,8 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) for (int isum = -3; isum <= 3; isum++) { - float val = hist1d->GetBinContent(maxbin + isum); - float center = hist1d->GetBinCenter(maxbin + isum); + double val = hist1d->GetBinContent(maxbin + isum); + double center = hist1d->GetBinCenter(maxbin + isum); hibin_sum += center * val; hibin2_sum += center * center * val; hadc_sum += val; @@ -601,7 +601,7 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) unsigned int pad_key = create_pad_key(side, layer, phibin); - float fee = 0; + double fee = 0; std::map::iterator chan_it = chan_map.find(pad_key); if (chan_it != chan_map.end()) { @@ -612,10 +612,10 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) } int rx = get_rx(layer); - float corr = 0; + double corr = 0; unsigned int fee_key = create_fee_key(side, sector, rx, fee); - std::map>::iterator fee_blm_it = feebaseline_map.find(fee_key); + std::map>::iterator fee_blm_it = feebaseline_map.find(fee_key); if (fee_blm_it != feebaseline_map.end()) { if (tbin < (int) (*fee_blm_it).second.size()) @@ -623,8 +623,8 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) corr = (*fee_blm_it).second[tbin]; } hitr->second->setAdc(0); - float nuadc = (float(adc) - corr); - nuadc = std::max(nuadc, 0); + double nuadc = (double(adc) - corr); + nuadc = std::max(nuadc, 0); hitr->second->setAdc(nuadc); if (m_writeTree) @@ -642,10 +642,10 @@ int TpcCombinedRawDataUnpacker::process_event(PHCompositeNode* topNode) fXh[nh++] = 0; // channel; fXh[nh++] = 0; // sampadd; fXh[nh++] = 0; // sampch; - fXh[nh++] = (float) phibin; - fXh[nh++] = (float) tbin; + fXh[nh++] = (double) phibin; + fXh[nh++] = (double) tbin; fXh[nh++] = layer; - fXh[nh++] = float(adc); + fXh[nh++] = double(adc); fXh[nh++] = 0; // hpedestal2; fXh[nh++] = 0; // hpedwidth2; fXh[nh++] = corr; diff --git a/offline/packages/tpc/TpcCombinedRawDataUnpacker.h b/offline/packages/tpc/TpcCombinedRawDataUnpacker.h index 8c8bfd353b..0dcb0e555e 100644 --- a/offline/packages/tpc/TpcCombinedRawDataUnpacker.h +++ b/offline/packages/tpc/TpcCombinedRawDataUnpacker.h @@ -88,8 +88,8 @@ class TpcCombinedRawDataUnpacker : public SubsysReco struct chan_info { unsigned int fee = std::numeric_limits::max(); - float ped = -1; - float width = -1; + double ped = -1; + double width = -1; int entries = 0; }; TNtuple *m_ntup{nullptr}; @@ -113,7 +113,7 @@ class TpcCombinedRawDataUnpacker : public SubsysReco bool m_doChanHitsCut{false}; int m_ChanHitsCut{9999}; - float m_ped_sig_cut{4.0}; + double m_ped_sig_cut{4.0}; bool m_writeTree{false}; bool m_do_baseline_corr{false}; @@ -125,7 +125,7 @@ class TpcCombinedRawDataUnpacker : public SubsysReco std::map chan_map; // stays in place std::map feeadc_map; // histos reset after each event std::map> feeentries_map; // cleared after each event - std::map> feebaseline_map; // cleared after each event + std::map> feebaseline_map; // cleared after each event }; #endif // TPC_COMBINEDRAWDATAUNPACKER_H diff --git a/offline/packages/tpc/TpcCombinedRawDataUnpackerDebug.cc b/offline/packages/tpc/TpcCombinedRawDataUnpackerDebug.cc index 0bb412197f..2e2cc693e6 100644 --- a/offline/packages/tpc/TpcCombinedRawDataUnpackerDebug.cc +++ b/offline/packages/tpc/TpcCombinedRawDataUnpackerDebug.cc @@ -34,6 +34,7 @@ #include #include +#include #include #include // for exit #include // for exit @@ -234,14 +235,8 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) TpcRawHit* tpchit = tpccont->get_hit(i); uint64_t gtm_bco = tpchit->get_gtm_bco(); - if (gtm_bco < bco_min) - { - bco_min = gtm_bco; - } - if (gtm_bco > bco_max) - { - bco_max = gtm_bco; - } + bco_min = std::min(gtm_bco, bco_min); + bco_max = std::max(gtm_bco, bco_max); int fee = tpchit->get_fee(); int channel = tpchit->get_channel(); @@ -303,8 +298,8 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) hit_set_key = TpcDefs::genHitSetKey(layer, (mc_sectors[sector % 12]), side); hit_set_container_itr = trkr_hit_set_container->findOrAddHitSet(hit_set_key); - float hpedestal = 0; - float hpedwidth = 0; + double hpedestal = 0; + double hpedwidth = 0; pedhist.Reset(); if (!m_do_zerosup) @@ -328,7 +323,7 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) if (!hit) { hit = new TrkrHitv2(); - hit->setAdc(float(adc)); + hit->setAdc(double(adc)); hit_set_container_itr->second->addHitSpecificKey(hit_key, hit); } @@ -362,7 +357,7 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) int hmaxbin = 0; for (int nbin = 1; nbin <= pedhist.GetNbinsX(); nbin++) { - float val = pedhist.GetBinContent(nbin); + double val = pedhist.GetBinContent(nbin); if (val > hmax) { hmaxbin = nbin; @@ -386,8 +381,8 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) for (int isum = -3; isum <= 3; isum++) { - float val = pedhist.GetBinContent(hmaxbin + isum); - float center = pedhist.GetBinCenter(hmaxbin + isum); + double val = pedhist.GetBinContent(hmaxbin + isum); + double center = pedhist.GetBinCenter(hmaxbin + isum); ibin_sum += center * val; ibin2_sum += center * center * val; adc_sum += val; @@ -467,12 +462,12 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) feehist->Fill(t, adc - hpedestal + pedestal_offset); } } - float threshold_cut = (hpedwidth * m_ped_sig_cut); + double threshold_cut = (hpedwidth * m_ped_sig_cut); if (m_do_zs_emulation) { threshold_cut = m_zs_threshold; } - if ((float(adc) - hpedestal) > threshold_cut) + if ((double(adc) - hpedestal) > threshold_cut) { hit_key = TpcDefs::genHitKey(phibin, (unsigned int) t); // find existing hit, or create new one @@ -482,11 +477,11 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) hit = new TrkrHitv2(); if (m_do_baseline_corr) { - hit->setAdc(float(adc) - hpedestal + pedestal_offset); + hit->setAdc(double(adc) - hpedestal + pedestal_offset); } else { - hit->setAdc(float(adc) - hpedestal); + hit->setAdc(double(adc) - hpedestal); } hit_set_container_itr->second->addHitSpecificKey(hit_key, hit); } @@ -505,10 +500,10 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) fXh[nh++] = 0; // channel; fXh[nh++] = 0; // sampadd; fXh[nh++] = 0; // sampch; - fXh[nh++] = (float) phibin; - fXh[nh++] = (float) t; + fXh[nh++] = (double) phibin; + fXh[nh++] = (double) t; fXh[nh++] = layer; - fXh[nh++] = (float(adc) - hpedestal + pedestal_offset); + fXh[nh++] = (double(adc) - hpedestal + pedestal_offset); fXh[nh++] = hpedestal; fXh[nh++] = hpedwidth; @@ -532,17 +527,17 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) if (hiter.second != nullptr) { TH2I* hist2d = hiter.second; - std::vector pedvec(hist2d->GetNbinsX(), 0); + std::vector pedvec(hist2d->GetNbinsX(), 0); feebaseline_map.insert(std::make_pair(hiter.first, pedvec)); - std::map>::iterator fee_blm_it = feebaseline_map.find(hiter.first); + std::map>::iterator fee_blm_it = feebaseline_map.find(hiter.first); (*fee_blm_it).second.resize(hist2d->GetNbinsX(), 0); for (int binx = 1; binx < hist2d->GetNbinsX(); binx++) { - double timebin = ((TAxis*) hist2d->GetXaxis())->GetBinCenter(binx); + double timebin = ( hist2d->GetXaxis())->GetBinCenter(binx); std::string histname1d = "h" + std::to_string(hiter.first) + "_" + std::to_string((int) timebin); TH1D* hist1d = hist2d->ProjectionY(histname1d.c_str(), binx, binx); - float local_ped = 0; + double local_ped = 0; #ifdef DEBUG // if((*hiter).first == 210802&&timebin==383){ @@ -562,8 +557,8 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) for (int isum = -3; isum <= 3; isum++) { - float val = hist1d->GetBinContent(maxbin + isum); - float center = hist1d->GetBinCenter(maxbin + isum); + double val = hist1d->GetBinContent(maxbin + isum); + double center = hist1d->GetBinCenter(maxbin + isum); hibin_sum += center * val; // hibin2_sum += center * center * val; hadc_sum += val; @@ -629,9 +624,9 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) unsigned int pad_key = create_pad_key(side, layer, phibin); - float fee = 0; - float hpedestal2 = 0; - float hpedwidth2 = 0; + double fee = 0; + double hpedestal2 = 0; + double hpedwidth2 = 0; std::map::iterator chan_it = chan_map.find(pad_key); if (chan_it != chan_map.end()) { @@ -642,10 +637,10 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) } int rx = get_rx(layer); - float corr = 0; + double corr = 0; unsigned int fee_key = create_fee_key(side, sector, rx, fee); - std::map>::iterator fee_blm_it = feebaseline_map.find(fee_key); + std::map>::iterator fee_blm_it = feebaseline_map.find(fee_key); if (fee_blm_it != feebaseline_map.end()) { corr = (*fee_blm_it).second[tbin] - pedestal_offset; @@ -694,14 +689,11 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) } if (hpedwidth2 > -100 && hpedestal2 > -100) { - if ((float(adc) - pedestal_offset - corr) > (hpedwidth2 * m_ped_sig_cut)) + if ((double(adc) - pedestal_offset - corr) > (hpedwidth2 * m_ped_sig_cut)) { - float nuadc = (float(adc) - corr - pedestal_offset); - if (nuadc < 0) - { - nuadc = 0; - } - hitr->second->setAdc(float(nuadc)); + double nuadc = (double(adc) - corr - pedestal_offset); + nuadc = std::max(nuadc, 0); + hitr->second->setAdc(nuadc); #ifdef DEBUG // hitr->second->setAdc(10); if (tbin == 383 && layer >= 7 + 32 && fee == 21) @@ -717,7 +709,7 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) << " phibin " << phibin << " adc " << adc << " corr: " << corr - << " adcnu " << (float(adc) - corr - pedestal_offset) + << " adcnu " << (double(adc) - corr - pedestal_offset) << " adc in " << hitr->second->getAdc() << std::endl; } @@ -737,10 +729,10 @@ int TpcCombinedRawDataUnpackerDebug::process_event(PHCompositeNode* topNode) fXh[nh++] = 0; // channel; fXh[nh++] = 0; // sampadd; fXh[nh++] = 0; // sampch; - fXh[nh++] = (float) phibin; - fXh[nh++] = (float) tbin; + fXh[nh++] = (double) phibin; + fXh[nh++] = (double) tbin; fXh[nh++] = layer; - fXh[nh++] = float(adc); + fXh[nh++] = double(adc); fXh[nh++] = hpedestal2; fXh[nh++] = hpedwidth2; fXh[nh++] = corr; diff --git a/offline/packages/tpc/TpcCombinedRawDataUnpackerDebug.h b/offline/packages/tpc/TpcCombinedRawDataUnpackerDebug.h index baca369042..dd68e55863 100644 --- a/offline/packages/tpc/TpcCombinedRawDataUnpackerDebug.h +++ b/offline/packages/tpc/TpcCombinedRawDataUnpackerDebug.h @@ -28,7 +28,7 @@ class TpcCombinedRawDataUnpackerDebug : public SubsysReco int End(PHCompositeNode *topNode) override; void writeTree() { m_writeTree = true; } void do_zero_suppression(bool b) { m_do_zerosup = b; } - void set_pedestalSigmaCut(float b) { m_ped_sig_cut = b; } + void set_pedestalSigmaCut(double b) { m_ped_sig_cut = b; } void do_noise_rejection(bool b) { m_do_noise_rejection = b; } void doBaselineCorr(bool val) { m_do_baseline_corr = val; } void doZSEmulation(bool val) { m_do_zs_emulation = val; } @@ -49,8 +49,8 @@ class TpcCombinedRawDataUnpackerDebug : public SubsysReco struct chan_info { unsigned int fee = std::numeric_limits::max(); - float ped = -1; - float width = -1; + double ped = -1; + double width = -1; }; unsigned int get_rx(unsigned int layer) { @@ -104,7 +104,7 @@ class TpcCombinedRawDataUnpackerDebug : public SubsysReco int FEE_map[26]{4, 5, 0, 2, 1, 11, 9, 10, 8, 7, 6, 0, 1, 3, 7, 6, 5, 4, 3, 2, 0, 2, 1, 3, 5, 4}; int FEE_R[26]{2, 2, 1, 1, 1, 3, 3, 3, 3, 3, 3, 2, 2, 1, 2, 2, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3}; - float m_ped_sig_cut{4.0}; + double m_ped_sig_cut{4.0}; bool m_writeTree{false}; bool m_do_zerosup{true}; @@ -117,7 +117,7 @@ class TpcCombinedRawDataUnpackerDebug : public SubsysReco std::string outfile_name; std::map chan_map; // stays in place std::map feeadc_map; // histos reset after each event - std::map> feebaseline_map; // cleared after each event + std::map> feebaseline_map; // cleared after each event }; #endif // TPC_COMBINEDRAWDATAUNPACKER_H diff --git a/offline/packages/tpc/TpcDistortionCorrection.cc b/offline/packages/tpc/TpcDistortionCorrection.cc index b759331e77..71b9ea8b2f 100644 --- a/offline/packages/tpc/TpcDistortionCorrection.cc +++ b/offline/packages/tpc/TpcDistortionCorrection.cc @@ -15,7 +15,7 @@ namespace { template - inline constexpr T square(const T& x) + constexpr T square(const T x) { return x * x; } diff --git a/offline/packages/tpc/TpcDistortionCorrectionContainer.h b/offline/packages/tpc/TpcDistortionCorrectionContainer.h index c7ba14937b..2d65ca79dd 100644 --- a/offline/packages/tpc/TpcDistortionCorrectionContainer.h +++ b/offline/packages/tpc/TpcDistortionCorrectionContainer.h @@ -21,7 +21,7 @@ class TpcDistortionCorrectionContainer int m_dimensions = 3; bool m_use_scalefactor = false; - float m_scalefactor = 1.0; + double m_scalefactor = 1.0; //! set the phi histogram to be interpreted as radians rather than mm bool m_phi_hist_in_radians = true; diff --git a/offline/packages/tpc/TpcLoadDistortionCorrection.cc b/offline/packages/tpc/TpcLoadDistortionCorrection.cc index 0ce2ffa4e1..65bf156a7a 100644 --- a/offline/packages/tpc/TpcLoadDistortionCorrection.cc +++ b/offline/packages/tpc/TpcLoadDistortionCorrection.cc @@ -58,7 +58,7 @@ int TpcLoadDistortionCorrection::InitRun(PHCompositeNode* topNode) } /// Get the RUN node and check - auto runNode = dynamic_cast(iter.findFirst("PHCompositeNode", "RUN")); + auto *runNode = dynamic_cast(iter.findFirst("PHCompositeNode", "RUN")); if (!runNode) { std::cout << "TpcLoadDistortionCorrection::InitRun - RUN Node missing, quitting" << std::endl; @@ -74,17 +74,17 @@ int TpcLoadDistortionCorrection::InitRun(PHCompositeNode* topNode) } // get distortion correction object and create if not found - auto distortion_correction_object = findNode::getClass(topNode, m_node_name[i]); + auto *distortion_correction_object = findNode::getClass(topNode, m_node_name[i]); if (!distortion_correction_object) { std::cout << "TpcLoadDistortionCorrection::InitRun - creating TpcDistortionCorrectionContainer in node " << m_node_name[i] << std::endl; distortion_correction_object = new TpcDistortionCorrectionContainer; - auto node = new PHDataNode(distortion_correction_object, m_node_name[i]); + auto *node = new PHDataNode(distortion_correction_object, m_node_name[i]); runNode->addNode(node); } std::cout << "TpcLoadDistortionCorrection::InitRun - reading corrections from " << m_correction_filename[i] << std::endl; - auto distortion_tfile = TFile::Open(m_correction_filename[i].c_str()); + auto *distortion_tfile = TFile::Open(m_correction_filename[i].c_str()); if (!distortion_tfile) { std::cout << "TpcLoadDistortionCorrection::InitRun - cannot open " << m_correction_filename[i] << std::endl; diff --git a/offline/packages/tpc/TpcLoadDistortionCorrection.h b/offline/packages/tpc/TpcLoadDistortionCorrection.h index 6727957487..276d18fec4 100644 --- a/offline/packages/tpc/TpcLoadDistortionCorrection.h +++ b/offline/packages/tpc/TpcLoadDistortionCorrection.h @@ -48,7 +48,7 @@ class TpcLoadDistortionCorrection : public SubsysReco } //! set the scale factor to be applied to the correction - void set_scale_factor(DistortionType i, float value) + void set_scale_factor(DistortionType i, double value) { m_use_scalefactor[i] = true; m_scalefactor[i] = value; @@ -97,7 +97,7 @@ class TpcLoadDistortionCorrection : public SubsysReco std::array m_use_scalefactor = {}; //! scale factors - std::array m_scalefactor = {1.0,1.0,1.0,1.0}; + std::array m_scalefactor = {1.0,1.0,1.0,1.0}; //! set the phi histogram to be interpreted as radians rather than mm std::array m_phi_hist_in_radians = {true,true,true,true}; diff --git a/offline/packages/tpc/TpcRawDataTree.cc b/offline/packages/tpc/TpcRawDataTree.cc index 6199fb7425..1141b5de55 100644 --- a/offline/packages/tpc/TpcRawDataTree.cc +++ b/offline/packages/tpc/TpcRawDataTree.cc @@ -61,7 +61,7 @@ int TpcRawDataTree::InitRun(PHCompositeNode * /*unused*/) m_SampleTree->Branch("nWaveormInFrame", &m_nWaveormInFrame, "nWaveormInFrame/I"); m_SampleTree->Branch("maxFEECount", &m_maxFEECount, "maxFEECount/I"); m_SampleTree->Branch("nSamples", &m_nSamples, "nSamples/I"); - m_SampleTree->Branch("adcSamples", &m_adcSamples[0], "adcSamples[nSamples]/s"); + m_SampleTree->Branch("adcSamples", m_adcSamples.data(), "adcSamples[nSamples]/s"); m_SampleTree->Branch("fee", &m_fee, "fee/I"); m_SampleTree->Branch("sampaAddress", &m_sampaAddress, "sampaAddress/I"); m_SampleTree->Branch("sampaChannel", &m_sampaChannel, "sampaChannel/I"); diff --git a/offline/packages/tpc/TpcRawWriter.cc b/offline/packages/tpc/TpcRawWriter.cc index 5d7711e2bb..bc217516d7 100644 --- a/offline/packages/tpc/TpcRawWriter.cc +++ b/offline/packages/tpc/TpcRawWriter.cc @@ -76,7 +76,7 @@ int TpcRawWriter::InitRun(PHCompositeNode *topNode) } // Create the Cluster node if required - auto trkrclusters = findNode::getClass(dstNode, "TRKR_CLUSTER"); + auto *trkrclusters = findNode::getClass(dstNode, "TRKR_CLUSTER"); if (!trkrclusters) { PHNodeIterator dstiter(dstNode); @@ -94,7 +94,7 @@ int TpcRawWriter::InitRun(PHCompositeNode *topNode) DetNode->addNode(TrkrClusterContainerNode); } - auto clusterhitassoc = findNode::getClass(topNode, "TRKR_CLUSTERHITASSOC"); + auto *clusterhitassoc = findNode::getClass(topNode, "TRKR_CLUSTERHITASSOC"); if (!clusterhitassoc) { PHNodeIterator dstiter(dstNode); @@ -116,7 +116,7 @@ int TpcRawWriter::InitRun(PHCompositeNode *topNode) if (!m_rawhits) { PHNodeIterator dstiter(dstNode); - auto DetNode = dynamic_cast(dstiter.findFirst("PHCompositeNode", "TRKR")); + auto *DetNode = dynamic_cast(dstiter.findFirst("PHCompositeNode", "TRKR")); if (!DetNode) { DetNode = new PHCompositeNode("TRKR"); @@ -124,7 +124,7 @@ int TpcRawWriter::InitRun(PHCompositeNode *topNode) } m_rawhits = new RawHitSetContainerv1; - auto newNode = new PHIODataNode(m_rawhits, "TRKR_RAWHITSET", "PHObject"); + auto *newNode = new PHIODataNode(m_rawhits, "TRKR_RAWHITSET", "PHObject"); DetNode->addNode(newNode); } @@ -311,7 +311,7 @@ int TpcRawWriter::process_event(PHCompositeNode *topNode) // count++; } std::cout << "processing tpc" << std::endl; - float tpc_zmax = m_tGeometry->get_max_driftlength() + m_tGeometry->get_CM_halfwidth(); + double tpc_zmax = m_tGeometry->get_max_driftlength() + m_tGeometry->get_CM_halfwidth(); // loop over the TPC HitSet objects TrkrHitSetContainer::ConstRange tpc_hitsetrange = m_hits->getHitSets(TrkrDefs::TrkrId::tpcId); @@ -405,7 +405,7 @@ int TpcRawWriter::process_event(PHCompositeNode *topNode) { continue; } - float_t fadc = (hitr->second->getAdc()) - pedestal; // proper int rounding +0.5 + double_t fadc = (hitr->second->getAdc()) - pedestal; // proper int rounding +0.5 unsigned short adc = 0; if (fadc > 0) { diff --git a/offline/packages/tpc/TpcSimpleClusterizer.cc b/offline/packages/tpc/TpcSimpleClusterizer.cc index f439d1d682..ec49c51aec 100644 --- a/offline/packages/tpc/TpcSimpleClusterizer.cc +++ b/offline/packages/tpc/TpcSimpleClusterizer.cc @@ -33,6 +33,7 @@ #include +#include #include #include // for sqrt, cos, sin #include @@ -46,7 +47,7 @@ namespace { template - inline constexpr T square(const T &x) + constexpr T square(const T &x) { return x * x; } @@ -63,7 +64,7 @@ namespace unsigned int layer = 0; int side = 0; unsigned int sector = 0; - float pedestal = 0; + double pedestal = 0; bool do_assoc = true; unsigned short phibins = 0; unsigned short phioffset = 0; @@ -142,22 +143,10 @@ namespace int iphi = iter.second.first + my_data.phioffset; int iz = iter.second.second + my_data.zoffset; - if (iphi > phibinhi) - { - phibinhi = iphi; - } - if (iphi < phibinlo) - { - phibinlo = iphi; - } - if (iz > zbinhi) - { - zbinhi = iz; - } - if (iz < zbinlo) - { - zbinlo = iz; - } + phibinhi = std::max(iphi, phibinhi); + phibinlo = std::min(iphi, phibinlo); + zbinhi = std::max(iz, zbinhi); + zbinlo = std::min(iz, zbinlo); // update phi sums double phi_center = my_data.layergeom->get_phicenter(iphi, my_data.side); @@ -205,7 +194,7 @@ namespace clusz -= (clusz < 0) ? my_data.par0_neg : my_data.par0_pos; // create cluster and fill - auto clus = new TrkrClusterv3; + auto *clus = new TrkrClusterv3; clus->setAdc(adc_sum); /// Get the surface key to find the surface from the map @@ -280,7 +269,7 @@ namespace void *ProcessSector(void *threadarg) { - auto my_data = (struct thread_data *) threadarg; + auto *my_data = (struct thread_data *) threadarg; const auto &pedestal = my_data->pedestal; const auto &phibins = my_data->phibins; @@ -303,7 +292,7 @@ namespace unsigned short phibin = TpcDefs::getPad(hitr->first) - phioffset; unsigned short zbin = TpcDefs::getTBin(hitr->first) - zoffset; - float_t fadc = (hitr->second->getAdc()) - pedestal; // proper int rounding +0.5 + double_t fadc = (hitr->second->getAdc()) - pedestal; // proper int rounding +0.5 // std::cout << " layer: " << my_data->layer << " phibin " << phibin << " zbin " << zbin << " fadc " << hitr->second->getAdc() << " pedestal " << pedestal << " fadc " << std::endl unsigned short adc = 0; @@ -332,11 +321,11 @@ namespace all_hit_map.insert(std::make_pair(adc, thisHit)); } // adcval[phibin][zbin] = (unsigned short) adc; - adcval[phibin][zbin] = (unsigned short) adc; + adcval[phibin][zbin] = adc; } } - while (all_hit_map.size() > 0) + while (!all_hit_map.empty()) { auto iter = all_hit_map.rbegin(); if (iter == all_hit_map.rend()) @@ -413,7 +402,7 @@ int TpcSimpleClusterizer::InitRun(PHCompositeNode *topNode) } // Create the Cluster node if required - auto trkrclusters = findNode::getClass(dstNode, "TRKR_CLUSTER"); + auto *trkrclusters = findNode::getClass(dstNode, "TRKR_CLUSTER"); if (!trkrclusters) { PHNodeIterator dstiter(dstNode); @@ -431,7 +420,7 @@ int TpcSimpleClusterizer::InitRun(PHCompositeNode *topNode) DetNode->addNode(TrkrClusterContainerNode); } - auto clusterhitassoc = findNode::getClass(topNode, "TRKR_CLUSTERHITASSOC"); + auto *clusterhitassoc = findNode::getClass(topNode, "TRKR_CLUSTERHITASSOC"); if (!clusterhitassoc) { PHNodeIterator dstiter(dstNode); @@ -614,7 +603,7 @@ int TpcSimpleClusterizer::process_event(PHCompositeNode *topNode) const auto ckey = TrkrDefs::genClusKey(hitsetkey, index); // get cluster - auto cluster = data.cluster_vector[index]; + auto *cluster = data.cluster_vector[index]; // insert in map m_clusterlist->addClusterSpecifyKey(ckey, cluster); diff --git a/offline/packages/tpc/TrainingHits.cc b/offline/packages/tpc/TrainingHits.cc index 3a70db0854..20a810b225 100644 --- a/offline/packages/tpc/TrainingHits.cc +++ b/offline/packages/tpc/TrainingHits.cc @@ -1,17 +1,17 @@ #include "TrainingHits.h" TrainingHits::TrainingHits() + : radius(0.) + , phi(0.) + , z(0.) + , phistep(0.) + , zstep(0.) + , layer(0) + , ntouch(0) + , nedge(0) + , cluskey(0) { v_adc.fill(0); - radius = 0.; - phi = 0.; - z = 0.; - phistep = 0.; - zstep = 0.; - layer = 0; - ntouch = 0; - nedge = 0; - cluskey = 0; } void TrainingHits::Reset() diff --git a/offline/packages/tpccalib/PHTpcResiduals.cc b/offline/packages/tpccalib/PHTpcResiduals.cc index 54bcb5b42e..4360bc7d1b 100644 --- a/offline/packages/tpccalib/PHTpcResiduals.cc +++ b/offline/packages/tpccalib/PHTpcResiduals.cc @@ -769,22 +769,6 @@ int PHTpcResiduals::getNodes(PHCompositeNode* topNode) // tpc global position wrapper m_globalPositionWrapper.loadNodes(topNode); - if (m_disable_module_edge_corr) - { - m_globalPositionWrapper.set_enable_module_edge_corr(false); - } - if (m_disable_static_corr) - { - m_globalPositionWrapper.set_enable_static_corr(false); - } - if (m_disable_average_corr) - { - m_globalPositionWrapper.set_enable_average_corr(false); - } - if (m_disable_fluctuation_corr) - { - m_globalPositionWrapper.set_enable_fluctuation_corr(false); - } return Fun4AllReturnCodes::EVENT_OK; } diff --git a/offline/packages/tpccalib/PHTpcResiduals.h b/offline/packages/tpccalib/PHTpcResiduals.h index 66da67239d..62609e9400 100644 --- a/offline/packages/tpccalib/PHTpcResiduals.h +++ b/offline/packages/tpccalib/PHTpcResiduals.h @@ -106,10 +106,25 @@ class PHTpcResiduals : public SubsysReco m_useMicromegas = value; } - void disableModuleEdgeCorr() { m_disable_module_edge_corr = true; } - void disableStaticCorr() { m_disable_static_corr = true; } - void disableAverageCorr() { m_disable_average_corr = true; } - void disableFluctuationCorr() { m_disable_fluctuation_corr = true; } + void disableModuleEdgeCorr() + { + m_globalPositionWrapper.set_enable_module_edge_corr(false); + } + + void disableStaticCorr() + { + m_globalPositionWrapper.set_enable_static_corr(false); + } + + void disableAverageCorr() + { + m_globalPositionWrapper.set_enable_average_corr(false); + } + + void disableFluctuationCorr() + { + m_globalPositionWrapper.set_enable_fluctuation_corr(false); + } /// modify track map name void setTrackMapName( const std::string& value ) @@ -178,12 +193,6 @@ class PHTpcResiduals : public SubsysReco /// require track crossing zero bool m_requireCrossing = false; - /// disable distortion correction - bool m_disable_module_edge_corr = false; - bool m_disable_static_corr = false; - bool m_disable_average_corr = false; - bool m_disable_fluctuation_corr = false; - /// output file std::string m_outputfile = "TpcSpaceChargeMatrices.root"; diff --git a/offline/packages/tpccalib/TpcCentralMembraneMatching.cc b/offline/packages/tpccalib/TpcCentralMembraneMatching.cc index b3a8687a7d..e790bb2b1d 100644 --- a/offline/packages/tpccalib/TpcCentralMembraneMatching.cc +++ b/offline/packages/tpccalib/TpcCentralMembraneMatching.cc @@ -17,6 +17,8 @@ #include +#include + #include #include @@ -155,11 +157,13 @@ namespace TpcCentralMembraneMatching::TpcCentralMembraneMatching(const std::string& name) : SubsysReco(name) { + /* // calculate stripes center positions CalculateCenters(nPads_R1, R1_e, nGoodStripes_R1_e, keepUntil_R1_e, nStripesIn_R1_e, nStripesBefore_R1_e, cx1_e, cy1_e); CalculateCenters(nPads_R1, R1, nGoodStripes_R1, keepUntil_R1, nStripesIn_R1, nStripesBefore_R1, cx1, cy1); CalculateCenters(nPads_R2, R2, nGoodStripes_R2, keepUntil_R2, nStripesIn_R2, nStripesBefore_R2, cx2, cy2); CalculateCenters(nPads_R3, R3, nGoodStripes_R3, keepUntil_R3, nStripesIn_R3, nStripesBefore_R3, cx3, cy3); + */ } //___________________________________________________________ @@ -977,6 +981,9 @@ int TpcCentralMembraneMatching::getClusterRMatch(double clusterR, int side) //____________________________________________________________________________.. int TpcCentralMembraneMatching::InitRun(PHCompositeNode* topNode) { + + std::cout << "skipOutliers? " << m_skipOutliers << " manualInterp? " << m_manualInterp << std::endl; + if (!m_fieldOn) { m_useHeader = false; @@ -1086,7 +1093,31 @@ int TpcCentralMembraneMatching::InitRun(PHCompositeNode* topNode) // Get truth cluster positions //===================== - const double phi_petal = M_PI / 9.0; // angle span of one petal + CDBTTree *cdbttree = new CDBTTree(m_stripePatternFile); + cdbttree->LoadCalibrations(); + auto cdbMap = cdbttree->GetDoubleEntryMap(); + for (const auto &[index, values] : cdbMap) + { + m_truth_index.push_back(index); + double tmpR = cdbttree->GetDoubleValue(index, "truthR"); + double tmpPhi = cdbttree->GetDoubleValue(index, "truthPhi"); + TVector3 dummyPos(tmpR*cos(tmpPhi), tmpR*sin(tmpPhi), (index / 10000 < 18 ? 1.0 : -1.0)); + m_truth_pos.push_back(dummyPos); + truth_r_phi[(index / 10000 < 18 ? 1 : 0)]->Fill(tmpPhi, tmpR); + if(Verbosity() > 2) + { + std::cout << " index " << index << " x " << dummyPos.X() << " y " << dummyPos.Y() + << " phi " << std::atan2(dummyPos.Y(), dummyPos.X()) + << " radius " << get_r(dummyPos.X(), dummyPos.Y()) << std::endl; + } + if(m_savehistograms) + { + hxy_truth->Fill(dummyPos.X(), dummyPos.Y()); + } + + } + + //const double phi_petal = M_PI / 9.0; // angle span of one petal /* * utility function to @@ -1094,6 +1125,7 @@ int TpcCentralMembraneMatching::InitRun(PHCompositeNode* topNode) * - assign proper z, * - insert in container */ + /* auto save_truth_position = [&](TVector3 source) { source.SetZ(-1); @@ -1256,19 +1288,20 @@ int TpcCentralMembraneMatching::InitRun(PHCompositeNode* topNode) m_truth_index.push_back(truth_index_0); m_truth_index.push_back(truth_index_1); - if (Verbosity() > 2) - { - std::cout << " i " << i << " j " << j << " k " << k << " x1 " << dummyPos.X() << " y1 " << dummyPos.Y() - << " theta " << std::atan2(dummyPos.Y(), dummyPos.X()) - << " radius " << get_r(dummyPos.X(), dummyPos.y()) << std::endl; - } - if (m_savehistograms) - { - hxy_truth->Fill(dummyPos.X(), dummyPos.Y()); - } + if (Verbosity() > 2) + { + std::cout << " i " << i << " j " << j << " k " << k << " x1 " << dummyPos.X() << " y1 " << dummyPos.Y() + << " theta " << std::atan2(dummyPos.Y(), dummyPos.X()) + << " radius " << get_r(dummyPos.X(), dummyPos.y()) << std::endl; + } + if (m_savehistograms) + { + hxy_truth->Fill(dummyPos.X(), dummyPos.Y()); } } } +} +*/ /* int count[2] = {0, 0}; @@ -2121,7 +2154,14 @@ int TpcCentralMembraneMatching::process_event(PHCompositeNode* topNode) cmdiff->setTruthR(m_truth_pos[i].Perp()); cmdiff->setTruthZ(m_truth_pos[i].Z()); - if (m_averageMode) + if (m_totalDistMode) + { + cmdiff->setRecoPhi(raw_pos[reco_index].Phi()); + cmdiff->setRecoR(raw_pos[reco_index].Perp()); + cmdiff->setRecoZ(raw_pos[reco_index].Z()); + cmdiff->setNclusters(reco_nhits[reco_index]); + } + else if (m_averageMode) { cmdiff->setRecoPhi(static_pos[reco_index].Phi()); cmdiff->setRecoR(static_pos[reco_index].Perp()); @@ -2156,6 +2196,14 @@ int TpcCentralMembraneMatching::process_event(PHCompositeNode* topNode) dr = static_pos[reco_index].Perp() - m_truth_pos[i].Perp(); dphi = delta_phi(static_pos[reco_index].Phi() - m_truth_pos[i].Phi()); } + else if(m_totalDistMode) + { + clus_r = raw_pos[reco_index].Perp(); + clus_phi = raw_pos[reco_index].Phi(); + + dr = raw_pos[reco_index].Perp() - m_truth_pos[i].Perp(); + dphi = delta_phi(raw_pos[reco_index].Phi() - m_truth_pos[i].Phi()); + } if (clus_phi < 0) { clus_phi += 2 * M_PI; @@ -2221,11 +2269,21 @@ int TpcCentralMembraneMatching::process_event(PHCompositeNode* topNode) ckey++; } - + // std::cout << "about to fill fluct hist" << std::endl; for (int s = 0; s < 2; s++) { + /* + int N = gr_dR[s]->GetN(); + std::vector dataX(N), dataY(N); + for(int k=0; kGetY()[k]*cos(gr_dR[s]->GetX()[k]); + dataY[k] = gr_dR[s]->GetY()[k]*sin(gr_dR[s]->GetX()[k]); + } + */ + bool firstGoodR = false; for (int j = 1; j <= m_dcc_out->m_hDRint[s]->GetNbinsY(); j++) { @@ -2249,9 +2307,59 @@ int TpcCentralMembraneMatching::process_event(PHCompositeNode* topNode) for (int i = 2; i <= m_dcc_out->m_hDRint[s]->GetNbinsX() - 1; i++) { double phiVal = m_dcc_out->m_hDRint[s]->GetXaxis()->GetBinCenter(i); - m_dcc_out->m_hDRint[s]->SetBinContent(i, j, gr_dR[s]->Interpolate(phiVal, RVal)); - m_dcc_out->m_hDPint[s]->SetBinContent(i, j, RVal * gr_dPhi[s]->Interpolate(phiVal, RVal)); - } + + /* + double num_dPhi = 0.0; + double num_dR = 0.0; + double den = 0.0; + double smoothing_parameter = 2.0; + + double hX = RVal*cos(phiVal); + double hY = RVal*sin(phiVal); + + + + for(int k=0; k 100.0) continue; + + if(distSq < 1e-9) + { + num_dPhi = gr_dPhi[s]->GetZ()[k]; + num_dR = gr_dR[s]->GetZ()[k]; + + den = 1.0; + + break; + } + + double weight = 1.0 / pow(distSq, smoothing_parameter / 2.0); + num_dPhi += weight * gr_dPhi[s]->GetZ()[k]; + num_dR += weight * gr_dR[s]->GetZ()[k]; + den += weight; + + } + + if(den > 0.0) + { + m_dcc_out->m_hDRint[s]->SetBinContent(i, j, num_dR / den); + m_dcc_out->m_hDPint[s]->SetBinContent(i, j, RVal*(num_dPhi / den)); + } + */ + m_dcc_out->m_hDRint[s]->SetBinContent(i, j, gr_dR[s]->Interpolate(phiVal,RVal)); + if(!m_phiHist_in_rad) + { + m_dcc_out->m_hDPint[s]->SetBinContent(i, j, RVal*gr_dPhi[s]->Interpolate(phiVal,RVal)); + } + else + { + m_dcc_out->m_hDPint[s]->SetBinContent(i, j, gr_dPhi[s]->Interpolate(phiVal,RVal)); + } + } } } @@ -2342,15 +2450,149 @@ int TpcCentralMembraneMatching::End(PHCompositeNode* /*topNode*/) } } + for(int s=0; s<2; s++) + { + gr_dR_toInterp[s] = (TGraph2D*)gr_dR[s]->Clone(); + gr_dPhi_toInterp[s] = (TGraph2D*)gr_dPhi[s]->Clone(); + } + + //figure out anomolous points to skip and make list + std::vector pointsToSkip[2]; + if(m_skipOutliers) + { + for(int s=0; s<2; s++) + { + std::vector peakBins; + std::vector peakVals; + TH1D *hPeaks = new TH1D("hPeaks","",500,26,80); + int N = gr_dR[s]->GetN(); + + //Make R histogram + for(int i=0; iFill(gr_dR[s]->GetY()[i]); + } + + int bc = 0; + int pbc = 0; + //loop over and find peaks by identifying hist bins where content is higher than adjacent bins + for(int i=1; i<=500; i++) + { + bc = hPeaks->GetBinContent(i); + if(bc > 10 && bc > pbc) + { + if(peakBins.empty() || i > peakBins[peakBins.size()-1] + 1) + { + peakBins.push_back(i); + } + else + { + peakBins[peakBins.size()-1] = i; + } + } + pbc = bc; + } + + //Convert bins to R values, but if two bins are closer than 0.5 cm, pick the one with the largest bin content + for(int i=0; i<(int)peakBins.size(); i++) + { + if(i<(int)peakBins.size()-1 && hPeaks->GetBinCenter(peakBins[i+1]) - hPeaks->GetBinCenter(peakBins[i]) < 0.5) + { + peakVals.push_back((hPeaks->GetBinContent(peakBins[i]) > hPeaks->GetBinContent(peakBins[i+1]) ? hPeaks->GetBinCenter(peakBins[i]) : hPeaks->GetBinCenter(peakBins[i+1]))); + i++; + } + else + { + peakVals.push_back(hPeaks->GetBinCenter(peakBins[i])); + } + } + + std::vector mu; + std::vector sig; + + //fit each peak with a gaussian to get mean and sigma + TF1 *f1 = new TF1("f1","gaus(0)",26,80); + for(int i=0; i<(int)peakVals.size(); i++) + { + f1->SetParameters(hPeaks->GetBinContent(hPeaks->FindBin(peakVals[i])),peakVals[i],0.2); + double lo = (i == 0) ? peakVals[i] - 0.5 : (peakVals[i-1] + peakVals[i])/2.0; + double hi = (i < (int)peakVals.size() - 1) ? (peakVals[i] + peakVals[i+1])/2.0 : peakVals[i] + 1.0; + hPeaks->Fit(f1,"Q","",lo,hi); + + mu.push_back(f1->GetParameter(1)); + sig.push_back(f1->GetParameter(2)); + } + + //for each point in histogram, identify if within 3 sigma from mean of any of the peaks + //if not within 3 sigma from any of them, add to list of points to skip + for(int i=0; iGetY()[i]; + if(RVal_gr > mu[j] - 3*sig[j] && RVal_gr < mu[j] + 3*sig[j]) + { + good = true; + break; + } + } + if(!good) + { + pointsToSkip[s].push_back(i); + } + } + } + } + for (int s = 0; s < 2; s++) { - bool firstGoodR = false; + int N = gr_dR[s]->GetN(); + std::vector dataX(N); + std::vector dataY(N); + double minR = 99.0; + double maxR = 0.0; + + if(m_skipOutliers) + { + int N_toInterp = (int)gr_dR_toInterp[s]->GetN(); + for(int i=N_toInterp-1; i>=0; i--) + { + for(int j=0; j<(int)pointsToSkip[s].size(); j++) + { + if(i == pointsToSkip[s][j]) + { + gr_dR_toInterp[s]->RemovePoint(i); + gr_dPhi_toInterp[s]->RemovePoint(i); + //gr_points[s]->RemovePoint(i); + break; + } + } + } + } + + for(int k=0; kGetY()[k]; + + dataX[k] = RVal*cos(gr_dR[s]->GetX()[k]); + dataY[k] = RVal*sin(gr_dR[s]->GetX()[k]); + + minR = std::min(RVal, minR); + maxR = std::max(RVal, maxR); + } + + //bool firstGoodR = false; for (int j = 1; j <= m_dcc_out_aggregated->m_hDRint[s]->GetNbinsY(); j++) { double RVal = m_dcc_out_aggregated->m_hDRint[s]->GetYaxis()->GetBinCenter(j); double Rlow = m_dcc_out_aggregated->m_hDRint[s]->GetYaxis()->GetBinLowEdge(j); double Rhigh = m_dcc_out_aggregated->m_hDRint[s]->GetYaxis()->GetBinLowEdge(j + 1); + + if(Rhigh < minR || Rlow > maxR) { continue; +} + /* if (!firstGoodR) { for (int p = 0; p < gr_dR[s]->GetN(); p++) @@ -2363,14 +2605,91 @@ int TpcCentralMembraneMatching::End(PHCompositeNode* /*topNode*/) } continue; } + */ for (int i = 2; i <= m_dcc_out_aggregated->m_hDRint[s]->GetNbinsX() - 1; i++) { double phiVal = m_dcc_out_aggregated->m_hDRint[s]->GetXaxis()->GetBinCenter(i); - m_dcc_out_aggregated->m_hDRint[s]->SetBinContent(i, j, gr_dR[s]->Interpolate(phiVal, RVal)); - m_dcc_out_aggregated->m_hDPint[s]->SetBinContent(i, j, RVal * gr_dPhi[s]->Interpolate(phiVal, RVal)); - } + if(m_manualInterp) + { + double num_dPhi = 0.0; + double num_dR = 0.0; + double den = 0.0; + double smoothing_parameter = 2.0; + + double hX = RVal*cos(phiVal); + double hY = RVal*sin(phiVal); + + for(int k=0; k 100.0) { continue; +} + + if(distSq < 1e-9) + { + num_dPhi = gr_dPhi[s]->GetZ()[k]; + num_dR = gr_dR[s]->GetZ()[k]; + + den = 1.0; + + break; + } + + double weight = 1.0 / pow(distSq, smoothing_parameter / 2.0); + num_dPhi += weight * gr_dPhi[s]->GetZ()[k]; + num_dR += weight * gr_dR[s]->GetZ()[k]; + den += weight; + } + + if(den > 0.0) + { + m_dcc_out_aggregated->m_hDRint[s]->SetBinContent(i, j, num_dR / den); + if(!m_phiHist_in_rad) + { + m_dcc_out_aggregated->m_hDPint[s]->SetBinContent(i, j, RVal*(num_dPhi / den)); + } + else + { + m_dcc_out_aggregated->m_hDPint[s]->SetBinContent(i, j, num_dPhi / den); + } + } + } + else + { + m_dcc_out_aggregated->m_hDRint[s]->SetBinContent(i, j, gr_dR_toInterp[s]->Interpolate(phiVal,RVal)); + if(!m_phiHist_in_rad) + { + m_dcc_out_aggregated->m_hDPint[s]->SetBinContent(i, j, RVal*gr_dPhi_toInterp[s]->Interpolate(phiVal,RVal)); + } + else + { + m_dcc_out_aggregated->m_hDPint[s]->SetBinContent(i, j, gr_dPhi_toInterp[s]->Interpolate(phiVal,RVal)); + } + } + } } } @@ -2395,6 +2714,9 @@ int TpcCentralMembraneMatching::End(PHCompositeNode* /*topNode*/) gr_points[i]->Write(std::format("gr_points_{}z", (i == 1 ? "pos" : "neg")).c_str()); gr_dR[i]->Write(std::format("gr_dr_{}z", (i == 1 ? "pos" : "neg")).c_str()); gr_dPhi[i]->Write(std::format("gr_dPhi_{}z", (i == 1 ? "pos" : "neg")).c_str()); + + gr_dR_toInterp[i]->Write(std::format("gr_dr_toInterp_{}z", (i == 1 ? "pos" : "neg")).c_str()); + gr_dPhi_toInterp[i]->Write(std::format("gr_dPhi_toInterp_{}z", (i == 1 ? "pos" : "neg")).c_str()); } } @@ -2572,8 +2894,8 @@ int TpcCentralMembraneMatching::GetNodes(PHCompositeNode* topNode) std::cout << "TpcCentralMembraneMatching::GetNodes - creating TpcDistortionCorrectionContainer in node " << dcc_out_node_name << std::endl; m_dcc_out = new TpcDistortionCorrectionContainer; m_dcc_out->m_dimensions = 2; - m_dcc_out->m_phi_hist_in_radians = false; - m_dcc_out->m_interpolate_z = true; + m_dcc_out->m_phi_hist_in_radians = m_phiHist_in_rad; + m_dcc_out->m_interpolate_z = false; auto* node = new PHDataNode(m_dcc_out, dcc_out_node_name); runNode->addNode(node); } @@ -2652,6 +2974,7 @@ int TpcCentralMembraneMatching::GetNodes(PHCompositeNode* topNode) return Fun4AllReturnCodes::EVENT_OK; } +/* //_____________________________________________________________ void TpcCentralMembraneMatching::CalculateCenters( int nPads, @@ -2722,3 +3045,4 @@ void TpcCentralMembraneMatching::CalculateCenters( nGoodStripes[j] = i_out; } } +*/ diff --git a/offline/packages/tpccalib/TpcCentralMembraneMatching.h b/offline/packages/tpccalib/TpcCentralMembraneMatching.h index 3b3331fc5f..2bc44e5ede 100644 --- a/offline/packages/tpccalib/TpcCentralMembraneMatching.h +++ b/offline/packages/tpccalib/TpcCentralMembraneMatching.h @@ -98,12 +98,35 @@ class TpcCentralMembraneMatching : public SubsysReco m_averageMode = averageMode; } + void set_totalDistMode(bool totalDistMode) + { + m_totalDistMode = totalDistMode; + } + + void set_skipOutliers(bool skipOutliers) + { + m_skipOutliers = skipOutliers; + } + + void set_manualInterp(bool manualInterp) + { + m_manualInterp = manualInterp; + } + void set_event_sequence(int seq) { m_event_sequence = seq; m_event_index = 100 * seq; } + void set_stripePatternFile(const std::string &stripePatternFile) + { + m_stripePatternFile = stripePatternFile; + } + + void set_phiHistInRad(bool rad){ m_phiHist_in_rad = rad; } + + // void set_laminationFile(const std::string& filename) //{ // m_lamfilename = filename; @@ -136,6 +159,8 @@ class TpcCentralMembraneMatching : public SubsysReco //! tpc distortion correction utility class TpcDistortionCorrection m_distortionCorrection; + bool m_phiHist_in_rad{true}; + //! CMFlashClusterContainer *m_corrected_CMcluster_map{nullptr}; LaserClusterContainer *m_corrected_CMcluster_map{nullptr}; CMFlashDifferenceContainer *m_cm_flash_diffs{nullptr}; @@ -197,9 +222,12 @@ class TpcCentralMembraneMatching : public SubsysReco TTree *match_tree{nullptr}; TTree *event_tree{nullptr}; + std::string m_stripePatternFile = "/sphenix/u/bkimelman/CMStripePattern.root"; + bool m_useHeader{true}; bool m_averageMode{false}; - + bool m_totalDistMode{false}; + std::vector e_matched; std::vector e_truthIndex; std::vector e_truthR; @@ -275,6 +303,9 @@ class TpcCentralMembraneMatching : public SubsysReco TGraph2D *gr_dPhi[2]{nullptr, nullptr}; TGraph *gr_points[2]{nullptr, nullptr}; + TGraph2D *gr_dR_toInterp[2]{nullptr, nullptr}; + TGraph2D *gr_dPhi_toInterp[2]{nullptr, nullptr}; + /// phi cut for matching clusters to pad /** TODO: this will need to be adjusted to match beam-induced time averaged distortions */ double m_phi_cut{0.025}; @@ -298,6 +329,7 @@ class TpcCentralMembraneMatching : public SubsysReco //@} + /* ///@name central membrane pads definitions //@{ static constexpr double mm{1.0}; @@ -364,6 +396,7 @@ class TpcCentralMembraneMatching : public SubsysReco std::array &nStripesIn, std::array &nStripesBefore, double cx[][nRadii], double cy[][nRadii]); + */ /// store centers of all central membrane pads std::vector m_truth_pos; @@ -379,6 +412,8 @@ class TpcCentralMembraneMatching : public SubsysReco bool m_fieldOn{true}; bool m_doFancy{false}; bool m_doHadd{false}; + bool m_skipOutliers{false}; + bool m_manualInterp{false}; std::vector m_reco_RPeaks[2]; double m_m[2]{}; diff --git a/offline/packages/tpccalib/TpcLaminationFitting.cc b/offline/packages/tpccalib/TpcLaminationFitting.cc index 29b4cb106e..9e1eda849d 100644 --- a/offline/packages/tpccalib/TpcLaminationFitting.cc +++ b/offline/packages/tpccalib/TpcLaminationFitting.cc @@ -8,6 +8,8 @@ #include +#include + #include #include @@ -25,11 +27,16 @@ #include #include #include +#include #include #include #include #include +#include +#include + + #include #include #include @@ -55,25 +62,51 @@ int TpcLaminationFitting::InitRun(PHCompositeNode *topNode) { for (int s = 0; s < 2; s++) { + + m_hPetal[s] = new TH2D((boost::format("hPetal_%s") %(s == 1 ? "North" : "South")).str().c_str(), (boost::format("TPC %s;#phi;R [cm]") %(s == 1 ? "North" : "South")).str().c_str(), 500, m_phiModMin[s], m_phiModMax[s], 500, 30, 80); + m_parameterScan[s] = new TH2D((boost::format("parameterScan_%s") %(s == 1 ? "North" : "South")).str().c_str(), (boost::format("TPC %s Lamination Parameter Scan;m;B") %(s == 1 ? "North" : "South")).str().c_str(), 41, -0.0205, 0.0205, 49, -3.0625, 3.0625); + //m_parameterScan[s] = new TH2D((boost::format("parameterScan_%s") %(s == 1 ? "North" : "South")).str().c_str(), (boost::format("TPC %s Lamination Parameter Scan;m;B") %(s == 1 ? "North" : "South")).str().c_str(), 101, -0.101, 0.101, 101, -10.1, 10.1); + //m_parameterScan[s] = new TH2D((boost::format("parameterScan_%s") %(s == 1 ? "North" : "South")).str().c_str(), (boost::format("TPC %s Lamination Parameter Scan;A (asymptote);C (decay constant)") %(s == 1 ? "North" : "South")).str().c_str(), 101, -1.005, 0.005, 101, -0.0025, 0.5025); + for (int l = 0; l < 18; l++) { - double shift = l * M_PI / 9; + double shift = (l * M_PI / 9); if (s == 0) { shift += M_PI / 18; } + m_laminationIdeal[l][s] = shift; + //this function for the offset was determined from fitting the measured lamination offsets vs ideal lamination phi from field off data in run 75103 + //m_laminationOffset[l][s] = -0.00296837 + 0.0014604 * cos(shift - 1.2246); + if(s == 0) + { + //m_laminationOffset[l][s] = -0.00236289 + 0.00143918 * cos(shift - 1.31782); + m_laminationOffset[l][s] = -0.00148465 + 0.00219335 * cos(shift - 1.24219); + } + else + { + //m_laminationOffset[l][s] = -0.00323259 + 0.00138333 * cos(shift - 1.25373); + m_laminationOffset[l][s] = -0.00303345 + 0.0010828 * cos(shift - 1.03718); + } - m_hLamination[l][s] = new TH2D(std::format("hLamination{}_{}", l, (s == 1 ? "North" : "South")).c_str(), std::format("Lamination {} {}, #phi_{{expected}}={:.2f};R [cm];#phi", l, (s == 1 ? "North" : "South"), shift).c_str(), 200, 30, 80, 200, shift - 0.2, shift + 0.2); - //m_fLamination[l][s] = new TF1((std::format("fLamination{}_{}", l, (s == 1 ? "North" : "South")).c_str(), "[0]+[1]*exp(-[2]*x)", 30, 80); - //m_fLamination[l][s] = new TF1((std::format("fLamination{}_{}", l, (s == 1 ? "North" : "South")).c_str(), "[0]*(1+exp(-[2]*(x-[1])))", 30, 80); - m_fLamination[l][s] = new TF1(std::format("fLamination{}_{}", l, (s == 1 ? "North" : "South")).c_str(), "[3]+[0]*(1-exp(-[2]*(x-[1])))", 30, 80); - //m_fLamination[l][s]->SetParameters(-0.022 + shift, log(3.0/(-0.22 + shift)), 0.12); - m_fLamination[l][s]->SetParameters(-0.011, 30, 0.16, 0.0); - m_fLamination[l][s]->SetParLimits(0, -0.22, 0.0); - m_fLamination[l][s]->SetParLimits(1, 0, 80); - m_fLamination[l][s]->SetParLimits(2, 0.0, 3); - m_fLamination[l][s]->FixParameter(3, shift); - m_laminationCenter[l][s] = shift; + if(m_fieldOff) + { + m_hLamination[l][s] = new TH2D((boost::format("hLamination%d_%s") %l %(s == 1 ? "North" : "South")).str().c_str(), (boost::format("Lamination %d %s, #phi_{ideal}=%.2f;R [cm];#phi") %l %(s == 1 ? "North" : "South") %m_laminationIdeal[l][s]).str().c_str(), 200, 30, 80, 200, m_laminationIdeal[l][s] - 0.2, m_laminationIdeal[l][s] + 0.2); + m_fLamination[l][s] = new TF1((boost::format("fLamination%d_%s") %l %(s == 1 ? "North" : "South")).str().c_str(), "[0]+[1]", 30, 80); + m_fLamination[l][s]->SetParameters(m_laminationOffset[l][s], m_laminationIdeal[l][s]); + m_fLamination[l][s]->SetParLimits(0, -0.05, 0.05); + m_fLamination[l][s]->FixParameter(1, m_laminationIdeal[l][s]); + } + else + { + m_hLamination[l][s] = new TH2D((boost::format("hLamination%d_%s") %l %(s == 1 ? "North" : "South")).str().c_str(), (boost::format("Lamination %d %s, #phi_{nominal}=%.2f;R [cm];#phi") %l %(s == 1 ? "North" : "South") %(m_laminationIdeal[l][s]+m_laminationOffset[l][s])).str().c_str(), 200, 30, 80, 200, m_laminationIdeal[l][s]+m_laminationOffset[l][s] - 0.2, m_laminationIdeal[l][s]+m_laminationOffset[l][s] + 0.2); + m_fLamination[l][s] = new TF1((boost::format("fLamination%d_%s") %l %(s == 1 ? "North" : "South")).str().c_str(), "[3]+[0]*(1-exp(-[2]*(x-[1])))", 30, 80); + m_fLamination[l][s]->SetParameters(-0.08, 38, 0.16, 0.0); + m_fLamination[l][s]->SetParLimits(0, -0.02, 0.0); + m_fLamination[l][s]->SetParLimits(1, 0, 50); + m_fLamination[l][s]->SetParLimits(2, 0.0, 1.0); + m_fLamination[l][s]->FixParameter(3, m_laminationIdeal[l][s]+m_laminationOffset[l][s]); + } } } @@ -112,6 +145,95 @@ int TpcLaminationFitting::InitRun(PHCompositeNode *topNode) m_run_ZDC_map_auau.insert(std::pair(54969, 9680.)); */ + /* + for(int module=0; module<4; module++) + { + double spacing[nRadii]; + for(int j=0; j m_phiModMax[s]) + { + phi[s] -= M_PI / 9; + } + m_truthR[s].push_back(RValues[module][j]); + m_truthPhi[s].push_back(phi[s]); + } + + } + } + } + */ + CDBTTree *cdbttree = new CDBTTree(m_stripePatternFile); + cdbttree->LoadCalibrations(); + auto cdbMap = cdbttree->GetDoubleEntryMap(); + for (const auto &[index, values] : cdbMap) + { + if(index / 10000 == 18) + { + m_truthR[0].push_back(cdbttree->GetDoubleValue(index, "truthR")); + m_truthPhi[0].push_back(cdbttree->GetDoubleValue(index, "truthPhi")); + } + else if(index / 10000 == 0) + { + m_truthR[1].push_back(cdbttree->GetDoubleValue(index, "truthR")); + m_truthPhi[1].push_back(cdbttree->GetDoubleValue(index, "truthPhi")); + } + } + if(m_truthR[0].empty() || m_truthPhi[0].empty() || m_truthR[1].empty() || m_truthPhi[1].empty()) + { + std::cerr << "stripe pattern file passed has no stripes on one side. Exiting" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } + /* + for(int i=0; i<32; i++) + { + for(int j=0; j<11; j++) + { + int index0 = 18 + i*100 + j; + int index1 = i*100 + j; + + double R0 = cdbttree->GetDoubleValue(index0, "truthR"); + double Phi0 = cdbttree->GetDoubleValue(index0, "truthPhi"); + if(!std::isnan(R0) && !std::isnan(Phi0)) + { + m_truthR[0].push_back(R0); + m_truthPhi[0].push_back(Phi0); + } + + double R1 = cdbttree->GetDoubleValue(index1, "truthR"); + double Phi1 = cdbttree->GetDoubleValue(index1, "truthPhi"); + if(!std::isnan(R1) && !std::isnan(Phi1)) + { + m_truthR[1].push_back(R1); + m_truthPhi[1].push_back(Phi1); + } + } + } + */ + int ret = GetNodes(topNode); return ret; } @@ -200,13 +322,17 @@ int TpcLaminationFitting::GetNodes(PHCompositeNode *topNode) delete m_dcc_out->m_hDZint[i]; m_dcc_out->m_hDZint[i] = new TH2F(std::format("hIntDistortionZ{}", extension[i]).c_str(), std::format("hIntDistortionZ{}", extension[i]).c_str(), m_phibins + 2, phiMin, phiMax, m_rbins + 2, rMin, rMax); delete m_dcc_out->m_hentries[i]; - m_dcc_out->m_hentries[i] = new TH2I(std::format("hEntries{}", extension[i]).c_str(), std::format("hEntries{}", extension[i]).c_str(), m_phibins + 2, phiMin, phiMax, m_rbins + 2, rMin, rMax); + m_dcc_out->m_hentries[i] = new TH2I((boost::format("hEntries%s") % extension[i]).str().c_str(), (boost::format("hEntries%s") % extension[i]).str().c_str(), m_phibins + 2, phiMin, phiMax, m_rbins + 2, rMin, rMax); + + phiDistortionLamination[i] = new TH2F((boost::format("phiDistortionLamination%s") % extension[i]).str().c_str(), (boost::format("phiDistortionLamination%s") % extension[i]).str().c_str(), m_phibins + 2, phiMin, phiMax, m_rbins + 2, rMin, rMax); + } m_laminationTree = new TTree("laminationTree","laminationTree"); m_laminationTree->Branch("side",&m_side); m_laminationTree->Branch("lamIndex",&m_lamIndex); m_laminationTree->Branch("lamPhi",&m_lamPhi); + m_laminationTree->Branch("lamOffset",&m_lamShift); m_laminationTree->Branch("goodFit",&m_goodFit); m_laminationTree->Branch("A",&m_A); m_laminationTree->Branch("B",&m_B); @@ -216,6 +342,7 @@ int TpcLaminationFitting::GetNodes(PHCompositeNode *topNode) m_laminationTree->Branch("C_err",&m_C_err); m_laminationTree->Branch("distanceToFit",&m_dist); m_laminationTree->Branch("nBinsFit",&m_nBins); + m_laminationTree->Branch("RMSE",&m_rmse); return Fun4AllReturnCodes::EVENT_OK; @@ -262,11 +389,12 @@ int TpcLaminationFitting::process_event(PHCompositeNode *topNode) LaserCluster *cmclus = cmclus_orig; // const unsigned int adc = cmclus->getAdc(); bool side = (bool) TpcDefs::getSide(cmkey); - if (cmclus->getNLayers() <= m_nLayerCut) + if (cmclus->getNLayers() < m_nLayerCut) { continue; } + //Acts::Vector3 pos(cmclus->getX(), cmclus->getY(), cmclus->getZ()); Acts::Vector3 pos(cmclus->getX(), cmclus->getY(), (side ? 1.0 : -1.0)); if (m_dcc_in_module_edge) @@ -280,25 +408,49 @@ int TpcLaminationFitting::process_event(PHCompositeNode *topNode) TVector3 tmp_pos(pos[0], pos[1], pos[2]); - for (int l = 0; l < 18; l++) + if(cmclus->getNLayers() > m_nLayerCut && cmclus->getSDWeightedLayer() > 0.5) { - double shift = m_laminationCenter[l][side]; - - double phi2pi = tmp_pos.Phi(); - if (side && phi2pi < -0.2) - { - phi2pi += 2 * M_PI; - } - if (!side && phi2pi < M_PI / 18 - 0.2) + for (int l = 0; l < 18; l++) { - phi2pi += 2 * M_PI; + double shift = m_laminationIdeal[l][side]; + + double phi2pi = tmp_pos.Phi(); + if (side && phi2pi < -0.2) + { + phi2pi += 2 * M_PI; + } + if (!side && phi2pi < M_PI / 18 - 0.2) + { + phi2pi += 2 * M_PI; + } + + if (phi2pi > shift - 0.2 && phi2pi < shift + 0.2) + { + m_hLamination[l][side]->Fill(tmp_pos.Perp(), phi2pi); + } } + } - if (phi2pi > shift - 0.2 && phi2pi < shift + 0.2) - { - m_hLamination[l][side]->Fill(tmp_pos.Perp(), phi2pi); - } + if(cmclus->getSDWeightedLayer() > 0.5) + { + continue; + } + + double phi2pimod = tmp_pos.Phi(); + if (phi2pimod < 0.0) + { + phi2pimod += 2 * M_PI; + } + while(side && phi2pimod > M_PI / 9) + { + phi2pimod -= M_PI / 9; } + while(!side && phi2pimod > M_PI / 18) + { + phi2pimod -= M_PI / 9; + } + + m_hPetal[side]->Fill(phi2pimod, tmp_pos.Perp()); } return Fun4AllReturnCodes::EVENT_OK; @@ -328,6 +480,7 @@ int TpcLaminationFitting::fitLaminations() //float ZDC = 4500.0; TF1 *Af[2] = {new TF1("AN","pol1",0,100000), new TF1("AS","pol1",0,100000)}; TF1 *Bf[2] = {new TF1("BN","pol1",0,100000), new TF1("BS","pol1",0,100000)}; + //TF1 *Cf[2] = {new TF1("CN","pol1",0,100000), new TF1("CS","pol1",0,100000)}; double Cseed[2] = {0.16, 0.125}; if(ppMode) @@ -349,9 +502,12 @@ int TpcLaminationFitting::fitLaminations() Af[0]->SetParameters(-0.007999,-1.783e-6); Af[1]->SetParameters(-0.003288,-2.297e-6); - + Bf[0]->SetParameters(31.55,0.0006141); Bf[1]->SetParameters(34.7,0.0005226); + + //Cf[0]->SetParameters(5.33e-5,0.0); + //Cf[1]->SetParameters(4.166e-5,0.0); } else { @@ -379,6 +535,9 @@ int TpcLaminationFitting::fitLaminations() Bf[0]->SetParameters(32.96,0.0002997); Bf[1]->SetParameters(31.19,0.0005622); + //Cf[0]->SetParameters(1.316-5,0.0); + //Cf[1]->SetParameters(1.284e-5,0.0); + Cseed[0] = 0.125; Cseed[1] = 0.122; } @@ -400,12 +559,16 @@ int TpcLaminationFitting::fitLaminations() TGraph *gr = new TGraph(); TGraph *proj = new TGraph(); - //m_fLamination[l][s]->SetParameters(-0.022 + m_laminationCenter[l][s], 4.595 * seedScale, 0.138); - //m_fLamination[l][s]->SetParameters(-0.022 + m_laminationCenter[l][s], log(4.595 * seedScale/(-0.022 + m_laminationCenter[l][s])), 0.138); - //m_fLamination[l][s]->SetParameters(-0.011 + m_laminationCenter[l][s], 0.025, 0.16); - //m_fLamination[l][s]->SetParameters(-0.011, 30, 0.16, m_laminationCenter[l][s]); - m_fLamination[l][s]->SetParameters(Af[s]->Eval(m_ZDC_coincidence), Bf[s]->Eval(m_ZDC_coincidence), Cseed[s], m_laminationCenter[l][s]); - m_fLamination[l][s]->FixParameter(3, m_laminationCenter[l][s]); + if(m_fieldOff) + { + m_fLamination[l][s]->SetParameters(m_laminationOffset[l][s], m_laminationIdeal[l][s]); + m_fLamination[l][s]->FixParameter(1, m_laminationIdeal[l][s]); + } + else + { + m_fLamination[l][s]->SetParameters(Af[s]->Eval(m_ZDC_coincidence), Bf[s]->Eval(m_ZDC_coincidence), Cseed[s], m_laminationIdeal[l][s] + m_laminationOffset[l][s]); + m_fLamination[l][s]->FixParameter(3, m_laminationIdeal[l][s] + m_laminationOffset[l][s]); + } TF1 *fitSeed = (TF1 *) m_fLamination[l][s]->Clone(); fitSeed->SetName(std::format("fitSeed{}_{}", l, (s == 1 ? "North" : "South")).c_str()); @@ -444,7 +607,7 @@ int TpcLaminationFitting::fitLaminations() { double phi = m_hLamination[l][s]->GetYaxis()->GetBinCenter(j); - if (fabs(phi - m_laminationCenter[l][s]) > 0.05) + if (fabs(phi - m_laminationIdeal[l][s]) > 0.05) { continue; } @@ -481,6 +644,10 @@ int TpcLaminationFitting::fitLaminations() double distToFunc = 0.0; int nBinsUsed = 0; + int nBinsUsed_R_lt_45 = 0; + + double wc = 0.0; + double c = 0.0; for (int i = 1; i <= m_hLamination[l][s]->GetNbinsX(); i++) { @@ -506,14 +673,34 @@ int TpcLaminationFitting::fitLaminations() { distToFunc += j; nBinsUsed++; + if(R < 45.0) + { + nBinsUsed_R_lt_45++; + } break; } } + for(int j=0; j<= nBinAvg; j++) + { + if(m_hLamination[l][s]->GetBinContent(i,funcBin + j) > 0) + { + wc += m_hLamination[l][s]->GetBinContent(i,funcBin + j) * pow(j,2); + c += m_hLamination[l][s]->GetBinContent(i,funcBin + j); + } + if(j != 0 && m_hLamination[l][s]->GetBinContent(i,funcBin - j) > 0) + { + wc += m_hLamination[l][s]->GetBinContent(i,funcBin - j) * pow(j,2); + c += m_hLamination[l][s]->GetBinContent(i,funcBin - j); + } + } } m_distanceToFit[l][s] = distToFunc / nBinsUsed; m_nBinsFit[l][s] = nBinsUsed; - if (nBinsUsed < 10 || distToFunc / nBinsUsed > 1.0) + if(c>0) { m_fitRMSE[l][s] = sqrt(wc / c); + } else { m_fitRMSE[l][s] = -999; +} + if (nBinsUsed < 10 || distToFunc / nBinsUsed > 1.0 || nBinsUsed_R_lt_45 < 5) { m_laminationGoodFit[l][s] = false; } @@ -527,14 +714,8 @@ int TpcLaminationFitting::fitLaminations() return Fun4AllReturnCodes::EVENT_OK; } -int TpcLaminationFitting::InterpolatePhiDistortions(TH2 *simPhiDistortion[2]) +int TpcLaminationFitting::InterpolatePhiDistortions() { - phiDistortionLamination[0] = (TH2 *) simPhiDistortion[0]->Clone(); - phiDistortionLamination[0]->Reset(); - phiDistortionLamination[0]->SetName("phiDistortionLamination0"); - phiDistortionLamination[1] = (TH2 *) simPhiDistortion[1]->Clone(); - phiDistortionLamination[1]->Reset(); - phiDistortionLamination[1]->SetName("phiDistortionLamination1"); for (int s = 0; s < 2; s++) { @@ -562,51 +743,36 @@ int TpcLaminationFitting::InterpolatePhiDistortions(TH2 *simPhiDistortion[2]) phi -= 2 * M_PI; } int phiBin = phiDistortionLamination[s]->GetXaxis()->FindBin(phi); - //m_fLamination[l][s]->SetParameter(0, m_fLamination[l][s]->GetParameter(0) - m_laminationCenter[l][s]); - m_fLamination[l][s]->SetParameter(3, m_laminationOffset[l][s]); - /* - if(s==0) - { - m_fLamination[l][s]->SetParameter(3, 0.0); - } + if(m_fieldOff) + { + m_laminationOffset[l][s] = m_fLamination[l][s]->GetParameter(0); + m_fLamination[l][s]->SetParameter(1, 0.0); + } else - { - m_fLamination[l][s]->SetParameter(3, 0.0); - } - */ - //m_fLamination[l][s]->SetParameter(3, 0.0); - double phiDistortion = R * m_fLamination[l][s]->Integral(phiDistortionLamination[s]->GetYaxis()->GetBinLowEdge(i), phiDistortionLamination[s]->GetYaxis()->GetBinLowEdge(i + 1)) / (phiDistortionLamination[s]->GetYaxis()->GetBinLowEdge(i + 1) - phiDistortionLamination[s]->GetYaxis()->GetBinLowEdge(i)); - //m_fLamination[l][s]->SetParameter(0, m_fLamination[l][s]->GetParameter(0) + m_laminationCenter[l][s]); - m_fLamination[l][s]->SetParameter(3, m_laminationCenter[l][s]); + { + //m_fLamination[l][s]->SetParameter(3, -1.0*m_laminationOffset[l][s]); + m_fLamination[l][s]->SetParameter(3, 0.0); + } + double phiDistortion = m_fLamination[l][s]->Integral(phiDistortionLamination[s]->GetYaxis()->GetBinLowEdge(i), phiDistortionLamination[s]->GetYaxis()->GetBinLowEdge(i + 1)) / (phiDistortionLamination[s]->GetYaxis()->GetBinLowEdge(i + 1) - phiDistortionLamination[s]->GetYaxis()->GetBinLowEdge(i)); + if(!m_phiHist_in_rad) + { + phiDistortion *= R; + } + if(m_fieldOff) + { + m_fLamination[l][s]->SetParameter(1, m_laminationIdeal[l][s]); + } + else + { + //m_fLamination[l][s]->SetParameter(3, m_laminationIdeal[l][s]); + m_fLamination[l][s]->SetParameter(3, m_laminationIdeal[l][s] + m_laminationOffset[l][s]); + } phiDistortionLamination[s]->SetBinContent(phiBin, i, phiDistortion); + m_dcc_out->m_hDPint[s]->SetBinContent(phiBin, i, phiDistortion); } } } - for (int s = 0; s < 2; s++) - { - m_dcc_out->m_hDPint[s] = (TH2 *) phiDistortionLamination[s]->Clone(); - m_dcc_out->m_hDPint[s]->SetName(std::format("hIntDistortionP{}", (s == 0 ? "_negz" : "_posz")).c_str()); - } - - /* - for(int s=0; s<2; s++) - { - for(int i=1; i<=m_dcc_out->m_hDPint[s]->GetNbinsX(); i++) - { - for(int j=1; j<=m_dcc_out->m_hDPint[s]->GetNbinsY(); j++) - { - if(phiDistortionLamination[s]->GetBinContent(i,j) != 0.0) - { - m_dcc_out->m_hDPint[s]->SetBinContent(i,j, phiDistortionLamination[s]->GetBinContent(i,j)); - } - } - } - } - */ - - // m_dcc_out->m_hDPint[0] = (TH2*)phiDistortionLamination[0]->Clone(); - // m_dcc_out->m_hDPint[1] = (TH2*)phiDistortionLamination[1]->Clone(); for (int s = 0; s < 2; s++) { @@ -625,17 +791,14 @@ int TpcLaminationFitting::InterpolatePhiDistortions(TH2 *simPhiDistortion[2]) laminationPhiBins.push_back(j); } } - if (laminationPhiBins.size() > 1) { laminationPhiBins.push_back(laminationPhiBins[0]); } - for (int lamPair = 0; lamPair < (int) laminationPhiBins.size() - 1; lamPair++) { double dist0 = m_dcc_out->m_hDPint[s]->GetBinContent(laminationPhiBins[lamPair], i); double dist1 = m_dcc_out->m_hDPint[s]->GetBinContent(laminationPhiBins[lamPair + 1], i); - int nEmptyBins = laminationPhiBins[lamPair + 1] - laminationPhiBins[lamPair] - 1; if (laminationPhiBins[lamPair] > laminationPhiBins[lamPair + 1]) { @@ -646,7 +809,6 @@ int TpcLaminationFitting::InterpolatePhiDistortions(TH2 *simPhiDistortion[2]) bool wrap = false; int wrapBin = -1; for (int j = 1; j <= nEmptyBins; j++) - // for(int j=+ 1; j m_dcc_out->m_hDPint[s]->GetNbinsX() - 1) { @@ -670,9 +832,153 @@ int TpcLaminationFitting::InterpolatePhiDistortions(TH2 *simPhiDistortion[2]) return Fun4AllReturnCodes::EVENT_OK; } -int TpcLaminationFitting::End(PHCompositeNode * /*topNode*/) +int TpcLaminationFitting::doGlobalRMatching(int side) { + std::vector distortedPhi; + TF1 *tmpLamFit = (TF1*)m_fLamination[0][side]->Clone(); + + double meanB = 0.0; + + if(m_fieldOff) + { + tmpLamFit->SetParameters(0.0, 0.0); + meanB = -999.99; + } + else + { + double meanA = 0.0; + double meanC = 0.0; + int nGoodFits = 0; + for(int l = 0; l < 18; l++) + { + if(!m_laminationGoodFit[l][side]) + { + continue; + } + meanA += m_fLamination[l][side]->GetParameter(0); + meanB += m_fLamination[l][side]->GetParameter(1); + meanC += m_fLamination[l][side]->GetParameter(2); + nGoodFits++; + } + if(nGoodFits == 0) + { + return Fun4AllReturnCodes::EVENT_OK; + } + + meanA /= nGoodFits; + meanB /= nGoodFits; + meanC /= nGoodFits; + //tmpLamFit->SetParameters(meanA, meanB, meanC, meanOffset); + tmpLamFit->SetParameters(meanA, meanB, meanC, 0.0); + } + + + for(int i=0; i<(int)m_truthPhi[side].size(); i++) + { + double distortedPhiTmp = m_truthPhi[side][i] + tmpLamFit->Eval(m_truthR[side][i]); + while(distortedPhiTmp < m_phiModMin[side]) + { + distortedPhiTmp += M_PI / 9; + } + while(distortedPhiTmp > m_phiModMax[side]) + { + distortedPhiTmp -= M_PI / 9; + } + distortedPhi.push_back(distortedPhiTmp); + } + + double maxSum = 0.0; + double best_m = 0.0; + double best_b = 0.0; + //int mStep = 0; + //int bStep = 0; + //for(double m = -0.02; m<=0.02; m+=0.001) + for(int xbin=1; xbin<=m_parameterScan[side]->GetNbinsX(); xbin++) + { + double m = m_parameterScan[side]->GetXaxis()->GetBinCenter(xbin); + //for(double b=-3.0; b<=3.0; b+=0.125) + for(int ybin=1; ybin<=m_parameterScan[side]->GetNbinsY(); ybin++) + { + double b = m_parameterScan[side]->GetYaxis()->GetBinCenter(ybin); + double sum = 0.0; + for(int i=0; i<(int)m_truthR[side].size(); i++) + { + double distortedTruthR = (m_truthR[side][i] + b)/(1.0 - m); + //double distortedTruthR = boost::math::lambert_w0(-m*b*exp(meanB-m_truthR[side][i]-m))/b + m_truthR[side][i] + m; + int binR = m_hPetal[side]->GetYaxis()->FindBin(distortedTruthR); + int binPhi = m_hPetal[side]->GetXaxis()->FindBin(distortedPhi[i]); + for(int j=-2; j<=2; j++) + { + int neighborBinR = binR + j; + if(neighborBinR < 1 || neighborBinR > m_hPetal[side]->GetNbinsY()) { continue; +} + for(int k=-5; k<=5; k++) + { + int neighborBinPhi = binPhi + k; + if(neighborBinPhi < 1) + { + neighborBinPhi += m_hPetal[side]->GetNbinsX(); + } + if(neighborBinPhi > m_hPetal[side]->GetNbinsX()) + { + neighborBinPhi -= m_hPetal[side]->GetNbinsX(); + } + sum += m_hPetal[side]->GetBinContent(neighborBinPhi, neighborBinR); + } + } + } + + if(Verbosity() > 2) + { + std::cout << "working on side " << side << " m step " << xbin-1 << " b step " << ybin-1 << " with m = " << m << " and b = " << b << " with sum = " << sum << std::endl; + } + + m_parameterScan[side]->Fill(m, b, sum); + + if(sum > maxSum) + { + maxSum = sum; + best_m = m; + best_b = b; + } + //bStep++; + } + //mStep++; + } + + std::cout << "Best R distortion for side " << side << " is m = " << best_m << " and b = " << best_b << " with sum of " << maxSum << std::endl; + + for(int j=2; j<=m_dcc_out->m_hDRint[side]->GetNbinsX()-1; j++) + { + for(int i=2; i<=m_dcc_out->m_hDRint[side]->GetNbinsY()-1; i++) + { + double R = m_dcc_out->m_hDRint[side]->GetYaxis()->GetBinCenter(i); + double distortionR = R * best_m + best_b; + m_dcc_out->m_hDRint[side]->SetBinContent(j, i, distortionR); + } + } + + std::vector bestDistortedR; + for(double i : m_truthR[side]) + { + double distortedR = (i + best_b)/(1.0 - best_m); + bestDistortedR.push_back(distortedR); + } + + m_bestRMatch[side] = new TGraph(distortedPhi.size(), distortedPhi.data(), bestDistortedR.data()); + m_bestRMatch[side]->SetTitle((boost::format("Best R matching TPC %s, m = %.3f b = %.3f") %(side == 0 ? "South" : "North") %best_m %best_b).str().c_str()); + m_bestRMatch[side]->SetName((boost::format("bestRMatch_side%d") %side).str().c_str()); + m_bestRMatch[side]->SetMarkerStyle(25); + m_bestRMatch[side]->SetMarkerSize(0.8); + m_bestRMatch[side]->SetMarkerColor(kRed); + + return Fun4AllReturnCodes::EVENT_OK; +} + +int TpcLaminationFitting::End(PHCompositeNode * /*topNode*/) +{ + std::string sql = "SELECT * FROM gl1_scalers WHERE runnumber = " + std::to_string(m_runnumber) + ";"; odbc::Statement *stmt = DBInterface::instance()->getStatement("daq"); odbc::ResultSet *resultSet = stmt->executeQuery(sql); @@ -683,7 +989,7 @@ int TpcLaminationFitting::End(PHCompositeNode * /*topNode*/) delete resultSet; return Fun4AllReturnCodes::ABORTRUN; } - + while (resultSet->next()) { int index = resultSet->getInt("index"); @@ -692,20 +998,20 @@ int TpcLaminationFitting::End(PHCompositeNode * /*topNode*/) scalers[index][1] = resultSet->getLong("live"); scalers[index][2] = resultSet->getLong("raw"); } - + delete resultSet; - + m_ZDC_coincidence = (1.0*scalers[3][2]/scalers[0][2])/(106e-9); - + std::cout << "Runnumber: " << m_runnumber << " ppMode: " << ppMode << " ZDC coindicence rate: " << m_ZDC_coincidence << std::endl; - + int fitSuccess = fitLaminations(); if (fitSuccess != Fun4AllReturnCodes::EVENT_OK) { std::cout << PHWHERE << " Return code for lamination fitting was " << fitSuccess << " and not successful" << std::endl; return Fun4AllReturnCodes::ABORTRUN; } - + if(!m_QAFileName.empty()) { TCanvas *c1 = new TCanvas(); @@ -726,19 +1032,57 @@ int TpcLaminationFitting::End(PHCompositeNode * /*topNode*/) } m_fLamination[l][s]->Draw("same"); - TLine *line = new TLine(30,m_laminationCenter[l][s],80,m_laminationCenter[l][s]); - line->SetLineColor(kBlue); - line->SetLineStyle(2); - line->Draw("same"); + TLegend *leg = new TLegend(0.15,0.15,0.45,0.4); + + TLine *lineIdeal; + TLine *lineOffset; + if(m_fieldOff) + { + lineIdeal = new TLine(30,m_laminationIdeal[l][s],80,m_laminationIdeal[l][s]); + lineIdeal->SetLineColor(kBlue); + leg->AddEntry(lineIdeal,std::format("#phi_{{ideal}}={:.6f}",m_laminationIdeal[l][s]).c_str(), "l"); + } + else + { + lineIdeal = new TLine(30,m_laminationIdeal[l][s],80,m_laminationIdeal[l][s]); + lineIdeal->SetLineColor(kBlue); + leg->AddEntry(lineIdeal,std::format("#phi_{{ideal}}={:.6f}",m_laminationIdeal[l][s]).c_str(), "l"); + + lineOffset = new TLine(30,m_laminationIdeal[l][s]+m_laminationOffset[l][s],80,m_laminationIdeal[l][s]+m_laminationOffset[l][s]); + lineOffset->SetLineColor(kGreen+2); + lineOffset->SetLineStyle(2); + leg->AddEntry(lineOffset,std::format("#phi_{{ideal}}+#phi_{{offset}}={:.6f}",m_laminationOffset[l][s]).c_str(), "l"); + lineOffset->Draw("same"); + } + lineIdeal->Draw("same"); + + leg->Draw("same"); + + TPaveText *pars = new TPaveText(0.6, 0.55, 0.85, 0.85, "NDC"); - pars->AddText("#phi = #phi_{ideal} + A#times (1 - e^{-C#times (R - B)})"); - pars->AddText(std::format("A={:.3f}#pm {:.3f}", m_fLamination[l][s]->GetParameter(0), m_fLamination[l][s]->GetParError(0)).c_str()); - pars->AddText(std::format("#phi_{{ideal}}={:.3f}#pm {:.3f}", m_fLamination[l][s]->GetParameter(3), m_fLamination[l][s]->GetParError(3)).c_str()); - pars->AddText(std::format("B={:.3f}#pm {:.3f}", m_fLamination[l][s]->GetParameter(1), m_fLamination[l][s]->GetParError(1)).c_str()); - pars->AddText(std::format("C={:.3f}#pm {:.3f}", m_fLamination[l][s]->GetParameter(2), m_fLamination[l][s]->GetParError(2)).c_str()); - pars->AddText(std::format("Distance to line={:.2f}", m_distanceToFit[l][s]).c_str()); - pars->AddText(std::format("Number of Bins used={}", m_nBinsFit[l][s]).c_str()); + if(m_fieldOff) + { + pars->AddText("#phi = #phi_{ideal} + #phi_{offset}"); + pars->AddText(std::format("#phi_{{ideal}}={:.3f}#pm {:.3f}",m_fLamination[l][s]->GetParameter(1), m_fLamination[l][s]->GetParError(1)).c_str()); + pars->AddText(std::format("#phi_{{offset}}={:.3f}#pm {:.3f}", m_fLamination[l][s]->GetParameter(0), m_fLamination[l][s]->GetParError(0)).c_str()); + pars->AddText(std::format("Distance to line={:.2f}", m_distanceToFit[l][s]).c_str()); + pars->AddText(std::format("Number of Bins used={}", m_nBinsFit[l][s]).c_str()); + pars->AddText(std::format("WRMSE={:.2f}", m_fitRMSE[l][s]).c_str()); + } + else + { + pars->AddText("#phi = #phi_{ideal} + A#times (1 - e^{-C#times (R - B)})"); + pars->AddText(std::format("A={:.3f}#pm {:.3f}", m_fLamination[l][s]->GetParameter(0), m_fLamination[l][s]->GetParError(0)).c_str()); + //pars->AddText(std::format("#phi_{{ideal}}=%.3f#pm 0.000", m_laminationIdeal[l][s]).c_str()); + pars->AddText(std::format("#phi_{{nominal}}={:.3f}#pm 0.000", (m_laminationIdeal[l][s]+m_laminationOffset[l][s])).c_str()); + //pars->AddText(std::format("#phi_{{offset}}={:.3f}#pm 0.000", m_laminationOffset[l][s]).c_str()); + pars->AddText(std::format("B={:.3f}#pm {:.3f}", m_fLamination[l][s]->GetParameter(1), m_fLamination[l][s]->GetParError(1)).c_str()); + pars->AddText(std::format("C={:.3f}#pm {:.3f}", m_fLamination[l][s]->GetParameter(2), m_fLamination[l][s]->GetParError(2)).c_str()); + pars->AddText(std::format("Distance to line={:.2f}", m_distanceToFit[l][s]).c_str()); + pars->AddText(std::format("Number of Bins used={}", m_nBinsFit[l][s]).c_str()); + pars->AddText(std::format("WRMSE={:.2f}", m_fitRMSE[l][s]).c_str()); + } pars->Draw("same"); c1->SaveAs(m_QAFileName.c_str()); } @@ -746,80 +1090,105 @@ int TpcLaminationFitting::End(PHCompositeNode * /*topNode*/) c1->SaveAs(std::format("{}]", m_QAFileName).c_str()); } - TFile *simDistortion = new TFile("/cvmfs/sphenix.sdcc.bnl.gov/gcc-12.1.0/release/release_new/new.10/share/calibrations/distortion_maps/average_minus_static_distortion_inverted_10-new.root", "READ"); - TH3 *hIntDistortionP_posz = (TH3 *) simDistortion->Get("hIntDistortionP_posz"); - hIntDistortionP_posz->GetZaxis()->SetRange(2, 2); - TH2 *simPhiDistortion[2]; - simPhiDistortion[1] = (TH2 *) hIntDistortionP_posz->Project3D("yx"); - TH3 *hIntDistortionP_negz = (TH3 *) simDistortion->Get("hIntDistortionP_negz"); - hIntDistortionP_negz->GetZaxis()->SetRange(hIntDistortionP_negz->GetNbinsZ() - 1, hIntDistortionP_negz->GetNbinsZ() - 1); - simPhiDistortion[0] = (TH2 *) hIntDistortionP_negz->Project3D("yx"); - - int interpolateSuccess = InterpolatePhiDistortions(simPhiDistortion); + //TFile *simDistortion = new TFile("/cvmfs/sphenix.sdcc.bnl.gov/gcc-12.1.0/release/release_new/new.10/share/calibrations/distortion_maps/average_minus_static_distortion_inverted_10-new.root", "READ"); + //TH3 *hIntDistortionP_posz = (TH3 *) simDistortion->Get("hIntDistortionP_posz"); + //hIntDistortionP_posz->GetZaxis()->SetRange(2, 2); + //TH2 *simPhiDistortion[2]; + //simPhiDistortion[1] = (TH2 *) hIntDistortionP_posz->Project3D("yx"); + //TH3 *hIntDistortionP_negz = (TH3 *) simDistortion->Get("hIntDistortionP_negz"); + //hIntDistortionP_negz->GetZaxis()->SetRange(hIntDistortionP_negz->GetNbinsZ() - 1, hIntDistortionP_negz->GetNbinsZ() - 1); + //simPhiDistortion[0] = (TH2 *) hIntDistortionP_negz->Project3D("yx"); + + int interpolateSuccess = InterpolatePhiDistortions(); if (interpolateSuccess != Fun4AllReturnCodes::EVENT_OK) { std::cout << PHWHERE << " Return code for lamination interpolation was " << interpolateSuccess << " and not successful" << std::endl; return Fun4AllReturnCodes::ABORTRUN; } - - for (int s = 0; s < 2; s++) - { + + /* + for (int s = 0; s < 2; s++) + { scaleFactorMap[s] = (TH2 *) m_dcc_out->m_hDPint[s]->Clone(); scaleFactorMap[s]->SetName(std::format("scaleFactorMap{}", s).c_str()); scaleFactorMap[s]->Divide(simPhiDistortion[s]); - } - - TH3 *hIntDistortionR_posz = (TH3 *) simDistortion->Get("hIntDistortionR_posz"); - hIntDistortionR_posz->GetZaxis()->SetRange(2, 2); - TH2 *simRDistortion[2]; - simRDistortion[1] = (TH2 *) hIntDistortionR_posz->Project3D("yx"); - TH3 *hIntDistortionR_negz = (TH3 *) simDistortion->Get("hIntDistortionR_negz"); - hIntDistortionR_negz->GetZaxis()->SetRange(hIntDistortionR_negz->GetNbinsZ() - 1, hIntDistortionR_negz->GetNbinsZ() - 1); - simRDistortion[0] = (TH2 *) hIntDistortionR_negz->Project3D("yx"); - + } + + TH3 *hIntDistortionR_posz = (TH3 *) simDistortion->Get("hIntDistortionR_posz"); + hIntDistortionR_posz->GetZaxis()->SetRange(2, 2); + TH2 *simRDistortion[2]; + simRDistortion[1] = (TH2 *) hIntDistortionR_posz->Project3D("yx"); + TH3 *hIntDistortionR_negz = (TH3 *) simDistortion->Get("hIntDistortionR_negz"); + hIntDistortionR_negz->GetZaxis()->SetRange(hIntDistortionR_negz->GetNbinsZ() - 1, hIntDistortionR_negz->GetNbinsZ() - 1); + simRDistortion[0] = (TH2 *) hIntDistortionR_negz->Project3D("yx"); + */ + + + for (int s = 0; s < 2; s++) { - /* - for(int i=1; i<=m_dcc_out->m_hDRint[s]->GetNbinsX(); i++) + int RMatchingSuccess = doGlobalRMatching(s); + if (RMatchingSuccess != Fun4AllReturnCodes::EVENT_OK) { - for(int j=1; j<=m_dcc_out->m_hDRint[s]->GetNbinsY(); j++) - { - if(simRDistortion[s]->GetBinContent(i,j) != 0.0) - { - m_dcc_out->m_hDRint[s]->SetBinContent(i,j, simRDistortion[s]->GetBinContent(i,j)); - } - } + std::cout << PHWHERE << " Return code for doGlobalRMatching was " << RMatchingSuccess << " and not successful" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; } + /* + for(int i=1; i<=m_dcc_out->m_hDRint[s]->GetNbinsX(); i++) + { + for(int j=1; j<=m_dcc_out->m_hDRint[s]->GetNbinsY(); j++) + { + if(simRDistortion[s]->GetBinContent(i,j) != 0.0) + { + m_dcc_out->m_hDRint[s]->SetBinContent(i,j, simRDistortion[s]->GetBinContent(i,j)); + } + } + } */ - m_dcc_out->m_hDRint[s] = (TH2 *) simRDistortion[s]->Clone(); - m_dcc_out->m_hDRint[s]->SetName(std::format("hIntDistortionR{}", (s == 0 ? "_negz" : "_posz")).c_str()); - m_dcc_out->m_hDRint[s]->Multiply(scaleFactorMap[s]); + //m_dcc_out->m_hDRint[s] = (TH2 *) simRDistortion[s]->Clone(); + //m_dcc_out->m_hDRint[s]->SetName(std::format("hIntDistortionR{}", (s == 0 ? "_negz" : "_posz")).c_str()); + //m_dcc_out->m_hDRint[s]->Multiply(scaleFactorMap[s]); } - - + + + fill_guarding_bins(m_dcc_out); - - + + for(int s=0; s<2; s++) { for(int l=0; l<18; l++) { m_side = s; m_lamIndex = s*18 + l; - m_lamPhi = m_laminationCenter[l][s]; + m_lamPhi = m_laminationIdeal[l][s]; + m_lamShift = m_laminationOffset[l][s]; m_goodFit = m_laminationGoodFit[l][s]; - m_A = m_fLamination[l][s]->GetParameter(0); - m_B = m_fLamination[l][s]->GetParameter(1); - m_C = m_fLamination[l][s]->GetParameter(2); - m_A_err = m_fLamination[l][s]->GetParError(0); - m_B_err = m_fLamination[l][s]->GetParError(1); - m_C_err = m_fLamination[l][s]->GetParError(2); + if(m_fieldOff) + { + m_A = m_fLamination[l][s]->GetParameter(0); + m_A_err = m_fLamination[l][s]->GetParError(0); + m_B = -999; + m_B_err = -999; + m_C = -999; + m_C_err = -999; + } + else + { + m_A = m_fLamination[l][s]->GetParameter(0); + m_B = m_fLamination[l][s]->GetParameter(1); + m_C = m_fLamination[l][s]->GetParameter(2); + m_A_err = m_fLamination[l][s]->GetParError(0); + m_B_err = m_fLamination[l][s]->GetParError(1); + m_C_err = m_fLamination[l][s]->GetParError(2); + } m_dist = m_distanceToFit[l][s]; m_nBins = m_nBinsFit[l][s]; + m_rmse = m_fitRMSE[l][s]; m_laminationTree->Fill(); } } - + TFile *outputfile = new TFile(m_outputfile.c_str(), "RECREATE"); outputfile->cd(); for (int s = 0; s < 2; s++) @@ -832,17 +1201,36 @@ int TpcLaminationFitting::End(PHCompositeNode * /*topNode*/) } } phiDistortionLamination[s]->Write(); - scaleFactorMap[s]->Write(); + //scaleFactorMap[s]->Write(); + m_hPetal[s]->Write(); + if(m_bestRMatch[s]) + { + m_bestRMatch[s]->Write(); + } + m_parameterScan[s]->Write(); } m_laminationTree->Write(); - - m_hLamination[13][0]->Write(); - m_hLamination[13][1]->Write(); - m_hLamination[14][1]->Write(); - + + if(m_saveAllLaminationHistograms) + { + for(auto &i : m_hLamination) + { + for(auto &j : i) + { + j->Write(); + } + } + } + else + { + m_hLamination[13][0]->Write(); + m_hLamination[13][1]->Write(); + m_hLamination[14][1]->Write(); + } + outputfile->Close(); - + return Fun4AllReturnCodes::EVENT_OK; } @@ -851,7 +1239,7 @@ void TpcLaminationFitting::fill_guarding_bins(TpcDistortionCorrectionContainer * { for (int s = 0; s < 2; s++) { - for (const auto &h : {dcc->m_hDRint[s], dcc->m_hDPint[s]}) + for (const auto &h : {dcc->m_hDPint[s], dcc->m_hDRint[s]}) { const auto phibins = h->GetNbinsX(); const auto rbins = h->GetNbinsY(); diff --git a/offline/packages/tpccalib/TpcLaminationFitting.h b/offline/packages/tpccalib/TpcLaminationFitting.h index 73d77533d3..5285dff0d2 100644 --- a/offline/packages/tpccalib/TpcLaminationFitting.h +++ b/offline/packages/tpccalib/TpcLaminationFitting.h @@ -43,8 +43,19 @@ class TpcLaminationFitting : public SubsysReco m_QAFileName = QAFileName; } + void set_stripePatternFile(const std::string &stripePatternFile) + { + m_stripePatternFile = stripePatternFile; + } + void set_ppMode(bool mode){ ppMode = mode; } - + + void set_phiHistInRad(bool rad){ m_phiHist_in_rad = rad; } + + void set_saveAllLaminationHistograms(bool save){ m_saveAllLaminationHistograms = save; } + + void set_fieldOff(bool fieldOff){ m_fieldOff = fieldOff; } + void set_grid_dimensions(int phibins, int rbins); void set_nLayerCut(unsigned int cut) { m_nLayerCut = cut; } @@ -61,7 +72,8 @@ class TpcLaminationFitting : public SubsysReco int GetNodes(PHCompositeNode *topNode); int fitLaminations(); - int InterpolatePhiDistortions(TH2 *simPhiDistortion[2]); + int InterpolatePhiDistortions(); + int doGlobalRMatching(int side); void fill_guarding_bins(TpcDistortionCorrectionContainer *dcc); TpcDistortionCorrection m_distortionCorrection; @@ -78,14 +90,24 @@ class TpcLaminationFitting : public SubsysReco TH2 *m_hLamination[18][2]{{nullptr}}; TF1 *m_fLamination[18][2]{{nullptr}}; - double m_laminationCenter[18][2]{{0.0}}; + double m_laminationIdeal[18][2]{{0.0}}; + //double m_laminationCenter[18][2]{{0.0}}; double m_laminationOffset[18][2]{{0.0}}; + //double m_laminationOffset{0.00337078}; + //double m_laminationOffset{0.002775}; bool m_laminationGoodFit[18][2]{{false}}; double m_distanceToFit[18][2]{{0.0}}; int m_nBinsFit[18][2]{{0}}; + double m_fitRMSE[18][2]{{0.0}}; + + + TH2 *m_hPetal[2]{nullptr}; + TGraph *m_bestRMatch[2]{nullptr}; + TH2 *m_parameterScan[2]{nullptr}; + TH2 *phiDistortionLamination[2]{nullptr}; - TH2 *scaleFactorMap[2]{nullptr}; + //TH2 *scaleFactorMap[2]{nullptr}; unsigned int m_nLayerCut{1}; @@ -102,11 +124,19 @@ class TpcLaminationFitting : public SubsysReco double m_ZDC_coincidence{0}; //std::map m_run_ZDC_map_pp; //std::map m_run_ZDC_map_auau; - + + bool m_phiHist_in_rad{true}; + bool m_saveAllLaminationHistograms{false}; + + std::string m_stripePatternFile = "/sphenix/u/bkimelman/CMStripePattern.root"; + + bool m_fieldOff{false}; + TTree *m_laminationTree{nullptr}; bool m_side{false}; int m_lamIndex{0}; double m_lamPhi{0}; + double m_lamShift{0}; bool m_goodFit{false}; double m_A{0}; double m_B{0}; @@ -115,15 +145,38 @@ class TpcLaminationFitting : public SubsysReco double m_B_err{0}; double m_C_err{0}; double m_dist{0}; + double m_rmse{}; int m_nBins{0}; - int m_phibins{24}; + int m_phibins{80}; static constexpr float m_phiMin{0}; static constexpr float m_phiMax{2. * M_PI}; - int m_rbins{12}; + int m_rbins{52}; static constexpr float m_rMin{20}; // cm static constexpr float m_rMax{80}; // cm + + /* + const int nRadii{8}; + const int nStripes[4]{6,6,8,12}; + const int nPads[4]{96,96,128,192}; + const double RValues[4][8] = {{22.70902789, 23.84100043, 24.97297296, 26.1049455, 27.23691804, 28.36889058, 29.50086312, 30.63283566},{31.7648082, 32.89678074, 34.02875328, 35.16072582, 36.29269836, 37.4246709, 38.55664344, 39.68861597},{42.1705532, 44.2119258, 46.2532984, 48.29467608, 50.336069, 52.3774416, 54.4188015, 56.4601868},{59.46048725, 61.6545823, 63.84867738, 66.04277246, 68.23686754, 70.43096262, 72.6250577, 74.81915277}}; + + const int keepThisAndAfter[8]{1,0,1,0,1,0,1,0}; + const int keepUntil[4][8]{{4,4,5,4,5,5,5,5},{5,5,6,5,6,5,6,5},{7,7,8,7,8,8,8,8},{11,10,11,11,11,11,12,11}}; + + const double phi_petal = M_PI/6.0; + const int pr_mult = 3; + const int dw_mult = 8; + const double diffwidth = 0.06; + const double adjust = 0.015; + */ + + std::vector m_truthR[2]; + std::vector m_truthPhi[2]; + + double m_phiModMin[2]{-M_PI/18, 0.0}; + double m_phiModMax[2]{M_PI/18, M_PI/9}; }; #endif diff --git a/offline/packages/trackbase/AlignmentTransformation.cc b/offline/packages/trackbase/AlignmentTransformation.cc index b3eb79fcb0..2e8647ab01 100644 --- a/offline/packages/trackbase/AlignmentTransformation.cc +++ b/offline/packages/trackbase/AlignmentTransformation.cc @@ -277,6 +277,7 @@ void AlignmentTransformation::createMap(PHCompositeNode* topNode) surf = surfMaps.getTpcSurface(this_hitsetkey, (unsigned int) sskey); Eigen::Vector3d localFrameTranslation(0, 0, 0); + use_module_tilt = false; if (test_layer < 4 || use_module_tilt_always) { // get the local frame translation that puts the local surface center at the tilted position after the local rotations are applied @@ -285,6 +286,9 @@ void AlignmentTransformation::createMap(PHCompositeNode* topNode) double this_radius = std::sqrt(this_center[0] * this_center[0] + this_center[1] * this_center[1]); float moduleRadius = TpcModuleRadii[side][sector][this_region]; // radius of the center of the module in cm localFrameTranslation = getTpcLocalFrameTranslation(moduleRadius, this_radius, sensorAngles) * 10; // cm to mm + + // set this flag for later use + use_module_tilt = true; } Acts::Transform3 transform; @@ -417,70 +421,83 @@ Acts::Transform3 AlignmentTransformation::newMakeTransform(const Surface& surf, Acts::Transform3 transform; //! If we read the survey parameters directly, that is the full transform if (survey) - { - //! The millepede affines will just be what was read in, which was the - //! survey information. This should (in principle) be equivalent to - //! the ideal position + any misalignment - transform = mpGlobalTranslationAffine * mpGlobalRotationAffine * mpLocalRotationAffine; - } - else - { - if (trkrid == TrkrDefs::tpcId) { - transform = mpGlobalTranslationAffine * mpGlobalRotationAffine * actsTranslationAffine * actsRotationAffine * mpLocalTranslationAffine * mpLocalRotationAffine; + //! The millepede affines will just be what was read in, which was the + //! survey information. This should (in principle) be equivalent to + //! the ideal position + any misalignment + transform = mpGlobalTranslationAffine * mpGlobalRotationAffine * mpLocalRotationAffine; } - else + else { - if(use_new_silicon_rotation_order) + // not survey. this is the normal usage + + if (trkrid == TrkrDefs::tpcId) { - transform = mpGlobalTranslationAffine * mpGlobalRotationAffine * actsTranslationAffine * actsRotationAffine * mpLocalTranslationAffine * mpLocalRotationAffine; + if(use_module_tilt) + { + // use module tilt transforms with local rotation followed by local translation + transform = mpGlobalTranslationAffine * mpGlobalRotationAffine * actsTranslationAffine * actsRotationAffine * mpLocalTranslationAffine * mpLocalRotationAffine; + } + else + { + // backward compatibility for old alignment params sets + transform = mpGlobalTranslationAffine * mpGlobalRotationAffine * actsTranslationAffine * mpLocalRotationAffine * actsRotationAffine; + } } else { - // needed for backward compatibility to existing local rotations in MVTX - transform = mpGlobalTranslationAffine * mpGlobalRotationAffine * actsTranslationAffine * mpLocalRotationAffine * actsRotationAffine; + // silicon and TPOT + if(use_new_silicon_rotation_order) + { + // use new transform order for silicon as well as TPC + transform = mpGlobalTranslationAffine * mpGlobalRotationAffine * actsTranslationAffine * actsRotationAffine * mpLocalTranslationAffine * mpLocalRotationAffine; + } + else + { + // needed for backward compatibility to existing local rotation parmeter sets in silicon + transform = mpGlobalTranslationAffine * mpGlobalRotationAffine * actsTranslationAffine * mpLocalRotationAffine * actsRotationAffine; + } } } - } - + if (localVerbosity) - { - Acts::Transform3 actstransform = actsTranslationAffine * actsRotationAffine; - - std::cout << "newMakeTransform" << std::endl; - std::cout << "Input sensorAngles: " << std::endl - << sensorAngles << std::endl; - std::cout << "Input sensorAnglesGlobal: " << std::endl - << sensorAnglesGlobal << std::endl; - std::cout << "Input translation: " << std::endl - << millepedeTranslation << std::endl; - std::cout << "mpLocalRotationAffine: " << std::endl - << mpLocalRotationAffine.matrix() << std::endl; - std::cout << "mpLocalTranslationAffine: " << std::endl - << mpLocalTranslationAffine.matrix() << std::endl; - std::cout << "actsRotationAffine: " << std::endl - << actsRotationAffine.matrix() << std::endl; - std::cout << "actsTranslationAffine: " << std::endl - << actsTranslationAffine.matrix() << std::endl; - std::cout << "mpRotationGlobalAffine: " << std::endl - << mpGlobalRotationAffine.matrix() << std::endl; - std::cout << "mpTranslationGlobalAffine: " << std::endl - << mpGlobalTranslationAffine.matrix() << std::endl; - std::cout << "Overall transform: " << std::endl - << transform.matrix() << std::endl; - std::cout << "overall * idealinv " << std::endl - << (transform * actstransform.inverse()).matrix() << std::endl; - std::cout << "overall - ideal " << std::endl; - for (int test = 0; test < transform.matrix().rows(); test++) { - for (int test2 = 0; test2 < transform.matrix().cols(); test2++) - { - std::cout << transform(test, test2) - actstransform(test, test2) << ", "; - } - std::cout << std::endl; + Acts::Transform3 actstransform = actsTranslationAffine * actsRotationAffine; + + std::cout << "newMakeTransform" << std::endl; + std::cout << "Input sensorAngles: " << std::endl + << sensorAngles << std::endl; + std::cout << "Input sensorAnglesGlobal: " << std::endl + << sensorAnglesGlobal << std::endl; + std::cout << "Input translation: " << std::endl + << millepedeTranslation << std::endl; + std::cout << "mpLocalRotationAffine: " << std::endl + << mpLocalRotationAffine.matrix() << std::endl; + std::cout << "mpLocalTranslationAffine: " << std::endl + << mpLocalTranslationAffine.matrix() << std::endl; + std::cout << "actsRotationAffine: " << std::endl + << actsRotationAffine.matrix() << std::endl; + std::cout << "actsTranslationAffine: " << std::endl + << actsTranslationAffine.matrix() << std::endl; + std::cout << "mpRotationGlobalAffine: " << std::endl + << mpGlobalRotationAffine.matrix() << std::endl; + std::cout << "mpTranslationGlobalAffine: " << std::endl + << mpGlobalTranslationAffine.matrix() << std::endl; + std::cout << "Overall transform: " << std::endl + << transform.matrix() << std::endl; + std::cout << "overall * idealinv " << std::endl + << (transform * actstransform.inverse()).matrix() << std::endl; + std::cout << "overall - ideal " << std::endl; + for (int test = 0; test < transform.matrix().rows(); test++) + { + for (int test2 = 0; test2 < transform.matrix().cols(); test2++) + { + std::cout << transform(test, test2) - actstransform(test, test2) << ", "; + } + std::cout << std::endl; + } } - } - + return transform; } diff --git a/offline/packages/trackbase/AlignmentTransformation.h b/offline/packages/trackbase/AlignmentTransformation.h index 7055d6c65a..e8eb3882d1 100644 --- a/offline/packages/trackbase/AlignmentTransformation.h +++ b/offline/packages/trackbase/AlignmentTransformation.h @@ -128,7 +128,8 @@ class AlignmentTransformation bool use_new_silicon_rotation_order = false; bool use_module_tilt_always = false; - + bool use_module_tilt = false; // starts at false in all cases + bool use_intt_survey_geometry = false; Acts::Transform3 newMakeTransform(const Surface& surf, Eigen::Vector3d& millepedeTranslation, Eigen::Vector3d& sensorAngles, Eigen::Vector3d& localFrameTranslation, Eigen::Vector3d& sensorAnglesGlobal, unsigned int trkrid, bool survey); diff --git a/offline/packages/trackbase/ClusterErrorPara.cc b/offline/packages/trackbase/ClusterErrorPara.cc index cb62ed10f5..f45a59b14b 100644 --- a/offline/packages/trackbase/ClusterErrorPara.cc +++ b/offline/packages/trackbase/ClusterErrorPara.cc @@ -1,7 +1,8 @@ #include "ClusterErrorPara.h" #include "TrkrCluster.h" - +//#include +#include #include #include @@ -18,58 +19,96 @@ namespace { return x * x; } + } // namespace -ClusterErrorPara::ClusterErrorPara() +ClusterErrorPara::ClusterErrorPara(): + f0{new TF1("f0", "pol1", 0, 10)}, + f1{new TF1("f1", "pol2", 0, 10)}, + f2{new TF1("f2", "pol2", 0, 10)}, + f0fine{new TF1("f0fine", "pol2", 0, 20000)}, + f1fine{new TF1("f1fine", "pol3", 0, 20000)}, + f2fine{new TF1("f2fine", "pol5", 0, 20000)}, + f2fine2{new TF1("f2fine", "pol5", 0, 20000)}, + fz0{new TF1("fz0", "pol2", -2, 2)}, + fz1{new TF1("fz1", "pol4", -2, 2)}, + fz2{new TF1("fz2", "pol2", -2, 2)}, + fz0fine{new TF1("fz0fine", "pol2", 0, 20000)}, + fz1fine{new TF1("fz1fine", "pol3", 0, 20000)}, + fz2fine{new TF1("fz2fine", "pol5", 0, 20000)}, + fmm_55_2{new TF1("fmm_55_2", "pol2", -2, 2)}, + fmm_56_2{new TF1("fmm_56_2", "pol2", -2, 2)}, + fmm_3{new TF1("fmm_3", "pol2", -2, 2)}, + fadcz0{new TF1("fadcz0", "pol5", 0, 20000)}, + fadcz1{new TF1("fadcz1", "pol5", 0, 20000)}, + fadcz2{new TF1("fadcz2", "pol5", 0, 20000)}, + fadcz0fine{new TF1("fadcz0fine", "[0]+([1]/pow(x-[2],2))", 0, 20000)}, + fadcz1fine{new TF1("fadcz1fine", "[0]+([1]/pow(x-[2],2))", 0, 20000)}, + fadcz2fine{new TF1("fadcz2fine", "[0]+([1]/pow(x-[2],2))", 0, 20000)}, + fadcphi0{new TF1("fadcphi0", "pol4", 0, 20000)}, + fadcphi0fine{new TF1("fadcphi0fine", "pol2", 0, 20000)}, + fadcphi1{new TF1("fadcphi1", "pol4", 0, 20000)}, + fadcphi1fine{new TF1("fadcphi1fine", "pol4", 0, 20000)}, + fadcphi2{new TF1("fadcphi2", "pol5", 0, 20000)}, + fadcphi2fine1{new TF1("fadcphi2fine1", "pol4", 0, 20000)}, + fadcphi2fine2{new TF1("fadcphi2fine2", "pol1", 0, 20000)} + { - f0 = new TF1("f0", "pol1", 0, 10); + /* + ftpcR1 = new TF1("ftpcR1", "pol2", 0, 10); + ftpcR1->SetParameter(0, 3.206); + ftpcR1->SetParameter(1, -0.252); + ftpcR1->SetParameter(2, 0.007); + */ + + // f0 = new TF1("f0", "pol1", 0, 10); f0->SetParameter(0, 0.0163943); f0->SetParameter(1, 0.0192931); - f1 = new TF1("f1", "pol2", 0, 10); + // f1 = new TF1("f1", "pol2", 0, 10); f1->SetParameter(0, 0.0119384); f1->SetParameter(1, 0.0253197); f1->SetParameter(2, 0.0404213); - f2 = new TF1("f2", "pol2", 0, 10); + // f2 = new TF1("f2", "pol2", 0, 10); f2->SetParameter(0, 0.0107316); f2->SetParameter(1, 0.0294968); f2->SetParameter(2, 0.0414098); // f2->SetParameter(3,9.75877); - fz0 = new TF1("fz0", "pol2", -2, 2); + // fz0 = new TF1("fz0", "pol2", -2, 2); fz0->SetParameter(0, 0.0520278); fz0->SetParameter(1, -0.00578699); fz0->SetParameter(2, 0.0156972); - fz1 = new TF1("fz1", "pol4", -2, 2); + // fz1 = new TF1("fz1", "pol4", -2, 2); fz1->SetParameter(0, 0.0383233); fz1->SetParameter(1, -0.00577128); fz1->SetParameter(2, 0.0770914); fz1->SetParameter(3, -0.0818139); fz1->SetParameter(4, 0.050305); - fz2 = new TF1("fz2", "pol2", -2, 2); + // fz2 = new TF1("fz2", "pol2", -2, 2); fz2->SetParameter(0, 0.0371611); fz2->SetParameter(1, -0.000694558); fz2->SetParameter(2, 0.0437917); - fmm_55_2 = new TF1("fmm_55_2", "pol2", -2, 2); + // fmm_55_2 = new TF1("fmm_55_2", "pol2", -2, 2); fmm_55_2->SetParameter(0, 0.0430592); fmm_55_2->SetParameter(1, -0.000177174); fmm_55_2->SetParameter(2, 0.0914288); - fmm_56_2 = new TF1("fmm_56_2", "pol2", -2, 2); + // fmm_56_2 = new TF1("fmm_56_2", "pol2", -2, 2); fmm_56_2->SetParameter(0, 0.00363897); fmm_56_2->SetParameter(1, 0.0109713); fmm_56_2->SetParameter(2, 0.032354); - fmm_3 = new TF1("fmm_3", "pol2", -2, 2); + // fmm_3 = new TF1("fmm_3", "pol2", -2, 2); fmm_3->SetParameter(0, 0.00305396); fmm_3->SetParameter(1, 0.00505814); fmm_3->SetParameter(2, 0.0395137); - fadcz0 = new TF1("fadcz0", "pol5", 0, 20000); + // fadcz0 = new TF1("fadcz0", "pol5", 0, 20000); fadcz0->SetParameter(0, 2.08854); fadcz0->SetParameter(1, -0.0536847); fadcz0->SetParameter(2, 0.000989393); @@ -77,7 +116,7 @@ ClusterErrorPara::ClusterErrorPara() fadcz0->SetParameter(4, 4.42178e-08); fadcz0->SetParameter(5, -7.79669e-11); - fadcz1 = new TF1("fadcz1", "pol5", 0, 20000); + // fadcz1 = new TF1("fadcz1", "pol5", 0, 20000); fadcz1->SetParameter(0, 2.35278); fadcz1->SetParameter(1, -0.0535903); fadcz1->SetParameter(2, 0.00088052); @@ -85,7 +124,7 @@ ClusterErrorPara::ClusterErrorPara() fadcz1->SetParameter(4, 3.35361e-08); fadcz1->SetParameter(5, -5.61371e-11); - fadcz2 = new TF1("fadcz2", "pol5", 0, 20000); + // fadcz2 = new TF1("fadcz2", "pol5", 0, 20000); fadcz2->SetParameter(0, 2.53191); fadcz2->SetParameter(1, -0.062285); fadcz2->SetParameter(2, 0.00103893); @@ -93,22 +132,22 @@ ClusterErrorPara::ClusterErrorPara() fadcz2->SetParameter(4, 3.9802e-08); fadcz2->SetParameter(5, -6.67137e-11); - fadcz0fine = new TF1("fadcz0fine", "[0]+([1]/pow(x-[2],2))", 0, 20000); + // fadcz0fine = new TF1("fadcz0fine", "[0]+([1]/pow(x-[2],2))", 0, 20000); fadcz0fine->SetParameter(0, 9.63983e-01); fadcz0fine->SetParameter(1, 2.68585e+01); fadcz0fine->SetParameter(2, -4.78664e+00); - fadcz1fine = new TF1("fadcz1fine", "[0]+([1]/pow(x-[2],2))", 0, 20000); + // fadcz1fine = new TF1("fadcz1fine", "[0]+([1]/pow(x-[2],2))", 0, 20000); fadcz1fine->SetParameter(0, 9.85546e-01); fadcz1fine->SetParameter(1, 1.12622e+02); fadcz1fine->SetParameter(2, -1.26552e+01); - fadcz2fine = new TF1("fadcz2fine", "[0]+([1]/pow(x-[2],2))", 0, 20000); + // fadcz2fine = new TF1("fadcz2fine", "[0]+([1]/pow(x-[2],2))", 0, 20000); fadcz2fine->SetParameter(0, 9.71125e-01); fadcz2fine->SetParameter(1, 6.67244e+01); fadcz2fine->SetParameter(2, -3.55034e+00); - fadcphi0 = new TF1("fadcphi0", "pol4", 0, 20000); + // fadcphi0 = new TF1("fadcphi0", "pol4", 0, 20000); fadcphi0->SetParameter(0, 1.79273); fadcphi0->SetParameter(1, -0.0306044); fadcphi0->SetParameter(2, 0.000355984); @@ -116,26 +155,26 @@ ClusterErrorPara::ClusterErrorPara() fadcphi0->SetParameter(4, 4.26161e-09); // fadcphi0->SetParameter(5,-4.22758e-11); - fadcphi0fine = new TF1("fadcphi0fine", "pol2", 0, 20000); + // fadcphi0fine = new TF1("fadcphi0fine", "pol2", 0, 20000); fadcphi0fine->SetParameter(0, 1.02625); fadcphi0fine->SetParameter(1, -0.00167294); fadcphi0fine->SetParameter(2, 2.2912e-5); - fadcphi1 = new TF1("fadcphi1", "pol4", 0, 20000); + // fadcphi1 = new TF1("fadcphi1", "pol4", 0, 20000); fadcphi1->SetParameter(0, 2.12873); fadcphi1->SetParameter(1, -0.0369604); fadcphi1->SetParameter(2, 0.00042828); fadcphi1->SetParameter(3, -2.3665e-06); fadcphi1->SetParameter(4, 4.87683e-09); - fadcphi1fine = new TF1("fadcphi1fine", "pol4", 0, 20000); + // fadcphi1fine = new TF1("fadcphi1fine", "pol4", 0, 20000); fadcphi1fine->SetParameter(0, 1.11749); fadcphi1fine->SetParameter(1, -0.00354277); fadcphi1fine->SetParameter(2, 5.60236e-05); fadcphi1fine->SetParameter(3, -4.46412e-07); fadcphi1fine->SetParameter(4, 1.22689e-09); - fadcphi2 = new TF1("fadcphi2", "pol5", 0, 20000); + // fadcphi2 = new TF1("fadcphi2", "pol5", 0, 20000); fadcphi2->SetParameter(0, 2.29); fadcphi2->SetParameter(1, -0.0474362); fadcphi2->SetParameter(2, 0.000717789); @@ -143,23 +182,23 @@ ClusterErrorPara::ClusterErrorPara() fadcphi2->SetParameter(4, 2.52007e-08); fadcphi2->SetParameter(5, -4.14747e-11); - fadcphi2fine1 = new TF1("fadcphi2fine1", "pol4", 0, 20000); + // fadcphi2fine1 = new TF1("fadcphi2fine1", "pol4", 0, 20000); fadcphi2fine1->SetParameter(0, 1.39404); fadcphi2fine1->SetParameter(1, -0.0202245); fadcphi2fine1->SetParameter(2, 0.000394666); fadcphi2fine1->SetParameter(3, -3.37831e-06); fadcphi2fine1->SetParameter(4, 1.05017e-08); - fadcphi2fine2 = new TF1("fadcphi2fine2", "pol1", 0, 20000); + // fadcphi2fine2 = new TF1("fadcphi2fine2", "pol1", 0, 20000); fadcphi2fine2->SetParameter(0, 0.997); fadcphi2fine2->SetParameter(1, 0.00047); - f0fine = new TF1("f0fine", "pol2", 0, 20000); + // f0fine = new TF1("f0fine", "pol2", 0, 20000); f0fine->SetParameter(0, 0.98611); f0fine->SetParameter(1, -0.169505); f0fine->SetParameter(2, 1.12907); - f1fine = new TF1("f1fine", "pol3", 0, 20000); + // f1fine = new TF1("f1fine", "pol3", 0, 20000); f1fine->SetParameter(0, 0.968625); f1fine->SetParameter(1, -0.38894); f1fine->SetParameter(2, 3.36493); @@ -172,7 +211,7 @@ ClusterErrorPara::ClusterErrorPara() f2fine->SetParameter(3,-42.4668); f2fine->SetParameter(4,43.6083); */ - f2fine = new TF1("f2fine", "pol5", 0, 20000); + // f2fine = new TF1("f2fine", "pol5", 0, 20000); f2fine->SetLineColor(kBlue); f2fine->SetParameter(0, 1.14119); f2fine->SetParameter(1, -2.81483); @@ -181,18 +220,18 @@ ClusterErrorPara::ClusterErrorPara() f2fine->SetParameter(4, 72.2359); f2fine->SetParameter(5, -20.3802); - fz0fine = new TF1("fz0fine", "pol2", 0, 20000); + // fz0fine = new TF1("fz0fine", "pol2", 0, 20000); fz0fine->SetParameter(0, 0.96933); fz0fine->SetParameter(1, -0.0458534); fz0fine->SetParameter(2, 0.231419); - fz1fine = new TF1("fz1fine", "pol3", 0, 20000); + // fz1fine = new TF1("fz1fine", "pol3", 0, 20000); fz1fine->SetParameter(0, 0.886262); fz1fine->SetParameter(1, -0.0818167); fz1fine->SetParameter(2, 0.805824); fz1fine->SetParameter(3, -0.425423); - fz2fine = new TF1("fz2fine", "pol5", 0, 20000); + // fz2fine = new TF1("fz2fine", "pol5", 0, 20000); fz2fine->SetLineColor(kBlue); fz2fine->SetParameter(0, 0.880153); fz2fine->SetParameter(1, 0.552461); @@ -476,40 +515,258 @@ ClusterErrorPara::ClusterErrorPara() //_________________________________________________________________________________ ClusterErrorPara::error_t ClusterErrorPara::get_clusterv5_modified_error(TrkrCluster* cluster, double /*unused*/, TrkrDefs::cluskey key) { + + static const bool is_data_reco = []() { + recoConsts* rc = recoConsts::instance(); + if (rc->FlagExist("CDB_GLOBALTAG")) + { + if (rc->get_StringFlag("CDB_GLOBALTAG").find("MDC") != std::string::npos) + { + return false; + } + } + return true; // default to data + }(); + /* + static bool is_data_reco{true}; // default to data + static bool is_data_reco_set{false}; // default to data + if(!is_data_reco_set){ + recoConsts* rc = recoConsts::instance(); + if(rc->FlagExist("CDB_GLOBALTAG")) + { + if(rc->get_StringFlag("CDB_GLOBALTAG").find("MDC") != std::string::npos) + { + is_data_reco = false; + } + } + is_data_reco_set = true; + } + */ int layer = TrkrDefs::getLayer(key); double phierror = cluster->getRPhiError(); double zerror = cluster->getZError(); - if (TrkrDefs::getTrkrId(key) == TrkrDefs::tpcId) - { - if (layer == 7 || layer == 22 || layer == 23 || layer == 38 || layer == 39) - { - phierror *= 4; - zerror *= 4; - } - if (cluster->getEdge() >= 3) - { - phierror *= 4; - } - if (cluster->getOverlap() >= 2) - { - phierror *= 2; - } - if (cluster->getPhiSize() == 1) - { - phierror *= 10; + + if(is_data_reco==false){ + if (TrkrDefs::getTrkrId(key) == TrkrDefs::tpcId) + { + if (layer == 7 || layer == 22 || layer == 23 || layer == 38 || layer == 39) + { + phierror *= 4; + zerror *= 4; + } + if (cluster->getEdge() >= 3) + { + phierror *= 4; + } + if (cluster->getOverlap() >= 2) + { + phierror *= 2; + } + if (cluster->getPhiSize() == 1) + { + phierror *= 10; + } + if (cluster->getPhiSize() >= 5) + { + phierror *= 10; + } + + phierror = std::min(phierror, 0.1); + if (phierror < 0.0005) + { + phierror = 0.1; + } + } + }else{ + + if (TrkrDefs::getTrkrId(key) == TrkrDefs::tpcId) + { + if (layer == 7 || layer == 22 || layer == 23 || layer == 38 || layer == 39 || layer == 54) + { + phierror *= 4; + zerror *= 4; + } + if (cluster->getEdge() >= 3) + { + phierror *= 4; + } + if (cluster->getOverlap() >= 2) + { + phierror *= 2; + } + if(layer>=7&&layer<(7+48)){ + //Set phi error + if (cluster->getPhiSize() == 1) + { + phierror *= 1.0; + } + if (cluster->getPhiSize() == 2) + { + phierror*=3.15; + } + if (cluster->getPhiSize() == 3) + { + phierror *=3.5; + } + if (cluster->getPhiSize() >3) + { + phierror *= 4; + } + //Set Z Error + if (cluster->getZSize() == 1){ + zerror*=1.0; + } + if (cluster->getZSize() == 2){ + if(layer>=7&&layer<(7+16)){ + zerror*=7; + } + if(layer>=(7+16)&&layer<(7+32)){ + zerror*=4.5; + } + if(layer>=(7+32)&&layer<(7+48)){ + zerror*=4.5; + } + + } + if ((cluster->getZSize() == 3) || (cluster->getZSize() == 4)){ + if(layer>=7&&layer<(7+16)){ + zerror*=7; + } + if(layer>=(7+16)&&layer<(7+32)){ + zerror*=5; + } + if(layer>=(7+32)&&layer<(7+48)){ + zerror*=5; + } + // zerror*=6; + } + if (cluster->getZSize() >=5){ + if(layer>=7&&layer<(7+16)){ + zerror*=20; + } + if(layer>=(7+16)&&layer<(7+32)){ + zerror*=6; + } + if(layer>=(7+32)&&layer<(7+48)){ + zerror*=7; + } + } + /* + static TF1 ftpcR1("ftpcR1", "pol2", 0, 60); + ftpcR1.SetParameter(0, 3.206); + ftpcR1.SetParameter(1, -0.252); + ftpcR1.SetParameter(2, 0.007); + + static TF1 ftpcR2("ftpcR2", "pol2", 0, 60); + ftpcR2.SetParameter(0, 4.48); + ftpcR2.SetParameter(1, -0.226); + ftpcR2.SetParameter(2, 0.00362); + + static TF1 ftpcR3("ftpcR3", "pol2", 0, 60); + ftpcR3.SetParameter(0, 14.8112); + ftpcR3.SetParameter(1, -0.577); + ftpcR3.SetParameter(2, 0.00605); + + if(layer>=7&&layer<(7+16)){ + phierror*= ftpcR1.Eval(layer); + } + if(layer>=(7+16)&&layer<(7+32)){ + phierror*= ftpcR2.Eval(layer); + } + if(layer>=(7+32)&&layer<(7+48)){ + phierror*= ftpcR3.Eval(layer); + } + ftpcR2.SetParameter(0, 5.593); + ftpcR2.SetParameter(1, -0.2458); + ftpcR2.SetParameter(2, 0.00333455); + + ftpcR3.SetParameter(0, 5.6964); + ftpcR3.SetParameter(1, -0.21338); + ftpcR3.SetParameter(2, 0.002502); + + if(layer>=(7+16)&&layer<(7+32)){ + zerror*= ftpcR2.Eval(layer); + } + if(layer>=(7+32)&&layer<(7+48)){ + zerror*= ftpcR3.Eval(layer); + } + */ + + // Inline pol2 evaluation: p0 + p1*x + p2*x^2 + auto pol2 = [](double x, double p0, double p1, double p2) { + return p0 + p1 * x + p2 * x * x; + }; + + if(layer>=7&&layer<(7+16)){ + phierror *= pol2(layer, 3.206, -0.252, 0.007); + } + if(layer>=(7+16)&&layer<(7+32)){ + phierror *= pol2(layer, 4.48, -0.226, 0.00362); + } + if(layer>=(7+32)&&layer<(7+48)){ + phierror *= pol2(layer, 14.8112, -0.577, 0.00605); + } + + if(layer>=(7+16)&&layer<(7+32)){ + zerror *= pol2(layer, 5.593, -0.2458, 0.00333455); + } + if(layer>=(7+32)&&layer<(7+48)){ + zerror *= pol2(layer, 5.6964, -0.21338, 0.002502); + } + } + if (cluster->getPhiSize() >= 5) + { + phierror *= 10; + } + } + + if (TrkrDefs::getTrkrId(key) == TrkrDefs::mvtxId){ + phierror*=2; + zerror*=2; + } - if (cluster->getPhiSize() >= 5) - { - phierror *= 10; + + if (TrkrDefs::getTrkrId(key) == TrkrDefs::inttId){ + phierror*=9; + if (cluster->getPhiSize() == 1){ + phierror *= 1.25; + } + if (cluster->getPhiSize() == 2){ + phierror *= 2.25; + } + if((layer==3)||(layer==4)){ + phierror*=0.8; + } + if((layer==5)||(layer==6)){ + phierror*=1.2; + } } + + if (TrkrDefs::getTrkrId(key) == TrkrDefs::micromegasId){ + if(layer==55){ + /* + phierror*=5.4; + phierror*=4.6; + phierror*=3.0; + zerror*=0.82; + */ + phierror = 0.0289; + } + + if(layer==56){ + /* + phierror*=0.9; + phierror*=0.95; + zerror*=4.5; + zerror*=3.4; + */ + zerror = 0.577; + } - phierror = std::min(phierror, 0.1); - if (phierror < 0.0005) - { - phierror = 0.1; } } + return std::make_pair(square(phierror), square(zerror)); } diff --git a/offline/packages/trackbase/ClusterErrorPara.h b/offline/packages/trackbase/ClusterErrorPara.h index b125858217..39001d352c 100644 --- a/offline/packages/trackbase/ClusterErrorPara.h +++ b/offline/packages/trackbase/ClusterErrorPara.h @@ -17,6 +17,7 @@ class ClusterErrorPara virtual ~ClusterErrorPara() { + //delete ftpcR1; delete f0; delete f1; delete f2; @@ -71,6 +72,7 @@ class ClusterErrorPara double tpc_z_error(int layer, double beta, TrkrCluster *cluster); private: + // TF1 *ftpcR1 {nullptr}; TF1 *f0 {nullptr}; TF1 *f1 {nullptr}; TF1 *f2 {nullptr}; @@ -128,6 +130,7 @@ class ClusterErrorPara double scale_mm_1 {1.5}; double pull_fine_phi[60]{}; double pull_fine_z[60]{}; + }; #endif diff --git a/offline/packages/trackbase_historic/SvtxTrackState_v3.h b/offline/packages/trackbase_historic/SvtxTrackState_v3.h index 8f32d0e872..a29bd179ca 100644 --- a/offline/packages/trackbase_historic/SvtxTrackState_v3.h +++ b/offline/packages/trackbase_historic/SvtxTrackState_v3.h @@ -78,7 +78,7 @@ class SvtxTrackState_v3 : public SvtxTrackState float _pos[3]{}; float _mom[3]{}; float _covar[21]{}; // 6x6 triangular packed storage - TrkrDefs::cluskey _ckey{}; // clusterkey that is associated with this state + TrkrDefs::cluskey _ckey{std::numeric_limits::max()}; // clusterkey that is associated with this state std::string state_name; ClassDefOverride(SvtxTrackState_v3, 1) diff --git a/offline/packages/trackbase_historic/TrackAnalysisUtils.cc b/offline/packages/trackbase_historic/TrackAnalysisUtils.cc index 744949c8fe..04f5ff341c 100644 --- a/offline/packages/trackbase_historic/TrackAnalysisUtils.cc +++ b/offline/packages/trackbase_historic/TrackAnalysisUtils.cc @@ -1,12 +1,16 @@ #include "TrackAnalysisUtils.h" +#include + +#include +#include + #include #include #include #include -#include -#include +#include #include "SvtxTrack.h" #include "TrackSeed.h" @@ -18,7 +22,7 @@ namespace TrackAnalysisUtils float calc_dedx(TrackSeed* tpcseed, TrkrClusterContainer* clustermap, ActsGeometry* tgeometry, - float thickness_per_region[4]) + const float thickness_per_region[4]) { std::vector clusterKeys; clusterKeys.insert(clusterKeys.end(), tpcseed->begin_cluster_keys(), @@ -95,10 +99,10 @@ namespace TrackAnalysisUtils float calc_dedx_calib(SvtxTrack* track, TrkrClusterContainer* cluster_map, ActsGeometry* tgeometry, - float thickness_per_region[4]) + const float thickness_per_region[4]) { auto clusterKeys = get_cluster_keys(track->get_tpc_seed()); - + std::vector dedxlist; for (unsigned long cluster_key : clusterKeys) { @@ -137,7 +141,7 @@ namespace TrackAnalysisUtils float adc = cluster->getAdc(); float r = std::sqrt(cglob(0) * cglob(0) + cglob(1) * cglob(1)); - auto tpcseed = track->get_tpc_seed(); + auto* tpcseed = track->get_tpc_seed(); float alpha = (r * r) / (2 * r * std::abs(1.0 / tpcseed->get_qOverR())); float beta = std::atan(tpcseed->get_slope()); float alphacorr = std::cos(alpha); @@ -150,14 +154,14 @@ namespace TrackAnalysisUtils { betacorr = 4; } - if(track->get_crossing() < SHRT_MAX) + if (track->get_crossing() < SHRT_MAX) { - double z_crossing_corrected = - TpcClusterZCrossingCorrection::correctZ(cglob.z(), + double z_crossing_corrected = + TpcClusterZCrossingCorrection::correctZ(cglob.z(), TpcDefs::getSide(cluster_key), track->get_crossing()); - double maxz = tgeometry->get_max_driftlength() + tgeometry->get_CM_halfwidth(); - adc /= (1 - ((maxz - abs(z_crossing_corrected)) * 0.50 / maxz)); + double maxz = tgeometry->get_max_driftlength() + tgeometry->get_CM_halfwidth(); + adc /= (1 - ((maxz - abs(z_crossing_corrected)) * 0.50 / maxz)); } adc /= thickness; adc *= alphacorr; @@ -178,7 +182,7 @@ namespace TrackAnalysisUtils return sumdedx; } - TrackAnalysisUtils::DCAPair get_dca(SvtxTrack *track, + TrackAnalysisUtils::DCAPair get_dca(SvtxTrack* track, GlobalVertex* vertex) { Acts::Vector3 vpos(vertex->get_x(), @@ -201,9 +205,8 @@ namespace TrackAnalysisUtils vertexCov(i, j) = vertex->get_error(i, j); } } - - Acts::ActsSquareMatrix<3> rotCov = rot * (posCov+vertexCov) * rot_T; + Acts::ActsSquareMatrix<3> rotCov = rot * (posCov + vertexCov) * rot_T; dca.first.second = sqrt(rotCov(0, 0)); dca.second.second = sqrt(rotCov(2, 2)); @@ -274,12 +277,12 @@ namespace TrackAnalysisUtils std::vector get_cluster_keys(TrackSeed* seed) { std::vector out; - - if (seed) - { - std::copy(seed->begin_cluster_keys(), seed->end_cluster_keys(), std::back_inserter(out)); - } - + + if (seed) + { + std::copy(seed->begin_cluster_keys(), seed->end_cluster_keys(), std::back_inserter(out)); + } + return out; } @@ -296,4 +299,112 @@ namespace TrackAnalysisUtils return out; } + TrackAnalysisUtils::TrackFitResiduals + get_residuals(SvtxTrack* track, TrkrClusterContainer* clustermap, + PHCompositeNode* topNode) + { + TrackAnalysisUtils::TrackFitResiduals residuals; + TpcGlobalPositionWrapper globalWrapper; + globalWrapper.loadNodes(topNode); + globalWrapper.set_suppressCrossing(true); + TpcClusterMover mover; + auto* tpccellgeo = findNode::getClass(topNode, "TPCGEOMCONTAINER"); + mover.initialize_geometry(tpccellgeo); + mover.set_verbosity(0); + + auto* geometry = findNode::getClass(topNode, "ActsGeometry"); + + std::vector> global_raw; + + for (const auto& key : get_cluster_keys(track)) + { + auto* clus = clustermap->findCluster(key); + + // Fully correct the cluster positions for the crossing and all distortions + Acts::Vector3 global = globalWrapper.getGlobalPositionDistortionCorrected(key, clus, track->get_crossing()); + // add the global positions to a vector to give to the cluster mover + global_raw.emplace_back(key, global); + } + + auto global_moved = mover.processTrack(global_raw); + + for (const auto& ckey : get_cluster_keys(track)) + { + auto* cluster = clustermap->findCluster(ckey); + // loop over global vectors and get this cluster + Acts::Vector3 clusglob(0, 0, 0); + for (const auto& pair : global_raw) + { + auto thiskey = pair.first; + clusglob = pair.second; + if (thiskey == ckey) + { + break; + } + } + + Acts::Vector3 clusglob_moved(0, 0, 0); + for (const auto& pair : global_moved) + { + auto thiskey = pair.first; + clusglob_moved = pair.second; + if (thiskey == ckey) + { + break; + } + } + SvtxTrackState* state = nullptr; + for (auto state_iter = track->begin_states(); + state_iter != track->end_states(); + ++state_iter) + { + SvtxTrackState* tstate = state_iter->second; + auto stateckey = tstate->get_cluskey(); + if (stateckey == ckey) + { + state = tstate; + break; + } + } + Surface surf = geometry->maps().getSurface(ckey, cluster); + Surface surf_ideal = geometry->maps().getSurface(ckey, cluster); // Unchanged by distortion corrections + // if this is a TPC cluster, the crossing correction may have moved it across the central membrane, check the surface + auto trkrid = TrkrDefs::getTrkrId(ckey); + if (trkrid == TrkrDefs::tpcId) + { + TrkrDefs::hitsetkey hitsetkey = TrkrDefs::getHitSetKeyFromClusKey(ckey); + TrkrDefs::subsurfkey new_subsurfkey = 0; + surf = geometry->get_tpc_surface_from_coords(hitsetkey, clusglob_moved, new_subsurfkey); + } + + auto loc = geometry->getLocalCoords(ckey, cluster, track->get_crossing()); + // in this case we get local coords from transform of corrected global coords + clusglob_moved *= Acts::UnitConstants::cm; // we want mm for transformations + Acts::Vector3 normal = surf->normal(geometry->geometry().getGeoContext(), + Acts::Vector3(1, 1, 1), Acts::Vector3(1, 1, 1)); + auto local = surf->globalToLocal(geometry->geometry().getGeoContext(), + clusglob_moved, normal); + if (local.ok()) + { + loc = local.value() / Acts::UnitConstants::cm; + } + else + { + // otherwise take the manual calculation for the TPC + // doing it this way just avoids the bounds check that occurs in the surface class method + Acts::Vector3 loct = surf->transform(geometry->geometry().getGeoContext()).inverse() * clusglob_moved; // global is in mm + loct /= Acts::UnitConstants::cm; + + loc(0) = loct(0); + loc(1) = loct(1); + } + clusglob_moved /= Acts::UnitConstants::cm; // we want cm for the tree + Acts::Vector2 stateloc(state->get_localX(), state->get_localY()); + Acts::Vector3 stateglob(state->get_x(), state->get_y(), state->get_z()); + residuals.local_residuals[ckey] = stateloc - loc; + residuals.global_residuals[ckey] = stateglob - clusglob_moved; + } + return residuals; + } + } // namespace TrackAnalysisUtils diff --git a/offline/packages/trackbase_historic/TrackAnalysisUtils.h b/offline/packages/trackbase_historic/TrackAnalysisUtils.h index 168ff7495f..aab282da20 100644 --- a/offline/packages/trackbase_historic/TrackAnalysisUtils.h +++ b/offline/packages/trackbase_historic/TrackAnalysisUtils.h @@ -4,6 +4,9 @@ #include #include +#include +#include +#include #include class SvtxTrack; @@ -13,6 +16,13 @@ class TrkrClusterContainer; class GlobalVertex; namespace TrackAnalysisUtils { + + struct TrackFitResiduals + { + std::map local_residuals; + std::map global_residuals; + }; + /// Returns DCA as .first and uncertainty on DCA as .second using DCA = std::pair; using DCAPair = std::pair; @@ -28,9 +38,12 @@ namespace TrackAnalysisUtils // to pass these from the geometry object, which keeps the dependencies // of this helper class minimal. This will also help us catch any changes // when/if the tpc geometry changes in the future. This is to get us going - float thickness_per_region[4]); + const float thickness_per_region[4]); float calc_dedx(TrackSeed* tpcseed, TrkrClusterContainer* clustermap, ActsGeometry* tgeometry, - float thickness_per_region[4]); + float const thickness_per_region[4]); + TrackFitResiduals + get_residuals(SvtxTrack* track, TrkrClusterContainer* clustermap, + PHCompositeNode* topNode); }; // namespace TrackAnalysisUtils diff --git a/offline/packages/trackbase_historic/TrackSeed.h b/offline/packages/trackbase_historic/TrackSeed.h index 3d99703500..371bf557ab 100644 --- a/offline/packages/trackbase_historic/TrackSeed.h +++ b/offline/packages/trackbase_historic/TrackSeed.h @@ -49,8 +49,8 @@ class TrackSeed : public PHObject virtual float get_py() const { return NAN; } virtual short int get_crossing() const { return 0; } - virtual unsigned int get_silicon_seed_index() const { return 0; } - virtual unsigned int get_tpc_seed_index() const { return 0; } + virtual unsigned int get_silicon_seed_index() const { return std::numeric_limits::max(); } + virtual unsigned int get_tpc_seed_index() const { return std::numeric_limits::max(); } virtual short int get_crossing_estimate() const { return 0; } virtual bool empty_cluster_keys() const { return true; } diff --git a/offline/packages/trackbase_historic/TrackSeedHelper.cc b/offline/packages/trackbase_historic/TrackSeedHelper.cc index 99a9198811..0fba4fb80a 100644 --- a/offline/packages/trackbase_historic/TrackSeedHelper.cc +++ b/offline/packages/trackbase_historic/TrackSeedHelper.cc @@ -142,8 +142,8 @@ void TrackSeedHelper::circleFitByTaubin( float qOverR = 1./r; /// Set the charge - const auto& firstpos = positions_2d.at(0); - const auto& secondpos = positions_2d.at(1); + const auto& firstpos = *(positions_2d.begin()); + const auto& secondpos = *(positions_2d.rbegin()); const auto firstphi = atan2(firstpos.second, firstpos.first); const auto secondphi = atan2(secondpos.second, secondpos.first); diff --git a/offline/packages/trackreco/ActsPropagator.cc b/offline/packages/trackreco/ActsPropagator.cc index 8cd4942ea4..2578f05e61 100644 --- a/offline/packages/trackreco/ActsPropagator.cc +++ b/offline/packages/trackreco/ActsPropagator.cc @@ -48,7 +48,7 @@ ActsPropagator::makeTrackParams(SvtxTrackState* state, Acts::BoundSquareMatrix cov = transformer.rotateSvtxTrackCovToActs(state); return ActsTrackFittingAlgorithm::TrackParameters::create( - surf, + surf, // NOLINT (performance-unnecessary-value-param) m_geometry->geometry().getGeoContext(), actsFourPos, momentum, trackCharge / momentum.norm(), @@ -98,7 +98,8 @@ ActsPropagator::BTPPairResult ActsPropagator::propagateTrack(const Acts::BoundTrackParameters& params, const unsigned int sphenixLayer) { - unsigned int actsvolume, actslayer; + unsigned int actsvolume; + unsigned int actslayer; if (!checkLayer(sphenixLayer, actsvolume, actslayer) || !m_geometry) { return Acts::Result::failure(std::error_code(0, std::generic_category())); @@ -125,7 +126,7 @@ ActsPropagator::propagateTrack(const Acts::BoundTrackParameters& params, if (result.ok()) { - auto finalparams = *result.value().endParameters; + auto finalparams = *result.value().endParameters; // NOLINT(bugprone-unchecked-optional-access) auto pathlength = result.value().pathLength; auto pair = std::make_pair(pathlength, finalparams); @@ -154,7 +155,7 @@ ActsPropagator::propagateTrack(const Acts::BoundTrackParameters& params, if (result.ok()) { - auto finalparams = *result.value().endParameters; + auto finalparams = *result.value().endParameters; // NOLINT(bugprone-unchecked-optional-access) auto pathlength = result.value().pathLength; auto pair = std::make_pair(pathlength, finalparams); @@ -183,7 +184,7 @@ ActsPropagator::propagateTrackFast(const Acts::BoundTrackParameters& params, if (result.ok()) { - auto finalparams = *result.value().endParameters; + auto finalparams = *result.value().endParameters; // NOLINT(bugprone-unchecked-optional-access) auto pathlength = result.value().pathLength; auto pair = std::make_pair(pathlength, finalparams); diff --git a/offline/packages/trackreco/DSTClusterPruning.cc b/offline/packages/trackreco/DSTClusterPruning.cc index 15bfe547ca..890e465b96 100644 --- a/offline/packages/trackreco/DSTClusterPruning.cc +++ b/offline/packages/trackreco/DSTClusterPruning.cc @@ -177,6 +177,42 @@ void DSTClusterPruning::prune_clusters() } return; } + if(m_pruneAllSeeds) + { + for(const auto& container : {m_tpc_track_seed_container, m_silicon_track_seed_container}) + { + for (const auto& trackseed : *container) + { + if (!trackseed) + { + if(Verbosity() > 1) + { + std::cout << "No TrackSeed" << std::endl; + } + continue; + } + + for (auto key_iter = trackseed->begin_cluster_keys(); key_iter != trackseed->end_cluster_keys(); ++key_iter) + { + const auto& cluster_key = *key_iter; + auto *cluster = m_cluster_map->findCluster(cluster_key); + if (!cluster) + { + std::cout << "DSTClusterPruning::evaluate_tracks - unable to find cluster for key " << cluster_key << std::endl; + continue; + } + if (!m_reduced_cluster_map->findCluster(cluster_key)) + { + m_cluster = new TrkrClusterv5(); + m_cluster->CopyFrom(cluster); + m_reduced_cluster_map->addClusterSpecifyKey(cluster_key, m_cluster); + } + } + } + } + return; + } + for (const auto& trackseed : *m_track_seed_container) { if (!trackseed) diff --git a/offline/packages/trackreco/DSTClusterPruning.h b/offline/packages/trackreco/DSTClusterPruning.h index c9ec35ea53..5fa2ff9b4f 100644 --- a/offline/packages/trackreco/DSTClusterPruning.h +++ b/offline/packages/trackreco/DSTClusterPruning.h @@ -52,6 +52,12 @@ class DSTClusterPruning : public SubsysReco //! end of processing //int End(PHCompositeNode*) override; + //! dump all clusters on all seeds out + void pruneAllSeeds() + { + m_pruneAllSeeds = true; + } + private: //! load nodes int load_nodes(PHCompositeNode*); @@ -68,6 +74,9 @@ class DSTClusterPruning : public SubsysReco TrackSeedContainer* m_tpc_track_seed_container = nullptr; TrackSeedContainer* m_silicon_track_seed_container = nullptr; +//! set to true if you want to dump out all clusters on all silicon +//! and all tpc seeds individually + bool m_pruneAllSeeds = false; //@} // debugging helpers diff --git a/offline/packages/trackreco/MakeSourceLinks.cc b/offline/packages/trackreco/MakeSourceLinks.cc index efbbe92853..f9038d182e 100644 --- a/offline/packages/trackreco/MakeSourceLinks.cc +++ b/offline/packages/trackreco/MakeSourceLinks.cc @@ -1,13 +1,12 @@ #include "MakeSourceLinks.h" -#include +#include +#include #include #include #include -#include #include #include -#include #include #include @@ -16,8 +15,8 @@ #include #include -#include #include +#include #include @@ -29,26 +28,25 @@ namespace { - template + template inline T square(const T& x) { return x * x; } - [[maybe_unused]] std::ostream& operator << (std::ostream& out, const Acts::Vector3& v ) + [[maybe_unused]] std::ostream& operator<<(std::ostream& out, const Acts::Vector3& v) { out << "(" << v.x() << ", " << v.y() << ", " << v.z() << ")"; return out; } - - [[maybe_unused]] std::ostream& operator << (std::ostream& out, const Acts::Vector2& v ) + [[maybe_unused]] std::ostream& operator<<(std::ostream& out, const Acts::Vector2& v) { out << "(" << v.x() << ", " << v.y() << ")"; return out; } -} +} // namespace void MakeSourceLinks::initialize(PHG4TpcGeomContainer* cellgeo) { @@ -57,30 +55,33 @@ void MakeSourceLinks::initialize(PHG4TpcGeomContainer* cellgeo) { _clusterMover.initialize_geometry(cellgeo); } - } - //___________________________________________________________________________________ +//___________________________________________________________________________________ SourceLinkVec MakeSourceLinks::getSourceLinks( - TrackSeed* track, - ActsTrackFittingAlgorithm::MeasurementContainer& measurements, - TrkrClusterContainer* clusterContainer, - ActsGeometry* tGeometry, - const TpcGlobalPositionWrapper& globalPositionWrapper, - alignmentTransformationContainer* transformMapTransient, - std::set< Acts::GeometryIdentifier>& transient_id_set, - short int crossing - ) + TrackSeed* track, + ActsTrackFittingAlgorithm::MeasurementContainer& measurements, + TrkrClusterContainer* clusterContainer, + ActsGeometry* tGeometry, + const TpcGlobalPositionWrapper& globalPositionWrapper, + alignmentTransformationContainer* transformMapTransient, + std::set& transient_id_set, + short int crossing) { - if(m_verbosity > 1) { std::cout << "Entering MakeSourceLinks::getSourceLinks " << std::endl; } + if (m_verbosity > 1) + { + std::cout << "Entering MakeSourceLinks::getSourceLinks " << std::endl; + } SourceLinkVec sourcelinks; if (m_pp_mode && crossing == SHRT_MAX) { // Need to skip this in the pp case, for AuAu it should not happen - if(m_verbosity > 1) - { std::cout << "Seed has no crossing, and in pp mode: skip this seed" << std::endl; } + if (m_verbosity > 1) + { + std::cout << "Seed has no crossing, and in pp mode: skip this seed" << std::endl; + } return sourcelinks; } @@ -96,84 +97,90 @@ SourceLinkVec MakeSourceLinks::getSourceLinks( ++clusIter) { auto key = *clusIter; - auto cluster = clusterContainer->findCluster(key); + auto* cluster = clusterContainer->findCluster(key); if (!cluster) + { + if (m_verbosity > 0) { - if (m_verbosity > 0) - {std::cout << "MakeSourceLinks: Failed to get cluster with key " << key << " for track seed" << std::endl;} - continue; + std::cout << "MakeSourceLinks: Failed to get cluster with key " << key << " for track seed" << std::endl; } - else - if(m_verbosity > 0) - {std::cout << "MakeSourceLinks: Found cluster with key " << key << " for track seed " << std::endl;} - + continue; + } + if (m_verbosity > 0) + { + std::cout << "MakeSourceLinks: Found cluster with key " << key << " for track seed " << std::endl; + } + /// Make a safety check for clusters that couldn't be attached to a surface auto surf = tGeometry->maps().getSurface(key, cluster); if (!surf) - { - continue; - } - + { + continue; + } + const unsigned int trkrid = TrkrDefs::getTrkrId(key); const unsigned int clus_layer = TrkrDefs::getLayer(key); - if(m_verbosity > 1) { std::cout << " Cluster key " << key << " layer " << clus_layer << " trkrid " << trkrid << " crossing " << crossing << std::endl; } + if (m_verbosity > 1) + { + std::cout << " Cluster key " << key << " layer " << clus_layer << " trkrid " << trkrid << " crossing " << crossing << std::endl; + } // For the TPC, cluster z has to be corrected for the crossing z offset, distortion, and TOF z offset // we do this by modifying the fake surface transform, to move the cluster to the corrected position if (trkrid == TrkrDefs::tpcId) { - Acts::Vector3 global = globalPositionWrapper.getGlobalPositionDistortionCorrected(key, cluster, crossing ); + Acts::Vector3 global = globalPositionWrapper.getGlobalPositionDistortionCorrected(key, cluster, crossing); Acts::Vector3 nominal_global_in = tGeometry->getGlobalPosition(key, cluster); Acts::Vector3 global_in = tGeometry->getGlobalPosition(key, cluster); // The wrapper returns the global position corrected for distortion and the cluster crossing z offset // The cluster z crossing correction has to be applied to the nominal global position (global_in) - double cluster_crossing_corrected_z= TpcClusterZCrossingCorrection::correctZ(global_in.z(), TpcDefs::getSide(key), crossing); - double crossing_correction = cluster_crossing_corrected_z - global_in.z(); + double cluster_crossing_corrected_z = TpcClusterZCrossingCorrection::correctZ(global_in.z(), TpcDefs::getSide(key), crossing); + double crossing_correction = cluster_crossing_corrected_z - global_in.z(); global_in.z() = cluster_crossing_corrected_z; - - if(m_verbosity > 2) + + if (m_verbosity > 2) { - unsigned int this_layer = TrkrDefs::getLayer(key); - unsigned int this_side = TpcDefs::getSide(key); - if(this_layer == 28) - { - std::cout << " crossing " << crossing << " layer " << this_layer << " side " << this_side << " clusterkey " << key << std::endl - << " nominal global_in " << nominal_global_in(0) << " " << nominal_global_in(1) << " " << nominal_global_in(2) - << " global_in " << global_in(0) << " " << global_in(1) << " " << global_in(2) - << " corr glob " << global(0) << " " << global(1) << " " << global(2) << std::endl - << " distortion " << global(0)-global_in(0) << " " - << global(1) - global_in(1) << " " << global(2) - global_in(2) - << " cluster crossing z correction " << crossing_correction - << std::endl; - } + unsigned int this_layer = TrkrDefs::getLayer(key); + unsigned int this_side = TpcDefs::getSide(key); + if (this_layer == 28) + { + std::cout << " crossing " << crossing << " layer " << this_layer << " side " << this_side << " clusterkey " << key << std::endl + << " nominal global_in " << nominal_global_in(0) << " " << nominal_global_in(1) << " " << nominal_global_in(2) + << " global_in " << global_in(0) << " " << global_in(1) << " " << global_in(2) + << " corr glob " << global(0) << " " << global(1) << " " << global(2) << std::endl + << " distortion " << global(0) - global_in(0) << " " + << global(1) - global_in(1) << " " << global(2) - global_in(2) + << " cluster crossing z correction " << crossing_correction + << std::endl; + } } - + // Make an afine transform that implements the distortion correction as a translation - auto correction_translation = (global - global_in)*Acts::UnitConstants::cm; - Acts::Vector3 correction_rotation(0,0,0); // null rotation + auto correction_translation = (global - global_in) * Acts::UnitConstants::cm; + Acts::Vector3 correction_rotation(0, 0, 0); // null rotation Acts::Transform3 tcorr = tGeometry->makeAffineTransform(correction_rotation, correction_translation); auto this_surf = tGeometry->maps().getSurface(key, cluster); Acts::GeometryIdentifier id = this_surf->geometryId(); - auto check_cluster = clusterContainer->findCluster(key); - Acts::Vector2 check_local2d = tGeometry->getLocalCoords(key, check_cluster) * Acts::UnitConstants::cm; // need mm - Acts::Vector3 check_local3d (check_local2d(0), check_local2d(1), 0); + auto* check_cluster = clusterContainer->findCluster(key); + Acts::Vector2 check_local2d = tGeometry->getLocalCoords(key, check_cluster) * Acts::UnitConstants::cm; // need mm + Acts::Vector3 check_local3d(check_local2d(0), check_local2d(1), 0); Acts::GeometryContext temp_transient_geocontext; - temp_transient_geocontext = transformMapTransient; - Acts::Vector3 check_before_pos_surf = this_surf->localToGlobal( temp_transient_geocontext, - check_local2d, - Acts::Vector3(1,1,1)); - if(m_verbosity > 2) - { - unsigned int this_layer = TrkrDefs::getLayer(key); - if(this_layer == 28) - { - std::cout << "Check global from transient transform BEFORE via surface method " << check_before_pos_surf(0)/10.0 << " " - << " " << check_before_pos_surf(1)/10.0 << " " << check_before_pos_surf(2)/10.0 << std::endl; - } - } - + temp_transient_geocontext = transformMapTransient; + Acts::Vector3 check_before_pos_surf = this_surf->localToGlobal(temp_transient_geocontext, + check_local2d, + Acts::Vector3(1, 1, 1)); + if (m_verbosity > 2) + { + unsigned int this_layer = TrkrDefs::getLayer(key); + if (this_layer == 28) + { + std::cout << "Check global from transient transform BEFORE via surface method " << check_before_pos_surf(0) / 10.0 << " " + << " " << check_before_pos_surf(1) / 10.0 << " " << check_before_pos_surf(2) / 10.0 << std::endl; + } + } + // replace the the default alignment transform with the corrected one auto ctxt = tGeometry->geometry().getGeoContext(); alignmentTransformationContainer* transformMap = ctxt.get(); @@ -181,18 +188,18 @@ SourceLinkVec MakeSourceLinks::getSourceLinks( transformMapTransient->replaceTransform(id, corrected_transform); transient_id_set.insert(id); - Acts::Vector3 check_after_pos_surf = this_surf->localToGlobal( temp_transient_geocontext, - check_local2d, - Acts::Vector3(1,1,1)); - if(m_verbosity > 2) - { - unsigned int this_layer = TrkrDefs::getLayer(key); - if(this_layer == 28) - { - std::cout << "Check global from transient transform AFTER via surface method " << check_after_pos_surf(0)/10.0 << " " - << " " << check_after_pos_surf(1)/10.0 << " " << check_after_pos_surf(2)/10.0 << std::endl; - } - } + Acts::Vector3 check_after_pos_surf = this_surf->localToGlobal(temp_transient_geocontext, + check_local2d, + Acts::Vector3(1, 1, 1)); + if (m_verbosity > 2) + { + unsigned int this_layer = TrkrDefs::getLayer(key); + if (this_layer == 28) + { + std::cout << "Check global from transient transform AFTER via surface method " << check_after_pos_surf(0) / 10.0 << " " + << " " << check_after_pos_surf(1) / 10.0 << " " << check_after_pos_surf(2) / 10.0 << std::endl; + } + } } // end TPC specific treatment // corrected TPC transforms are installed, capture the cluster key @@ -201,128 +208,143 @@ SourceLinkVec MakeSourceLinks::getSourceLinks( } // end loop over clusters here Acts::GeometryContext transient_geocontext; - transient_geocontext = transformMapTransient; + transient_geocontext = transformMapTransient; // loop over cluster_vec and make source links - for(auto& cluskey : cluster_vec) + for (auto& cluskey : cluster_vec) + { + if (m_ignoreLayer.contains(TrkrDefs::getLayer(cluskey))) { - if (m_ignoreLayer.contains(TrkrDefs::getLayer(cluskey))) - { - if (m_verbosity > 3) - { - std::cout << PHWHERE << "skipping cluster in layer " - << (unsigned int) TrkrDefs::getLayer(cluskey) << std::endl; - } - continue; - } - - // get local coordinates (TPC time needs conversion to cm) - auto cluster = clusterContainer->findCluster(cluskey); - Acts::Vector2 localPos = tGeometry->getLocalCoords(cluskey, cluster, crossing); // cm - - Surface surf = tGeometry->maps().getSurface(cluskey, cluster); - - Acts::ActsVector<2> loc; - loc[Acts::eBoundLoc0] = localPos(0) * Acts::UnitConstants::cm; // mm - loc[Acts::eBoundLoc1] = localPos(1) * Acts::UnitConstants::cm; - - std::array indices = - {Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc1}; - Acts::ActsSquareMatrix<2> cov = Acts::ActsSquareMatrix<2>::Zero(); - - // get errors - Acts::Vector3 global = tGeometry->getGlobalPosition(cluskey, cluster); - double clusRadius = sqrt(global[0] * global[0] + global[1] * global[1]); - auto para_errors = _ClusErrPara.get_clusterv5_modified_error(cluster, clusRadius, cluskey); - cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = para_errors.first * Acts::UnitConstants::cm2; - cov(Acts::eBoundLoc0, Acts::eBoundLoc1) = 0; - cov(Acts::eBoundLoc1, Acts::eBoundLoc0) = 0; - cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = para_errors.second * Acts::UnitConstants::cm2; - - ActsSourceLink::Index index = measurements.size(); - - SourceLink sl(surf->geometryId(), index, cluskey); - Acts::SourceLink actsSL{sl}; - Acts::Measurement meas(actsSL, indices, loc, cov); if (m_verbosity > 3) - { - unsigned int this_layer = TrkrDefs::getLayer(cluskey); - if (this_layer == 28) - { - std::cout << "source link in layer " << this_layer << " for cluskey " << cluskey << " is " << sl.index() << ", loc : " - << loc.transpose() << std::endl - << ", cov : " << cov.transpose() << std::endl - << " geo id " << sl.geometryId() << std::endl; - std::cout << "Surface original transform: " << std::endl; - surf.get()->toStream(tGeometry->geometry().getGeoContext(), std::cout); - std::cout << std::endl << "Surface transient transform: " << std::endl; - surf.get()->toStream(transient_geocontext, std::cout); - std::cout << std::endl; - std::cout << "Corrected surface transform:" << std::endl; - std::cout << transformMapTransient->getTransform(surf->geometryId()).matrix() << std::endl; - std::cout << "Cluster error " << cluster->getRPhiError() << " , " << cluster->getZError() << std::endl; - std::cout << "For key " << cluskey << " with local pos " << std::endl - << localPos(0) << ", " << localPos(1) - << std::endl << std::endl; - } + { + std::cout << PHWHERE << "skipping cluster in layer " + << (unsigned int) TrkrDefs::getLayer(cluskey) << std::endl; + } + continue; + } + + // get local coordinates (TPC time needs conversion to cm) + auto* cluster = clusterContainer->findCluster(cluskey); + if (TrkrDefs::getTrkrId(cluskey) == TrkrDefs::TrkrId::tpcId) + { + if (cluster->getEdge() > m_cluster_edge_rejection) + { + continue; + } } + Acts::Vector2 localPos = tGeometry->getLocalCoords(cluskey, cluster, crossing); // cm + + Surface surf = tGeometry->maps().getSurface(cluskey, cluster); + + Acts::ActsVector<2> loc; + loc[Acts::eBoundLoc0] = localPos(0) * Acts::UnitConstants::cm; // mm + loc[Acts::eBoundLoc1] = localPos(1) * Acts::UnitConstants::cm; + + std::array indices = + {Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc1}; + Acts::ActsSquareMatrix<2> cov = Acts::ActsSquareMatrix<2>::Zero(); + + // get errors + Acts::Vector3 global = tGeometry->getGlobalPosition(cluskey, cluster); + double clusRadius = sqrt(global[0] * global[0] + global[1] * global[1]); + auto para_errors = ClusterErrorPara::get_clusterv5_modified_error(cluster, clusRadius, cluskey); + cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = para_errors.first * Acts::UnitConstants::cm2; + cov(Acts::eBoundLoc0, Acts::eBoundLoc1) = 0; + cov(Acts::eBoundLoc1, Acts::eBoundLoc0) = 0; + cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = para_errors.second * Acts::UnitConstants::cm2; - sourcelinks.push_back(actsSL); - measurements.push_back(meas); + ActsSourceLink::Index index = measurements.size(); + + SourceLink sl(surf->geometryId(), index, cluskey); + Acts::SourceLink actsSL{sl}; + Acts::Measurement meas(actsSL, indices, loc, cov); + if (m_verbosity > 3) + { + unsigned int this_layer = TrkrDefs::getLayer(cluskey); + if (this_layer == 28) + { + std::cout << "source link in layer " << this_layer << " for cluskey " << cluskey << " is " << sl.index() << ", loc : " + << loc.transpose() << std::endl + << ", cov : " << cov.transpose() << std::endl + << " geo id " << sl.geometryId() << std::endl; + std::cout << "Surface original transform: " << std::endl; + surf.get()->toStream(tGeometry->geometry().getGeoContext(), std::cout); + std::cout << std::endl + << "Surface transient transform: " << std::endl; + surf.get()->toStream(transient_geocontext, std::cout); + std::cout << std::endl; + std::cout << "Corrected surface transform:" << std::endl; + std::cout << transformMapTransient->getTransform(surf->geometryId()).matrix() << std::endl; + std::cout << "Cluster error " << cluster->getRPhiError() << " , " << cluster->getZError() << std::endl; + std::cout << "For key " << cluskey << " with local pos " << std::endl + << localPos(0) << ", " << localPos(1) + << std::endl + << std::endl; + } } + sourcelinks.push_back(actsSL); + measurements.emplace_back(meas); + } + SLTrackTimer.stop(); auto SLTime = SLTrackTimer.get_accumulated_time(); if (m_verbosity > 1) - { - std::cout << "PHActsTrkFitter Source Links generation time: " + { + std::cout << "PHActsTrkFitter Source Links generation time: " << SLTime << std::endl; - } + } return sourcelinks; } void MakeSourceLinks::resetTransientTransformMap( - alignmentTransformationContainer* transformMapTransient, - std::set< Acts::GeometryIdentifier>& transient_id_set, - ActsGeometry* tGeometry ) + alignmentTransformationContainer* transformMapTransient, + std::set& transient_id_set, + ActsGeometry* tGeometry) const { - if(m_verbosity > 2) { std::cout << "Resetting TransientTransformMap with transient_id_set size " << transient_id_set.size() << std::endl; } + if (m_verbosity > 2) + { + std::cout << "Resetting TransientTransformMap with transient_id_set size " << transient_id_set.size() << std::endl; + } // loop over modifiedTransformSet and replace transient elements modified for the last track with the default transforms - for(auto& id : transient_id_set) - { - auto ctxt = tGeometry->geometry().getGeoContext(); - alignmentTransformationContainer* transformMap = ctxt.get(); - auto transform = transformMap->getTransform(id); - transformMapTransient->replaceTransform(id, transform); - // std::cout << "replaced transform for id " << id << std::endl; - } + for (const auto& id : transient_id_set) + { + auto ctxt = tGeometry->geometry().getGeoContext(); + alignmentTransformationContainer* transformMap = ctxt.get(); + auto transform = transformMap->getTransform(id); + transformMapTransient->replaceTransform(id, transform); + // std::cout << "replaced transform for id " << id << std::endl; + } transient_id_set.clear(); } - //___________________________________________________________________________________ SourceLinkVec MakeSourceLinks::getSourceLinksClusterMover( - TrackSeed* track, - ActsTrackFittingAlgorithm::MeasurementContainer& measurements, - TrkrClusterContainer* clusterContainer, - ActsGeometry* tGeometry, - const TpcGlobalPositionWrapper& globalPositionWrapper, - short int crossing - ) + TrackSeed* track, + ActsTrackFittingAlgorithm::MeasurementContainer& measurements, + TrkrClusterContainer* clusterContainer, + ActsGeometry* tGeometry, + const TpcGlobalPositionWrapper& globalPositionWrapper, + short int crossing) { - if(m_verbosity > 1) { std::cout << "Entering MakeSourceLinks::getSourceLinksClusterMover for seed " - << " with crossing " << crossing - << std::endl; } + if (m_verbosity > 1) + { + std::cout << "Entering MakeSourceLinks::getSourceLinksClusterMover for seed " + << " with crossing " << crossing + << std::endl; + } SourceLinkVec sourcelinks; if (m_pp_mode && crossing == SHRT_MAX) { // Need to skip this in the pp case, for AuAu it should not happen - if(m_verbosity > 1) - { std::cout << "Seed has no crossing, and in pp mode: skip this seed" << std::endl; } + if (m_verbosity > 1) + { + std::cout << "Seed has no crossing, and in pp mode: skip this seed" << std::endl; + } return sourcelinks; } @@ -339,13 +361,17 @@ SourceLinkVec MakeSourceLinks::getSourceLinksClusterMover( ++clusIter) { auto key = *clusIter; - auto cluster = clusterContainer->findCluster(key); + auto* cluster = clusterContainer->findCluster(key); if (!cluster) { if (m_verbosity > 0) - {std::cout << "Failed to get cluster with key " << key << " for track " << track << std::endl;} + { + std::cout << "Failed to get cluster with key " << key << " for track " << track << std::endl; + } else - {std::cout << "PHActsTrkFitter :: Key: " << key << " for track " << track << std::endl;} + { + std::cout << "PHActsTrkFitter :: Key: " << key << " for track " << track << std::endl; + } continue; } @@ -359,40 +385,43 @@ SourceLinkVec MakeSourceLinks::getSourceLinksClusterMover( const unsigned int trkrid = TrkrDefs::getTrkrId(key); - if(m_verbosity > 1) { std::cout << " Cluster key " << key << " trkrid " << trkrid << " crossing " << crossing << std::endl; } + if (m_verbosity > 1) + { + std::cout << " Cluster key " << key << " trkrid " << trkrid << " crossing " << crossing << std::endl; + } // For the TPC, cluster z has to be corrected for the crossing z offset, distortion, and TOF z offset // we do this locally here and do not modify the cluster, since the cluster may be associated with multiple silicon tracks - const Acts::Vector3 global = globalPositionWrapper.getGlobalPositionDistortionCorrected(key, cluster, crossing ); + const Acts::Vector3 global = globalPositionWrapper.getGlobalPositionDistortionCorrected(key, cluster, crossing); if (trkrid == TrkrDefs::tpcId) { - if(m_verbosity > 2) - { - unsigned int this_layer = TrkrDefs::getLayer(key); - if(this_layer == 28) - { - unsigned int this_side = TpcDefs::getSide(key); - Acts::Vector3 nominal_global_in = tGeometry->getGlobalPosition(key, cluster); - Acts::Vector3 global_in = tGeometry->getGlobalPosition(key, cluster); - double cluster_crossing_corrected_z= TpcClusterZCrossingCorrection::correctZ(global_in.z(), TpcDefs::getSide(key), crossing); - double crossing_correction = cluster_crossing_corrected_z - global_in.z(); - global_in.z() = cluster_crossing_corrected_z; - - std::cout << " crossing " << crossing << " layer " << this_layer << " side " << this_side << " clusterkey " << key << std::endl - << " nominal global_in " << nominal_global_in(0) << " " << nominal_global_in(1) << " " << nominal_global_in(2) << std::endl - << " global_in " << global_in(0) << " " << global_in(1) << " " << global_in(2) << std::endl - << " corr glob " << global(0) << " " << global(1) << " " << global(2) << std::endl - << " distortion " << global(0)-global_in(0) << " " - << global(1) - global_in(1) << " " << global(2) - global_in(2) - << " cluster crossing z correction " << crossing_correction - << std::endl; - } - } + if (m_verbosity > 2) + { + unsigned int this_layer = TrkrDefs::getLayer(key); + if (this_layer == 28) + { + unsigned int this_side = TpcDefs::getSide(key); + Acts::Vector3 nominal_global_in = tGeometry->getGlobalPosition(key, cluster); + Acts::Vector3 global_in = tGeometry->getGlobalPosition(key, cluster); + double cluster_crossing_corrected_z = TpcClusterZCrossingCorrection::correctZ(global_in.z(), TpcDefs::getSide(key), crossing); + double crossing_correction = cluster_crossing_corrected_z - global_in.z(); + global_in.z() = cluster_crossing_corrected_z; + + std::cout << " crossing " << crossing << " layer " << this_layer << " side " << this_side << " clusterkey " << key << std::endl + << " nominal global_in " << nominal_global_in(0) << " " << nominal_global_in(1) << " " << nominal_global_in(2) << std::endl + << " global_in " << global_in(0) << " " << global_in(1) << " " << global_in(2) << std::endl + << " corr glob " << global(0) << " " << global(1) << " " << global(2) << std::endl + << " distortion " << global(0) - global_in(0) << " " + << global(1) - global_in(1) << " " << global(2) - global_in(2) + << " cluster crossing z correction " << crossing_correction + << std::endl; + } + } } // add the global positions to a vector to give to the cluster mover - global_raw.emplace_back(std::make_pair(key, global)); + global_raw.emplace_back(key, global); } // end loop over clusters here @@ -405,10 +434,10 @@ SourceLinkVec MakeSourceLinks::getSourceLinksClusterMover( } // loop over global positions returned by cluster mover - for(auto&& [cluskey, global] : global_moved) + for (auto&& [cluskey, global] : global_moved) { // std::cout << "Global moved: " << global.x() << " " << global.y() << " " << global.z() << std::endl; - + if (m_ignoreLayer.contains(TrkrDefs::getLayer(cluskey))) { if (m_verbosity > 3) @@ -419,21 +448,26 @@ SourceLinkVec MakeSourceLinks::getSourceLinksClusterMover( continue; } - auto cluster = clusterContainer->findCluster(cluskey); + auto* cluster = clusterContainer->findCluster(cluskey); Surface surf = tGeometry->maps().getSurface(cluskey, cluster); - if(std::isnan(global.x()) || std::isnan(global.y())) + if (std::isnan(global.x()) || std::isnan(global.y())) { std::cout << "MakeSourceLinks::getSourceLinksClusterMover - invalid position" - << " key: " << cluskey - << " layer: " << (int)TrkrDefs::getLayer(cluskey) - << " position: " << global - << std::endl; + << " key: " << cluskey + << " layer: " << (int) TrkrDefs::getLayer(cluskey) + << " position: " << global + << std::endl; } // if this is a TPC cluster, the crossing correction may have moved it across the central membrane, check the surface auto trkrid = TrkrDefs::getTrkrId(cluskey); if (trkrid == TrkrDefs::tpcId) { + if (cluster->getEdge() > m_cluster_edge_rejection) + { + continue; + } + TrkrDefs::hitsetkey hitsetkey = TrkrDefs::getHitSetKeyFromClusKey(cluskey); TrkrDefs::subsurfkey new_subsurfkey = 0; surf = tGeometry->get_tpc_surface_from_coords(hitsetkey, global, new_subsurfkey); @@ -441,7 +475,10 @@ SourceLinkVec MakeSourceLinks::getSourceLinksClusterMover( if (!surf) { - if(m_verbosity > 2) { std::cout << "MakeSourceLinks::getSourceLinksClusterMover - Failed to find surface for cluskey " << cluskey << std::endl; } + if (m_verbosity > 2) + { + std::cout << "MakeSourceLinks::getSourceLinksClusterMover - Failed to find surface for cluskey " << cluskey << std::endl; + } continue; } @@ -449,7 +486,7 @@ SourceLinkVec MakeSourceLinks::getSourceLinksClusterMover( Acts::Vector2 localPos; global *= Acts::UnitConstants::cm; // we want mm for transformations - Acts::Vector3 normal = surf->normal(tGeometry->geometry().getGeoContext(),Acts::Vector3(1,1,1), Acts::Vector3(1,1,1)); + Acts::Vector3 normal = surf->normal(tGeometry->geometry().getGeoContext(), Acts::Vector3(1, 1, 1), Acts::Vector3(1, 1, 1)); auto local = surf->globalToLocal(tGeometry->geometry().getGeoContext(), global, normal); if (local.ok()) @@ -458,11 +495,14 @@ SourceLinkVec MakeSourceLinks::getSourceLinksClusterMover( } else { - if(m_verbosity > 2) { std::cout << "MakeSourceLinks::getSourceLinksClusterMover - Taking manual calculation for global to local " << std::endl; } + if (m_verbosity > 2) + { + std::cout << "MakeSourceLinks::getSourceLinksClusterMover - Taking manual calculation for global to local " << std::endl; + } /// otherwise take the manual calculation for the TPC // doing it this way just avoids the bounds check that occurs in the surface class method - Acts::Vector3 loct = surf->transform(tGeometry->geometry().getGeoContext()).inverse() * global ; // global is in mm + Acts::Vector3 loct = surf->transform(tGeometry->geometry().getGeoContext()).inverse() * global; // global is in mm loct /= Acts::UnitConstants::cm; localPos(0) = loct(0); @@ -474,34 +514,34 @@ SourceLinkVec MakeSourceLinks::getSourceLinksClusterMover( std::cout << "MakeSourceLinks::getSourceLinksClusterMover - Cluster " << cluskey << " cluster global after mover: " << global << std::endl; std::cout << "MakeSourceLinks::getSourceLinksClusterMover - stored: cluster local X " << cluster->getLocalX() << " cluster local Y " << cluster->getLocalY() << std::endl; - const Acts::Vector2 localTest = tGeometry->getLocalCoords(cluskey, cluster); // cm + const Acts::Vector2 localTest = tGeometry->getLocalCoords(cluskey, cluster); // cm std::cout << "MakeSourceLinks::getSourceLinksClusterMover - localTest from getLocalCoords: " << localTest << std::endl; std::cout << "MakeSourceLinks::getSourceLinksClusterMover - new from inverse transform of cluster global after mover: " << std::endl; - const Acts::Vector3 globalTest = surf->localToGlobal(tGeometry->geometry().getGeoContext(), localTest*Acts::UnitConstants::cm, normal); - std::cout << "MakeSourceLinks::getSourceLinksClusterMover - global from localTest: " << Acts::Vector3(globalTest/Acts::UnitConstants::cm) << std::endl; + const Acts::Vector3 globalTest = surf->localToGlobal(tGeometry->geometry().getGeoContext(), localTest * Acts::UnitConstants::cm, normal); + std::cout << "MakeSourceLinks::getSourceLinksClusterMover - global from localTest: " << Acts::Vector3(globalTest / Acts::UnitConstants::cm) << std::endl; - const Acts::Vector3 globalNew = surf->localToGlobal(tGeometry->geometry().getGeoContext(), localPos*Acts::UnitConstants::cm, normal); - std::cout << "MakeSourceLinks::getSourceLinksClusterMover - global from new local: " << Acts::Vector3(globalNew/Acts::UnitConstants::cm) << std::endl; + const Acts::Vector3 globalNew = surf->localToGlobal(tGeometry->geometry().getGeoContext(), localPos * Acts::UnitConstants::cm, normal); + std::cout << "MakeSourceLinks::getSourceLinksClusterMover - global from new local: " << Acts::Vector3(globalNew / Acts::UnitConstants::cm) << std::endl; } Acts::ActsVector<2> loc; loc[Acts::eBoundLoc0] = localPos(0) * Acts::UnitConstants::cm; loc[Acts::eBoundLoc1] = localPos(1) * Acts::UnitConstants::cm; std::array indices = - {Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc1}; + {Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc1}; Acts::ActsSquareMatrix<2> cov = Acts::ActsSquareMatrix<2>::Zero(); double clusRadius = sqrt(global[0] * global[0] + global[1] * global[1]); - auto para_errors = _ClusErrPara.get_clusterv5_modified_error(cluster, clusRadius, cluskey); + auto para_errors = ClusterErrorPara::get_clusterv5_modified_error(cluster, clusRadius, cluskey); cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = para_errors.first * Acts::UnitConstants::cm2; cov(Acts::eBoundLoc0, Acts::eBoundLoc1) = 0; cov(Acts::eBoundLoc1, Acts::eBoundLoc0) = 0; cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = para_errors.second * Acts::UnitConstants::cm2; ActsSourceLink::Index index = measurements.size(); - + SourceLink sl(surf->geometryId(), index, cluskey); Acts::SourceLink actsSL{sl}; Acts::Measurement meas(actsSL, indices, loc, cov); @@ -521,16 +561,16 @@ SourceLinkVec MakeSourceLinks::getSourceLinksClusterMover( } sourcelinks.push_back(actsSL); - measurements.push_back(meas); + measurements.emplace_back(meas); } SLTrackTimer.stop(); auto SLTime = SLTrackTimer.get_accumulated_time(); if (m_verbosity > 1) - { - std::cout << "PHMakeSourceLinks::getSourceLinksClusterMover - ActsTrkFitter Source Links generation time: " + { + std::cout << "PHMakeSourceLinks::getSourceLinksClusterMover - ActsTrkFitter Source Links generation time: " << SLTime << std::endl; - } + } return sourcelinks; } diff --git a/offline/packages/trackreco/MakeSourceLinks.h b/offline/packages/trackreco/MakeSourceLinks.h index 8acf4f8272..d22acc4881 100644 --- a/offline/packages/trackreco/MakeSourceLinks.h +++ b/offline/packages/trackreco/MakeSourceLinks.h @@ -1,17 +1,17 @@ #ifndef TRACKRECO_MAKESOURCELINKS_H #define TRACKRECO_MAKESOURCELINKS_H -#include #include #include -#include #include +#include +#include #include /// Acts includes to create all necessary definitions -#include #include +#include #include @@ -40,51 +40,47 @@ class TrackSeed; class MakeSourceLinks { public: - MakeSourceLinks() = default; + MakeSourceLinks() = default; - void initialize(PHG4TpcGeomContainer* cellgeo); + void initialize(PHG4TpcGeomContainer* cellgeo); - void setVerbosity(int verbosity) {m_verbosity = verbosity;} - - void set_pp_mode(bool ispp) { m_pp_mode = ispp; } + void setVerbosity(int verbosity) { m_verbosity = verbosity; } + void set_pp_mode(bool ispp) { m_pp_mode = ispp; } + void set_cluster_edge_rejection(int edge) { m_cluster_edge_rejection = edge; } void ignoreLayer(int layer) { m_ignoreLayer.insert(layer); } SourceLinkVec getSourceLinks( - TrackSeed* /*seed*/, - ActsTrackFittingAlgorithm::MeasurementContainer& /*measurements*/, - TrkrClusterContainer* /*clusters*/, - ActsGeometry* /*geometry*/, - const TpcGlobalPositionWrapper& /*globalpositionWrapper*/, - alignmentTransformationContainer* /*transformMapTransient*/, - std::set< Acts::GeometryIdentifier>& /*transient_id_set*/, - short int /*crossing*/); + TrackSeed* /*seed*/, + ActsTrackFittingAlgorithm::MeasurementContainer& /*measurements*/, + TrkrClusterContainer* /*clusters*/, + ActsGeometry* /*geometry*/, + const TpcGlobalPositionWrapper& /*globalpositionWrapper*/, + alignmentTransformationContainer* /*transformMapTransient*/, + std::set& /*transient_id_set*/, + short int /*crossing*/); void resetTransientTransformMap( - alignmentTransformationContainer* /*transformMapTransient*/, - std::set< Acts::GeometryIdentifier>& /*transient_id_set*/, - ActsGeometry* /*tGeometry*/ ); + alignmentTransformationContainer* /*transformMapTransient*/, + std::set& /*transient_id_set*/, + ActsGeometry* /*tGeometry*/) const; SourceLinkVec getSourceLinksClusterMover( - TrackSeed* /*seed*/, - ActsTrackFittingAlgorithm::MeasurementContainer& /*measurements*/, - TrkrClusterContainer* /*clusters*/, - ActsGeometry* /*geometry*/, - const TpcGlobalPositionWrapper& /*globalpositionWrapper*/, - short int crossing - ); + TrackSeed* /*seed*/, + ActsTrackFittingAlgorithm::MeasurementContainer& /*measurements*/, + TrkrClusterContainer* /*clusters*/, + ActsGeometry* /*geometry*/, + const TpcGlobalPositionWrapper& /*globalpositionWrapper*/, + short int crossing); private: int m_verbosity = 0; bool m_pp_mode = false; std::set m_ignoreLayer; - + int m_cluster_edge_rejection = 0; TpcClusterMover _clusterMover; ClusterErrorPara _ClusErrPara; - - }; - #endif diff --git a/offline/packages/trackreco/PHActsSiliconSeeding.cc b/offline/packages/trackreco/PHActsSiliconSeeding.cc index d4741a2ca9..8af74c701f 100644 --- a/offline/packages/trackreco/PHActsSiliconSeeding.cc +++ b/offline/packages/trackreco/PHActsSiliconSeeding.cc @@ -818,10 +818,13 @@ std::vector PHActsSiliconSeeding::findMatches( float avgtriplety = 0; for (auto& pos : clusters) { - avgtripletx += std::cos(std::atan2(pos(1), pos(0))); - avgtriplety += std::sin(std::atan2(pos(1), pos(0))); + + avgtripletx += std::cos(getPhiFromBeamSpot(pos(1), pos(0))); + avgtriplety += std::sin(getPhiFromBeamSpot(pos(1), pos(0))); } + float avgtripletphi = std::atan2(avgtriplety, avgtripletx); + std::vector dummykeys = keys; std::vector dummyclusters = clusters; @@ -889,6 +892,9 @@ std::vector PHActsSiliconSeeding::findMatches( // get an estimate of the phi of the track at this layer // to know which hitsetkeys to look at float layerradius = 0; + float x0 = 0.0; + float y0 = 0.0; + if (layer > 2) { layerradius = m_geomContainerIntt->GetLayerGeom(layer)->get_radius(); @@ -896,12 +902,21 @@ std::vector PHActsSiliconSeeding::findMatches( else { layerradius = m_geomContainerMvtx->GetLayerGeom(layer)->get_radius(); + x0 = m_mvtx_x0; + y0 = m_mvtx_y0; } + float xfitradius_moved = fitpars[1] - x0; + float yfitradius_moved = fitpars[2] - y0; const auto [xplus, yplus, xminus, yminus] = TrackFitUtils::circle_circle_intersection(layerradius, fitpars[0], - fitpars[1], fitpars[2]); - - float approximate_phi1 = atan2(yplus, xplus); - float approximate_phi2 = atan2(yminus, xminus); + xfitradius_moved, yfitradius_moved); + float xp = xplus + x0; + float xm = xminus + x0; + float yp = yplus + y0; + float ym = yminus + y0; + + + float approximate_phi1 = getPhiFromBeamSpot(yp, xp); + float approximate_phi2 = getPhiFromBeamSpot(ym, xm); float approximatephi = approximate_phi1; if (std::fabs(normPhi2Pi(approximate_phi2 - avgtripletphi)) < std::fabs(normPhi2Pi(approximate_phi1 - avgtripletphi))) { @@ -911,7 +926,7 @@ std::vector PHActsSiliconSeeding::findMatches( { auto surf = m_tGeometry->maps().getSiliconSurface(hitsetkey); auto surfcenter = surf->center(m_tGeometry->geometry().geoContext); - float surfphi = atan2(surfcenter.y(), surfcenter.x()); + float surfphi = getPhiFromBeamSpot(surfcenter.y(), surfcenter.x()); float dphi = normPhi2Pi(approximatephi - surfphi); /// Check that the projection is within some reasonable amount of the segment @@ -1141,9 +1156,10 @@ std::vector> PHActsSiliconSeeding::iterateLayers( float avgtriplety = 0; for (const auto& pos : positions) { - avgtripletx += std::cos(std::atan2(pos(1), pos(0))); - avgtriplety += std::sin(std::atan2(pos(1), pos(0))); + avgtripletx += std::cos(getPhiFromBeamSpot(pos(1), pos(0))); + avgtriplety += std::sin(getPhiFromBeamSpot(pos(1), pos(0))); } + float avgtripletphi = std::atan2(avgtriplety, avgtripletx); int layer34timebucket = std::numeric_limits::max(); @@ -1155,13 +1171,29 @@ std::vector> PHActsSiliconSeeding::iterateLayers( } } + // move the fitted circle center the negative of the MVTX center position + float x0 = 0.0; // cm + float y0 = 0.0; for (int layer = startLayer; layer < endLayer; ++layer) { float layerradius = m_geomContainerIntt->GetLayerGeom(layer)->get_radius(); - const auto [xplus, yplus, xminus, yminus] = TrackFitUtils::circle_circle_intersection(layerradius, fitpars[0], fitpars[1], fitpars[2]); + if(layer < 3) + { + x0 = m_mvtx_x0; + y0 = m_mvtx_y0; + } - float approximate_phi1 = atan2(yplus, xplus); - float approximate_phi2 = atan2(yminus, xminus); + float xfitradius_moved = fitpars[1] - x0; + float yfitradius_moved = fitpars[2] - y0; + + const auto [xplus, yplus, xminus, yminus] = TrackFitUtils::circle_circle_intersection(layerradius, fitpars[0], xfitradius_moved, yfitradius_moved); + + float xp = xplus + x0; + float xm = xminus + x0; + float yp = yplus + y0; + float ym = yminus + y0; + float approximate_phi1 = getPhiFromBeamSpot(yp, xp); + float approximate_phi2 = getPhiFromBeamSpot(ym, xm); float approximatephi = approximate_phi1; if (std::fabs(normPhi2Pi(approximate_phi2 - avgtripletphi)) < std::fabs(normPhi2Pi(approximate_phi1 - avgtripletphi))) { @@ -1171,7 +1203,7 @@ std::vector> PHActsSiliconSeeding::iterateLayers( { auto surf = m_tGeometry->maps().getSiliconSurface(hitsetkey); auto surfcenter = surf->center(m_tGeometry->geometry().geoContext); - float surfphi = atan2(surfcenter.y(), surfcenter.x()); + float surfphi = getPhiFromBeamSpot(surfcenter.y(), surfcenter.x()); if(Verbosity() > 5) { std::cout << "approximate phis " << approximate_phi1 << " " << approximate_phi2 << " using " << approximatephi @@ -1404,7 +1436,8 @@ std::vector PHActsSiliconSeeding::getSiliconSpacePoints(Acts: if (det == TrkrDefs::TrkrId::mvtxId) { auto strobeId = MvtxDefs::getStrobeId(hitsetkey); - if (strobeId != strobe) + //if (strobeId != strobe) + if (abs(strobeId - strobe) > 1) { continue; } @@ -1713,6 +1746,15 @@ double PHActsSiliconSeeding::normPhi2Pi(const double phi) return returnPhi; } +float PHActsSiliconSeeding::getPhiFromBeamSpot(float clusy, float clusx) const +{ + // Calculate the phi value for (clusx, clusy) relative to the beam spot (x,y) position + + float phirel = std::atan2(clusy - m_beamSpoty, clusx - m_beamSpotx); + + return phirel; +} + void PHActsSiliconSeeding::largeGridSpacing(const bool spacing) { if (!spacing) diff --git a/offline/packages/trackreco/PHActsSiliconSeeding.h b/offline/packages/trackreco/PHActsSiliconSeeding.h index ea3fe2c1ad..506f9c225c 100644 --- a/offline/packages/trackreco/PHActsSiliconSeeding.h +++ b/offline/packages/trackreco/PHActsSiliconSeeding.h @@ -176,6 +176,16 @@ class PHActsSiliconSeeding : public SubsysReco { m_minSeedPt = pt; } + void set_mvtxCenterXY(const float X, const float Y) + { + m_mvtx_x0 = X; + m_mvtx_y0 = Y; + } + void set_beamSpotXY(const float X, const float Y) + { + m_beamSpotx = X; + m_beamSpoty = Y; + } /// A function to run the seeder with large (true) /// or small (false) grid spacing @@ -243,6 +253,8 @@ class PHActsSiliconSeeding : public SubsysReco short int getCrossingIntt(TrackSeed &si_track); std::vector getInttCrossings(TrackSeed &si_track); + float getPhiFromBeamSpot(float clusy, float clusx) const; + void createHistograms(); void writeHistograms(); double normPhi2Pi(const double phi); @@ -354,6 +366,15 @@ class PHActsSiliconSeeding : public SubsysReco float m_inttzSearchWin = 2.0; // default to one strip width double m_mvtxrPhiSearchWin = 0.2; float m_mvtxzSearchWin = 0.5; + + // collision point in sPHENIX coordinates, from vertex finder (pp run 3) + float m_beamSpotx = -0.072; // cm + float m_beamSpoty = 0.141; // cm + + // center of MVTX barrel in sPHENIX coordinates - default is for Run 3 pp + float m_mvtx_x0 = 0.6; // cm + float m_mvtx_y0 = -0.1; + /// Whether or not to use truth clusters in hit lookup bool m_useTruthClusters = false; diff --git a/offline/packages/trackreco/PHActsTrkFitter.cc b/offline/packages/trackreco/PHActsTrkFitter.cc index a26ee1fa0a..d0006ac25c 100644 --- a/offline/packages/trackreco/PHActsTrkFitter.cc +++ b/offline/packages/trackreco/PHActsTrkFitter.cc @@ -5,7 +5,6 @@ * \author Tony Frawley */ - #include "PHActsTrkFitter.h" #include "ActsPropagator.h" @@ -25,7 +24,7 @@ #include #include #include -//#include +// #include #include #include #include @@ -134,8 +133,8 @@ int PHActsTrkFitter::InitRun(PHCompositeNode* topNode) MaterialSurfaceSelector selector; if (m_fitSiliconMMs || m_directNavigation) { - m_tGeometry->geometry().tGeometry->visitSurfaces(selector,false); - //std::cout<<"selector.surfaces.size() "<geometry().tGeometry->visitSurfaces(selector, false); + // std::cout<<"selector.surfaces.size() "<(m_evalname); m_evaluator->Init(topNode); - if(m_actsEvaluator && !m_simActsEvaluator) + if (m_actsEvaluator && !m_simActsEvaluator) { m_evaluator->isData(); } @@ -182,10 +182,10 @@ int PHActsTrkFitter::InitRun(PHCompositeNode* topNode) _tpccellgeo = findNode::getClass(topNode, "TPCGEOMCONTAINER"); if (!_tpccellgeo) - { - std::cout << PHWHERE << " unable to find DST node TPCGEOMCONTAINER" << std::endl; - return Fun4AllReturnCodes::ABORTRUN; - } + { + std::cout << PHWHERE << " unable to find DST node TPCGEOMCONTAINER" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + } if (Verbosity() > 1) { @@ -287,7 +287,7 @@ int PHActsTrkFitter::End(PHCompositeNode* /*topNode*/) { m_evaluator->End(); } - if(m_useOutlierFinder) + if (m_useOutlierFinder) { m_outlierFinder.Write(); } @@ -314,47 +314,46 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) // capture the input crossing value, and set crossing parameters //============================== - short silicon_crossing = SHRT_MAX; - auto siseed = m_siliconSeeds->get(siid); - if(siseed) - { - silicon_crossing = siseed->get_crossing(); - } + short silicon_crossing = SHRT_MAX; + auto *siseed = m_siliconSeeds->get(siid); + if (siseed) + { + silicon_crossing = siseed->get_crossing(); + } short crossing = silicon_crossing; short int crossing_estimate = crossing; - if(m_enable_crossing_estimate) - { - crossing_estimate = track->get_crossing_estimate(); // geometric crossing estimate from matcher - } + if (m_enable_crossing_estimate) + { + crossing_estimate = track->get_crossing_estimate(); // geometric crossing estimate from matcher + } //=============================== - // must have silicon seed with valid crossing if we are doing a SC calibration fit if (m_fitSiliconMMs) + { + if ((siid == std::numeric_limits::max()) || (silicon_crossing == SHRT_MAX)) { - if( (siid == std::numeric_limits::max()) || (silicon_crossing == SHRT_MAX)) - { - continue; - } + continue; } + } // do not skip TPC only tracks, just set crossing to the nominal zero - if(!siseed) - { - crossing = 0; - } + if (!siseed) + { + crossing = 0; + } if (Verbosity() > 1) { - if(siseed) - { - std::cout << "tpc and si id " << tpcid << ", " << siid << " silicon_crossing " << silicon_crossing - << " crossing " << crossing << " crossing estimate " << crossing_estimate << std::endl; - } + if (siseed) + { + std::cout << "tpc and si id " << tpcid << ", " << siid << " silicon_crossing " << silicon_crossing + << " crossing " << crossing << " crossing estimate " << crossing_estimate << std::endl; + } } - auto tpcseed = m_tpcSeeds->get(tpcid); + auto *tpcseed = m_tpcSeeds->get(tpcid); /// Need to also check that the tpc seed wasn't removed by the ghost finder if (!tpcseed) @@ -381,7 +380,7 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) if (Verbosity() > 1 && siseed) { std::cout << " m_pp_mode " << m_pp_mode << " m_enable_crossing_estimate " << m_enable_crossing_estimate - << " INTT crossing " << crossing << " crossing_estimate " << crossing_estimate << std::endl; + << " INTT crossing " << crossing << " crossing_estimate " << crossing_estimate << std::endl; } short int this_crossing = crossing; @@ -390,35 +389,35 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) std::vector chisq_ndf; std::vector svtx_vec; - if(m_pp_mode) + if (m_pp_mode) + { + if (m_enable_crossing_estimate && crossing == SHRT_MAX) { - if (m_enable_crossing_estimate && crossing == SHRT_MAX) - { - // this only happens if there is a silicon seed but no assigned INTT crossing, and only in pp_mode - // If there is no INTT crossing, start with the crossing_estimate value, vary up and down, fit, and choose the best chisq/ndf - use_estimate = true; - nvary = max_bunch_search; - if (Verbosity() > 1) - { - std::cout << " No INTT crossing: use crossing_estimate " << crossing_estimate << " with nvary " << nvary << std::endl; - } - } - else - { - // use INTT crossing - crossing_estimate = crossing; - } + // this only happens if there is a silicon seed but no assigned INTT crossing, and only in pp_mode + // If there is no INTT crossing, start with the crossing_estimate value, vary up and down, fit, and choose the best chisq/ndf + use_estimate = true; + nvary = max_bunch_search; + if (Verbosity() > 1) + { + std::cout << " No INTT crossing: use crossing_estimate " << crossing_estimate << " with nvary " << nvary << std::endl; + } } + else + { + // use INTT crossing + crossing_estimate = crossing; + } + } else + { + // non pp mode, we want only crossing zero, veto others + if (siseed && silicon_crossing != 0) { - // non pp mode, we want only crossing zero, veto others - if(siseed && silicon_crossing != 0) - { - crossing = 0; - //continue; - } - crossing_estimate = crossing; + crossing = 0; + // continue; } + crossing_estimate = crossing; + } // Fit this track assuming either: // crossing = INTT value, if it exists (uses nvary = 0) @@ -441,16 +440,17 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) makeSourceLinks.initialize(_tpccellgeo); makeSourceLinks.setVerbosity(Verbosity()); makeSourceLinks.set_pp_mode(m_pp_mode); - for(const auto& layer : m_ignoreLayer) + makeSourceLinks.set_cluster_edge_rejection(m_cluster_edge_rejection); + for (const auto& layer : m_ignoreLayer) { makeSourceLinks.ignoreLayer(layer); } // loop over modifiedTransformSet and replace transient elements modified for the previous track with the default transforms // does nothing if m_transient_id_set is empty makeSourceLinks.resetTransientTransformMap( - m_alignmentTransformationMapTransient, - m_transient_id_set, - m_tGeometry); + m_alignmentTransformationMapTransient, + m_transient_id_set, + m_tGeometry); if (m_use_clustermover) { @@ -459,37 +459,56 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) { // silicon source links sourceLinks = makeSourceLinks.getSourceLinksClusterMover( - siseed, + siseed, + measurements, + m_clusterContainer, + m_tGeometry, + m_globalPositionWrapper, + this_crossing); + } + + // tpc source links + const auto tpcSourceLinks = makeSourceLinks.getSourceLinksClusterMover( + tpcseed, measurements, m_clusterContainer, m_tGeometry, m_globalPositionWrapper, this_crossing); - } - - // tpc source links - const auto tpcSourceLinks = makeSourceLinks.getSourceLinksClusterMover( - tpcseed, - measurements, - m_clusterContainer, - m_tGeometry, - m_globalPositionWrapper, - this_crossing); // add tpc sourcelinks to silicon source links sourceLinks.insert(sourceLinks.end(), tpcSourceLinks.begin(), tpcSourceLinks.end()); - - } else { - + } + else + { // make source links using transient transforms for distortion corrections - if(Verbosity() > 1) - { std::cout << "Calling getSourceLinks for si seed, siid " << siid << " and tpcid " << tpcid << std::endl; } + if (Verbosity() > 1) + { + std::cout << "Calling getSourceLinks for si seed, siid " << siid << " and tpcid " << tpcid << std::endl; + } if (siseed && !m_ignoreSilicon) { // silicon source links sourceLinks = makeSourceLinks.getSourceLinks( - siseed, + siseed, + measurements, + m_clusterContainer, + m_tGeometry, + m_globalPositionWrapper, + m_alignmentTransformationMapTransient, + m_transient_id_set, + this_crossing); + } + + if (Verbosity() > 1) + { + std::cout << "Calling getSourceLinks for tpc seed, siid " << siid << " and tpcid " << tpcid << std::endl; + } + + // tpc source links + const auto tpcSourceLinks = makeSourceLinks.getSourceLinks( + tpcseed, measurements, m_clusterContainer, m_tGeometry, @@ -497,21 +516,6 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) m_alignmentTransformationMapTransient, m_transient_id_set, this_crossing); - } - - if(Verbosity() > 1) - { std::cout << "Calling getSourceLinks for tpc seed, siid " << siid << " and tpcid " << tpcid << std::endl; } - - // tpc source links - const auto tpcSourceLinks = makeSourceLinks.getSourceLinks( - tpcseed, - measurements, - m_clusterContainer, - m_tGeometry, - m_globalPositionWrapper, - m_alignmentTransformationMapTransient, - m_transient_id_set, - this_crossing); // add tpc sourcelinks to silicon source links sourceLinks.insert(sourceLinks.end(), tpcSourceLinks.begin(), tpcSourceLinks.end()); @@ -524,32 +528,36 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) Acts::Vector3 position(0, 0, 0); if (siseed) { - position = TrackSeedHelper::get_xyz(siseed)*Acts::UnitConstants::cm; + position = TrackSeedHelper::get_xyz(siseed) * Acts::UnitConstants::cm; } - if(!siseed || !is_valid(position) || m_ignoreSilicon) + if (!siseed || !is_valid(position) || m_ignoreSilicon) { - position = TrackSeedHelper::get_xyz(tpcseed)*Acts::UnitConstants::cm; + position = TrackSeedHelper::get_xyz(tpcseed) * Acts::UnitConstants::cm; } if (!is_valid(position)) { - if(Verbosity() > 4) + if (Verbosity() > 4) { std::cout << "Invalid position of " << position.transpose() << std::endl; } continue; } + // filter sourcelinks to remove detectors that we don't want to include in the fit + sourceLinks = filterSourceLinks( sourceLinks ); + if (sourceLinks.empty()) { continue; } /// If using directed navigation, collect surface list to navigate - SurfacePtrVec surfaces_tmp; SurfacePtrVec surfaces; if (m_fitSiliconMMs || m_directNavigation) { - sourceLinks = getSurfaceVector(sourceLinks, surfaces_tmp); + + // get surfaces matching source links + const auto surfaces_tmp = getSurfaceVector(sourceLinks); // skip if there is no surfaces if (surfaces_tmp.empty()) @@ -559,26 +567,26 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) for (const auto& surface_apr : m_materialSurfaces) { - if(m_forceSiOnlyFit) + if (m_forceSiOnlyFit) { - if(surface_apr->geometryId().volume() >12) + if (surface_apr->geometryId().volume() > 12) { continue; } } bool pop_flag = false; - if(surface_apr->geometryId().approach() == 1) + if (surface_apr->geometryId().approach() == 1) { surfaces.push_back(surface_apr); } else { pop_flag = true; - for (const auto& surface_sns: surfaces_tmp) + for (const auto& surface_sns : surfaces_tmp) { if (surface_apr->geometryId().volume() == surface_sns->geometryId().volume()) { - if ( surface_apr->geometryId().layer()==surface_sns->geometryId().layer()) + if (surface_apr->geometryId().layer() == surface_sns->geometryId().layer()) { pop_flag = false; surfaces.push_back(surface_sns); @@ -594,9 +602,9 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) surfaces.pop_back(); pop_flag = false; } - if (surface_apr->geometryId().volume() == 12&& surface_apr->geometryId().layer()==8) + if (surface_apr->geometryId().volume() == 12 && surface_apr->geometryId().layer() == 8) { - for (const auto& surface_sns: surfaces_tmp) + for (const auto& surface_sns : surfaces_tmp) { if (14 == surface_sns->geometryId().volume()) { @@ -619,13 +627,13 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) { // make sure micromegas are in the tracks, if required if (m_useMicromegas && - std::none_of(surfaces.begin(), surfaces.end(), [this](const auto& surface) - { return m_tGeometry->maps().isMicromegasSurface(surface); })) - { - continue; + std::none_of(surfaces.begin(), surfaces.end(), [this](const auto& surface) + { return m_tGeometry->maps().isMicromegasSurface(surface); })) + { + continue; + } } } - } float px = std::numeric_limits::quiet_NaN(); float py = std::numeric_limits::quiet_NaN(); @@ -635,7 +643,7 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) float seedphi = 0; float seedtheta = 0; float seedeta = 0; - if(siseed) + if (siseed) { seedphi = siseed->get_phi(); seedtheta = siseed->get_theta(); @@ -659,7 +667,9 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) px = pt * std::cos(phi); py = pt * std::sin(phi); pz = pt * std::cosh(eta) * std::cos(theta); - } else { + } + else + { px = seedpt * std::cos(seedphi); py = seedpt * std::sin(seedphi); pz = seedpt * std::cosh(seedeta) * std::cos(seedtheta); @@ -668,14 +678,14 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) Acts::Vector3 momentum(px, py, pz); if (!is_valid(momentum)) { - if(Verbosity() > 4) + if (Verbosity() > 4) { std::cout << "Invalid momentum of " << momentum.transpose() << std::endl; } continue; } - auto pSurface = Acts::Surface::makeShared( position); + auto pSurface = Acts::Surface::makeShared(position); Acts::Vector4 actsFourPos(position(0), position(1), position(2), 10 * Acts::UnitConstants::ns); Acts::BoundSquareMatrix cov = setDefaultCovariance(); @@ -723,8 +733,10 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) auto trackStateContainer = std::make_shared(); ActsTrackFittingAlgorithm::TrackContainer tracks(trackContainer, trackStateContainer); - if(Verbosity() > 1) - { std::cout << "Calling fitTrack for track with siid " << siid << " tpcid " << tpcid << " crossing " << crossing << std::endl; } + if (Verbosity() > 1) + { + std::cout << "Calling fitTrack for track with siid " << siid << " tpcid " << tpcid << " crossing " << crossing << std::endl; + } auto result = fitTrack(sourceLinks, seed, kfOptions, surfaces, calibrator, tracks); fitTimer.stop(); @@ -761,7 +773,7 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) if (ivary != nvary) { - if(Verbosity() > 3) + if (Verbosity() > 3) { std::cout << "Skipping track fit for trial variation" << std::endl; } @@ -806,7 +818,6 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) if (getTrackFitResult(result, track, &newTrack, tracks, measurements)) { - // insert in dedicated map m_directedTrackMap->insertWithKey(&newTrack, trid); } @@ -822,11 +833,7 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) m_trackMap->insertWithKey(&newTrack, trid); } } // end insert track for normal fit - } // end case where INTT crossing is known - - - - + } // end case where INTT crossing is known } else if (!m_fitSiliconMMs) { @@ -840,7 +847,7 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) << std::endl; } } // end fit failed case - } // end ivary loop + } // end ivary loop trackTimer.stop(); auto trackTime = trackTimer.get_accumulated_time(); @@ -855,10 +862,10 @@ void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel) } bool PHActsTrkFitter::getTrackFitResult( - const FitResult& fitOutput, - TrackSeed* seed, SvtxTrack* track, - const ActsTrackFittingAlgorithm::TrackContainer& tracks, - const ActsTrackFittingAlgorithm::MeasurementContainer& measurements) + const FitResult& fitOutput, + TrackSeed* seed, SvtxTrack* track, + const ActsTrackFittingAlgorithm::TrackContainer& tracks, + const ActsTrackFittingAlgorithm::MeasurementContainer& measurements) { /// Make a trajectory state for storage, which conforms to Acts track fit /// analysis tool @@ -872,12 +879,12 @@ bool PHActsTrkFitter::getTrackFitResult( // retrieve track parameters from fit result Acts::BoundTrackParameters parameters = ActsExamples::TrackParameters(outtrack.referenceSurface().getSharedPtr(), - outtrack.parameters(), outtrack.covariance(), outtrack.particleHypothesis()); + outtrack.parameters(), outtrack.covariance(), outtrack.particleHypothesis()); indexedParams.emplace( - outtrack.tipIndex(), - ActsExamples::TrackParameters{outtrack.referenceSurface().getSharedPtr(), - outtrack.parameters(), outtrack.covariance(), outtrack.particleHypothesis()}); + outtrack.tipIndex(), + ActsExamples::TrackParameters{outtrack.referenceSurface().getSharedPtr(), + outtrack.parameters(), outtrack.covariance(), outtrack.particleHypothesis()}); if (Verbosity() > 2) { @@ -948,66 +955,54 @@ ActsTrackFittingAlgorithm::TrackFitterResult PHActsTrkFitter::fitTrack( { // use direct fit for silicon MM gits or direct navigation if (m_fitSiliconMMs || m_directNavigation) - { return (*m_fitCfg.dFit)(sourceLinks, seed, kfOptions, surfSequence, calibrator, tracks); } + { + return (*m_fitCfg.dFit)(sourceLinks, seed, kfOptions, surfSequence, calibrator, tracks); + } // use full fit in all other cases return (*m_fitCfg.fit)(sourceLinks, seed, kfOptions, calibrator, tracks); } //__________________________________________________________________________________ -SourceLinkVec PHActsTrkFitter::getSurfaceVector(const SourceLinkVec& sourceLinks, SurfacePtrVec& surfaces) const +SourceLinkVec PHActsTrkFitter::filterSourceLinks(const SourceLinkVec& sourceLinks ) const { - SourceLinkVec siliconMMSls; - - // if(Verbosity() > 1) - // std::cout << "Sorting " << sourceLinks.size() << " SLs" << std::endl; - + SourceLinkVec filtered; for (const auto& sl : sourceLinks) { const ActsSourceLink asl = sl.get(); - if (Verbosity() > 1) - { - std::cout << "SL available on : " << asl.geometryId() << std::endl; - } - const auto* const surf = m_tGeometry->geometry().tGeometry->findSurface(asl.geometryId()); - if (m_fitSiliconMMs) - { - // skip TPC surfaces - if (m_tGeometry->maps().isTpcSurface(surf)) - { - continue; - } - // also skip micromegas surfaces if not used - if (m_tGeometry->maps().isMicromegasSurface(surf) && !m_useMicromegas) - { - continue; - } - } + // skip TPC surfaces for fitSilicon MMs + if (m_tGeometry->maps().isTpcSurface(surf) && m_fitSiliconMMs) + { continue; } - if(m_forceSiOnlyFit) - { - if(m_tGeometry->maps().isMicromegasSurface(surf)||m_tGeometry->maps().isTpcSurface(surf)) - { - continue; - } - } + // skip micromegas surfaces if not used + if (m_tGeometry->maps().isMicromegasSurface(surf) && !m_useMicromegas) + { continue; } + + // skip everything but silicons if only silicon fit is required + if (m_forceSiOnlyFit && (m_tGeometry->maps().isMicromegasSurface(surf) || m_tGeometry->maps().isTpcSurface(surf)) ) + { continue; } // update vectors - siliconMMSls.push_back(sl); - surfaces.push_back(surf); + filtered.push_back(sl); } - if (Verbosity() > 10) + return filtered; +} + +//__________________________________________________________________________________ +SurfacePtrVec PHActsTrkFitter::getSurfaceVector(const SourceLinkVec& sourceLinks) const +{ + SurfacePtrVec surfaces; + for (const auto& sl : sourceLinks) { - for (const auto& surf : surfaces) - { - std::cout << "Surface vector : " << surf->geometryId() << std::endl; - } + const ActsSourceLink asl = sl.get(); + const auto* const surf = m_tGeometry->geometry().tGeometry->findSurface(asl.geometryId()); + surfaces.push_back(surf); } - return siliconMMSls; + return surfaces; } void PHActsTrkFitter::checkSurfaceVec(SurfacePtrVec& surfaces) const @@ -1059,10 +1054,10 @@ void PHActsTrkFitter::checkSurfaceVec(SurfacePtrVec& surfaces) const } void PHActsTrkFitter::updateSvtxTrack( - const std::vector& tips, - const Trajectory::IndexedParameters& paramsMap, - const ActsTrackFittingAlgorithm::TrackContainer& tracks, - SvtxTrack* track) + const std::vector& tips, + const Trajectory::IndexedParameters& paramsMap, + const ActsTrackFittingAlgorithm::TrackContainer& tracks, + SvtxTrack* track) { const auto& mj = tracks.trackStateContainer(); @@ -1133,31 +1128,72 @@ void PHActsTrkFitter::updateSvtxTrack( trackStateTimer.restart(); if (m_fillSvtxTrackStates) - { transformer.fillSvtxTrackStates(mj, trackTip, track, m_transient_geocontext); } + { + transformer.fillSvtxTrackStates(mj, trackTip, track, m_transient_geocontext); + } // in using silicon mm fit also extrapolate track parameters to all TPC surfaces with clusters // get all tpc clusters auto* seed = track->get_tpc_seed(); - if( m_fitSiliconMMs && seed ) + if (m_fitSiliconMMs && seed) { - // acts propagator ActsPropagator propagator(m_tGeometry); // loop over cluster keys associated to TPC seed - for( auto key_iter = seed->begin_cluster_keys(); key_iter != seed->end_cluster_keys(); ++key_iter ) + for (auto key_iter = seed->begin_cluster_keys(); key_iter != seed->end_cluster_keys(); ++key_iter) { const auto& cluskey = *key_iter; // make sure cluster is from TPC const auto detId = TrkrDefs::getTrkrId(cluskey); if (detId != TrkrDefs::tpcId) - { continue; } + { + continue; + } // get layer, propagate const auto layer = TrkrDefs::getLayer(cluskey); auto result = propagator.propagateTrack(params, layer); - if( !result.ok() ) { continue; } + if (!result.ok()) + { + continue; + } + + // get path length and extrapolated parameters + auto& [pathLength, trackStateParams] = result.value(); + pathLength /= Acts::UnitConstants::cm; + + // create track state and add to track + transformer.addTrackState(track, cluskey, pathLength, trackStateParams, m_transient_geocontext); + } + } + + // also propagate to Micromegas if not used for the fit + /* this is be used to get unbiased residuals in TPOT */ + if ((!m_useMicromegas) && seed) + { + // acts propagator + ActsPropagator propagator(m_tGeometry); + + // loop over cluster keys associated to TPC seed + for (auto key_iter = seed->begin_cluster_keys(); key_iter != seed->end_cluster_keys(); ++key_iter) + { + const auto& cluskey = *key_iter; + + // make sure cluster is from Micromegas (TPOT) + const auto detId = TrkrDefs::getTrkrId(cluskey); + if (detId != TrkrDefs::micromegasId) + { continue; } + + // get corresponding surface + const auto hitsetkey = TrkrDefs::getHitSetKeyFromClusKey(cluskey); + const auto surface = m_tGeometry->maps().getMMSurface(hitsetkey); + if (!surface) { continue; } + + // propagate + auto result = propagator.propagateTrack(params, surface); + if (!result.ok()) { continue; } // get path length and extrapolated parameters auto& [pathLength, trackStateParams] = result.value(); diff --git a/offline/packages/trackreco/PHActsTrkFitter.h b/offline/packages/trackreco/PHActsTrkFitter.h index c6e0afec35..056c3e88b3 100644 --- a/offline/packages/trackreco/PHActsTrkFitter.h +++ b/offline/packages/trackreco/PHActsTrkFitter.h @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include #include @@ -130,20 +130,21 @@ class PHActsTrkFitter : public SubsysReco void set_track_map_name(const std::string& map_name) { _track_map_name = map_name; } void set_svtx_seed_map_name(const std::string& map_name) { _svtx_seed_map_name = map_name; } - void set_svtx_alignment_state_map_name(const std::string& map_name) { - _svtx_alignment_state_map_name = map_name; - m_alignStates.alignmentStateMap(map_name); + void set_svtx_alignment_state_map_name(const std::string& map_name) + { + _svtx_alignment_state_map_name = map_name; + m_alignStates.alignmentStateMap(map_name); } /// Set flag for pp running void set_pp_mode(bool ispp) { m_pp_mode = ispp; } - void set_enable_geometric_crossing_estimate(bool flag) { m_enable_crossing_estimate = flag ; } + void set_enable_geometric_crossing_estimate(bool flag) { m_enable_crossing_estimate = flag; } void set_use_clustermover(bool use) { m_use_clustermover = use; } void ignoreLayer(int layer) { m_ignoreLayer.insert(layer); } - void setTrkrClusterContainerName(std::string &name){ m_clusterContainerName = name; } + void setTrkrClusterContainerName(const std::string& name) { m_clusterContainerName = name; } void setDirectNavigation(bool flag) { m_directNavigation = flag; } - + void setClusterEdgeRejection(int edge ) { m_cluster_edge_rejection = edge; } private: /// Get all the nodes int getNodes(PHCompositeNode* topNode); @@ -155,26 +156,28 @@ class PHActsTrkFitter : public SubsysReco /// Convert the acts track fit result to an svtx track void updateSvtxTrack( - const std::vector& tips, - const Trajectory::IndexedParameters& paramsMap, - const ActsTrackFittingAlgorithm::TrackContainer& tracks, - SvtxTrack* track); + const std::vector& tips, + const Trajectory::IndexedParameters& paramsMap, + const ActsTrackFittingAlgorithm::TrackContainer& tracks, + SvtxTrack* track); /// Helper function to call either the regular navigation or direct /// navigation, depending on m_fitSiliconMMs ActsTrackFittingAlgorithm::TrackFitterResult fitTrack( - const std::vector& sourceLinks, - const ActsTrackFittingAlgorithm::TrackParameters& seed, - const ActsTrackFittingAlgorithm::GeneralFitterOptions& - kfOptions, - const SurfacePtrVec& surfSequence, - const CalibratorAdapter& calibrator, - ActsTrackFittingAlgorithm::TrackContainer& tracks); - - /// Functions to get list of sorted surfaces for direct navigation, if - /// applicable - SourceLinkVec getSurfaceVector(const SourceLinkVec& sourceLinks, - SurfacePtrVec& surfaces) const; + const std::vector& sourceLinks, + const ActsTrackFittingAlgorithm::TrackParameters& seed, + const ActsTrackFittingAlgorithm::GeneralFitterOptions& kfOptions, + const SurfacePtrVec& surfSequence, + const CalibratorAdapter& calibrator, + ActsTrackFittingAlgorithm::TrackContainer& tracks); + + // remove all source links for detectors that we don't want to include in the fit + SourceLinkVec filterSourceLinks(const SourceLinkVec& sourceLinks ) const; + + /// get list of sorted surfaces for direct navigation, if applicable + SurfacePtrVec getSurfaceVector(const SourceLinkVec& sourceLinks) const; + + /// check ordering of the surfaces void checkSurfaceVec(SurfacePtrVec& surfaces) const; bool getTrackFitResult(const FitResult& fitOutput, TrackSeed* seed, @@ -240,9 +243,10 @@ class PHActsTrkFitter : public SubsysReco // max variation of bunch crossing away from crossing_estimate short int max_bunch_search = 2; - //name of TRKR_CLUSTER container + // name of TRKR_CLUSTER container std::string m_clusterContainerName = "TRKR_CLUSTER"; + int m_cluster_edge_rejection = 0; //!@name evaluator //@{ bool m_actsEvaluator = false; @@ -253,7 +257,7 @@ class PHActsTrkFitter : public SubsysReco //@} //! tracks -// SvtxTrackMap* m_seedTracks = nullptr; + // SvtxTrackMap* m_seedTracks = nullptr; //! tpc global position wrapper TpcGlobalPositionWrapper m_globalPositionWrapper; @@ -268,7 +272,7 @@ class PHActsTrkFitter : public SubsysReco int _n_iteration = 0; std::string _track_map_name = "SvtxTrackMap"; std::string _svtx_seed_map_name = "SvtxTrackSeedContainer"; - std::string _svtx_alignment_state_map_name = "SvtxAlignmentStateMap"; + std::string _svtx_alignment_state_map_name = "SvtxAlignmentStateMap"; /// Default particle assumption to pion unsigned int m_pHypothesis = 211; @@ -292,14 +296,18 @@ class PHActsTrkFitter : public SubsysReco std::vector m_materialSurfaces = {}; - struct MaterialSurfaceSelector { + struct MaterialSurfaceSelector + { std::vector surfaces = {}; /// @param surface is the test surface - void operator()(const Acts::Surface* surface) { - if (surface->surfaceMaterial() != nullptr) { + void operator()(const Acts::Surface* surface) + { + if (surface->surfaceMaterial() != nullptr) + { if (std::find(surfaces.begin(), surfaces.end(), surface) == - surfaces.end()) { + surfaces.end()) + { surfaces.push_back(surface); } } diff --git a/offline/packages/trackreco/PHMicromegasTpcTrackMatching.cc b/offline/packages/trackreco/PHMicromegasTpcTrackMatching.cc index 197d7039e3..a6294c7ff0 100644 --- a/offline/packages/trackreco/PHMicromegasTpcTrackMatching.cc +++ b/offline/packages/trackreco/PHMicromegasTpcTrackMatching.cc @@ -889,12 +889,12 @@ int PHMicromegasTpcTrackMatching::GetNodes(PHCompositeNode* topNode) } else { - _cluster_map = findNode::getClass(topNode, "TRKR_CLUSTER"); + _cluster_map = findNode::getClass(topNode, _clustermap_name); } if (!_cluster_map) { - std::cerr << PHWHERE << " ERROR: Can't find node TRKR_CLUSTER" << std::endl; + std::cerr << PHWHERE << " ERROR: Can't find node " << _clustermap_name << std::endl; return Fun4AllReturnCodes::ABORTEVENT; } diff --git a/offline/packages/trackreco/PHMicromegasTpcTrackMatching.h b/offline/packages/trackreco/PHMicromegasTpcTrackMatching.h index 58d2004041..7f9f8e2611 100644 --- a/offline/packages/trackreco/PHMicromegasTpcTrackMatching.h +++ b/offline/packages/trackreco/PHMicromegasTpcTrackMatching.h @@ -42,13 +42,13 @@ class PHMicromegasTpcTrackMatching : public SubsysReco void set_pt_cut( const float pt) { _pt_cut = pt; } void set_dphi_cut( const float dphi) { _dphi_cut = dphi; } void SetIteration(int iter) { _n_iteration = iter; } - + void set_clustermap_name(const std::string& name) { _clustermap_name = name; } void zeroField(const bool flag) { _zero_field = flag; } int Init(PHCompositeNode* topNode) override; int InitRun(PHCompositeNode* topNode) override; int process_event(PHCompositeNode*) override; int End(PHCompositeNode*) override; - + // deprecated calls inline void set_sc_calib_mode(const bool) {} inline void set_collision_rate(const double) {} @@ -89,6 +89,8 @@ class PHMicromegasTpcTrackMatching : public SubsysReco TrackSeedContainer* _tpc_track_map{nullptr}; TrackSeedContainer* _si_track_map{nullptr}; + std::string _clustermap_name = "TRKR_CLUSTER"; + //! default rphi search window for each layer std::array _rphi_search_win{0.25, 13.0}; diff --git a/offline/packages/trackreco/PHSiliconSeedMerger.cc b/offline/packages/trackreco/PHSiliconSeedMerger.cc index 16c0848456..c2e2d3e9b4 100644 --- a/offline/packages/trackreco/PHSiliconSeedMerger.cc +++ b/offline/packages/trackreco/PHSiliconSeedMerger.cc @@ -1,4 +1,3 @@ - #include "PHSiliconSeedMerger.h" #include @@ -14,34 +13,67 @@ #include #include -#include - -//____________________________________________________________________________.. +/** + * @brief Construct a PHSiliconSeedMerger with the given subsystem name. + * + * Initializes the PHSiliconSeedMerger and forwards the provided subsystem + * name to the base SubsysReco constructor. + * + * @param name Subsystem name used to register this module in the node tree. + */ PHSiliconSeedMerger::PHSiliconSeedMerger(const std::string& name) : SubsysReco(name) { } -//____________________________________________________________________________.. -PHSiliconSeedMerger::~PHSiliconSeedMerger() -{ -} +/** + * @brief Default destructor for PHSiliconSeedMerger. + * + * Performs default cleanup of the merger object and its owned resources. + */ +PHSiliconSeedMerger::~PHSiliconSeedMerger() = default; -//____________________________________________________________________________.. -int PHSiliconSeedMerger::Init(PHCompositeNode*) +/** + * @brief Perform module initialization (no operation required). + * + * This implementation does not perform any setup and always succeeds. + * + * @return int `EVENT_OK` indicating initialization succeeded. + */ +int PHSiliconSeedMerger::Init(PHCompositeNode* /*unused*/) { return Fun4AllReturnCodes::EVENT_OK; } -//____________________________________________________________________________.. +/** + * @brief Initializes run-time resources by retrieving required nodes. + * + * Calls getNodes(topNode) to locate and cache containers needed for processing this run. + * + * @param topNode Root of the node tree from which required nodes are retrieved. + * @return int `EVENT_OK` on success, `ABORTEVENT` or another non-zero code on failure. + */ int PHSiliconSeedMerger::InitRun(PHCompositeNode* topNode) { int ret = getNodes(topNode); return ret; } -//____________________________________________________________________________.. -int PHSiliconSeedMerger::process_event(PHCompositeNode*) +/** + * @brief Merge overlapping silicon seed tracks by consolidating MVTX cluster keys. + * + * Detects seeds whose MVTX cluster key sets fully overlap (one set equals the + * intersection) and treats one seed as a duplicate of the other. The merger + * preserves the seed with the larger MVTX key set; if both seeds share the + * same MVTX strobe and seed merging is enabled, the smaller seed's MVTX keys + * are merged into the preserved seed. After consolidation, duplicate seeds are + * erased from the silicon track container and preserved seeds are updated to + * include any newly merged MVTX cluster keys. + * + * @return Fun4AllReturnCodes::EVENT_OK on successful processing. + * + */ +int PHSiliconSeedMerger::process_event(PHCompositeNode* /*unused*/) { std::multimap> matches; std::set seedsToDelete; @@ -56,8 +88,7 @@ int PHSiliconSeedMerger::process_event(PHCompositeNode*) ++track1ID) { TrackSeed* track1 = m_siliconTracks->get(track1ID); - - if (seedsToDelete.find(track1ID) != seedsToDelete.end()) + if (seedsToDelete.contains(track1ID)) { continue; } @@ -74,7 +105,10 @@ int PHSiliconSeedMerger::process_event(PHCompositeNode*) { continue; } - track1Strobe = MvtxDefs::getStrobeId(ckey); + if (TrkrDefs::getTrkrId(ckey) == TrkrDefs::TrkrId::mvtxId) + { + track1Strobe = MvtxDefs::getStrobeId(ckey); + } mvtx1Keys.insert(ckey); } @@ -90,7 +124,6 @@ int PHSiliconSeedMerger::process_event(PHCompositeNode*) { continue; } - TrackSeed* track2 = m_siliconTracks->get(track2ID); if (track2 == nullptr) { @@ -110,7 +143,10 @@ int PHSiliconSeedMerger::process_event(PHCompositeNode*) continue; } mvtx2Keys.insert(ckey); - track2Strobe = MvtxDefs::getStrobeId(ckey); + if (TrkrDefs::getTrkrId(ckey) == TrkrDefs::TrkrId::mvtxId) + { + track2Strobe = MvtxDefs::getStrobeId(ckey); + } } std::vector intersection; @@ -120,19 +156,18 @@ int PHSiliconSeedMerger::process_event(PHCompositeNode*) mvtx2Keys.end(), std::back_inserter(intersection)); - /// If we have two clusters in common in the triplet, it is likely - /// from the same track - if (intersection.size() > m_clusterOverlap && track1Strobe == track2Strobe) + /// If the intersection fully encompasses one of the tracks, it is completely duplicated + if (intersection.size() == mvtx1Keys.size() || intersection.size() == mvtx2Keys.size()) { if (Verbosity() > 2) { std::cout << "Track " << track1ID << " keys " << std::endl; - for (auto& key : mvtx1Keys) + for (const auto& key : mvtx1Keys) { std::cout << " ckey: " << key << std::endl; } std::cout << "Track " << track2ID << " keys " << std::endl; - for (auto& key : mvtx2Keys) + for (const auto& key : mvtx2Keys) { std::cout << " ckey: " << key << std::endl; } @@ -143,47 +178,64 @@ int PHSiliconSeedMerger::process_event(PHCompositeNode*) } } - for (auto& key : mvtx2Keys) + /// one of the tracks is encompassed in the other. Take the larger one + std::set keysToKeep; + if (mvtx1Keys.size() >= mvtx2Keys.size()) { - mvtx1Keys.insert(key); + keysToKeep = mvtx1Keys; + if (track1Strobe == track2Strobe && m_mergeSeeds) + { + keysToKeep.insert(mvtx2Keys.begin(), mvtx2Keys.end()); + } + matches.insert(std::make_pair(track1ID, keysToKeep)); + seedsToDelete.insert(track2ID); + if (Verbosity() > 2) + { + std::cout << " will delete seed " << track2ID << std::endl; + } } - - if (Verbosity() > 2) + else { - std::cout << "Match IDed" << std::endl; - for (auto& key : mvtx1Keys) + keysToKeep = mvtx2Keys; + if (track1Strobe == track2Strobe && m_mergeSeeds) { - std::cout << " total track keys " << key << std::endl; + keysToKeep.insert(mvtx1Keys.begin(), mvtx1Keys.end()); + } + matches.insert(std::make_pair(track2ID, keysToKeep)); + seedsToDelete.insert(track1ID); + if (Verbosity() > 2) + { + std::cout << " will delete seed " << track1ID << std::endl; } } - - matches.insert(std::make_pair(track1ID, mvtx1Keys)); - seedsToDelete.insert(track2ID); - break; } } } - for (const auto& [trackKey, mvtxKeys] : matches) + if (m_mergeSeeds) { - auto track = m_siliconTracks->get(trackKey); - if (Verbosity() > 2) + for (const auto& [trackKey, mvtxKeys] : matches) { - std::cout << "original track: " << std::endl; - track->identify(); - } + auto* track = m_siliconTracks->get(trackKey); + if (Verbosity() > 2) + { + std::cout << "original track: " << std::endl; + track->identify(); + } - for (auto& key : mvtxKeys) - { - if (track->find_cluster_key(key) == track->end_cluster_keys()) + for (const auto& key : mvtxKeys) { - track->insert_cluster_key(key); - if (Verbosity() > 2) - std::cout << "adding " << key << std::endl; + if (track->find_cluster_key(key) == track->end_cluster_keys()) + { + track->insert_cluster_key(key); + if (Verbosity() > 2) + { + std::cout << "adding " << key << std::endl; + } + } } } } - for (const auto& key : seedsToDelete) { if (Verbosity() > 2) @@ -195,31 +247,47 @@ int PHSiliconSeedMerger::process_event(PHCompositeNode*) if (Verbosity() > 2) { - for (const auto& seed : *m_siliconTracks) - { - if (!seed) continue; - seed->identify(); - } + printRemainingDuplicates(); } return Fun4AllReturnCodes::EVENT_OK; } -//____________________________________________________________________________.. -int PHSiliconSeedMerger::ResetEvent(PHCompositeNode*) +/** + * @brief Reset per-event state for the merger. + * + * This implementation performs no per-event cleanup and always reports success. + * + * @return Integer status code: `Fun4AllReturnCodes::EVENT_OK`. + */ +int PHSiliconSeedMerger::ResetEvent(PHCompositeNode* /*unused*/) { return Fun4AllReturnCodes::EVENT_OK; } -//____________________________________________________________________________.. -int PHSiliconSeedMerger::End(PHCompositeNode*) +/** + * @brief Perform end-of-run shutdown for the silicon seed merger. + * + * @return int EVENT_OK on successful completion. + */ +int PHSiliconSeedMerger::End(PHCompositeNode* /*unused*/) { return Fun4AllReturnCodes::EVENT_OK; } +/** + * @brief Retrieve required nodes from the top-level node tree and validate availability. + * + * Locates the silicon TrackSeedContainer using m_trackMapName and stores it in + * m_siliconTracks. If the container is not found, the function logs an error + * message and signals an abort for the current event. + * + * @param topNode Root node used to search for the TrackSeedContainer. + * @return int Fun4AllReturnCodes::EVENT_OK on success, Fun4AllReturnCodes::ABORTEVENT if the silicon TrackSeedContainer is not present. + */ int PHSiliconSeedMerger::getNodes(PHCompositeNode* topNode) { - m_siliconTracks = findNode::getClass(topNode, m_trackMapName.c_str()); + m_siliconTracks = findNode::getClass(topNode, m_trackMapName); if (!m_siliconTracks) { std::cout << PHWHERE << "No silicon track container, can't merge seeds" @@ -229,3 +297,84 @@ int PHSiliconSeedMerger::getNodes(PHCompositeNode* topNode) return Fun4AllReturnCodes::EVENT_OK; } + +void PHSiliconSeedMerger::printRemainingDuplicates() +{ + for (unsigned int track1ID = 0; + track1ID != m_siliconTracks->size(); + ++track1ID) + { + std::set mvtx1Keyscheck; + + TrackSeed* seed = m_siliconTracks->get(track1ID); + if (!seed) + { + continue; + } + int strobe1 = -9999; + for (auto iter = seed->begin_cluster_keys(); + iter != seed->end_cluster_keys(); + ++iter) + { + mvtx1Keyscheck.insert(*iter); + if (TrkrDefs::getTrkrId(*iter) == TrkrDefs::mvtxId) + { + strobe1 = MvtxDefs::getStrobeId(*iter); + } + } + + for (unsigned int track2ID = 0; + track2ID != m_siliconTracks->size(); + ++track2ID) + { + std::set mvtx2Keyscheck; + TrackSeed* seed2 = m_siliconTracks->get(track2ID); + if (!seed2) + { + continue; + } + int strobe2 = -9999; + for (auto iter2 = seed2->begin_cluster_keys(); + iter2 != seed2->end_cluster_keys(); + ++iter2) + { + mvtx2Keyscheck.insert(*iter2); + if (TrkrDefs::getTrkrId(*iter2) == TrkrDefs::mvtxId) + { + strobe2 = MvtxDefs::getStrobeId(*iter2); + } + } + std::vector intersectioncheck; + std::set_intersection(mvtx1Keyscheck.begin(), + mvtx1Keyscheck.end(), + mvtx2Keyscheck.begin(), + mvtx2Keyscheck.end(), + std::back_inserter(intersectioncheck)); + if (track1ID != track2ID) + { + if (intersectioncheck.size() == mvtx1Keyscheck.size() || intersectioncheck.size() == mvtx2Keyscheck.size()) + { + std::cout << "After merge, still have duplicate seeds: " + << " seed1 ID " << track1ID << " strobe " << strobe1 << " nkeys " << mvtx1Keyscheck.size() + << " seed2 ID " << track2ID << " strobe " << strobe2 << " nkeys " << mvtx2Keyscheck.size() + << " intersection size " << intersectioncheck.size() + << std::endl; + std::cout << "seed 1 keys " << std::endl; + std::cout << " "; + for (const auto& key : mvtx1Keyscheck) + { + std::cout << key << ", "; + } + std::cout << std::endl; + std::cout << "seed 2 keys " << std::endl; + std::cout << " "; + for (const auto& key : mvtx2Keyscheck) + { + std::cout << key << ", "; + } + std::cout << std::endl; + } + } + } + } +} \ No newline at end of file diff --git a/offline/packages/trackreco/PHSiliconSeedMerger.h b/offline/packages/trackreco/PHSiliconSeedMerger.h index b8227cd581..b07551977d 100644 --- a/offline/packages/trackreco/PHSiliconSeedMerger.h +++ b/offline/packages/trackreco/PHSiliconSeedMerger.h @@ -25,17 +25,52 @@ class PHSiliconSeedMerger : public SubsysReco int ResetEvent(PHCompositeNode *topNode) override; int End(PHCompositeNode *topNode) override; + /** + * Set the name of the track seed container to use when retrieving silicon tracks. + * + * @param name Name of the TrackSeedContainer node (defaults to "SiliconTrackSeedContainer"). + */ void trackMapName(const std::string &name) { m_trackMapName = name; } + /** + * Set the maximum number of overlapping clusters considered during seed merging. + * @param nclusters Maximum number of clusters that may overlap (overlap threshold). + */ void clusterOverlap(const unsigned int nclusters) { m_clusterOverlap = nclusters; } + /** + * @brief Allow merging searches to include the INTT detector. + * + * Configure the merger to include INTT clusters in subsequent processing by disabling the MVTX-only restriction. + */ void searchIntt() { m_mvtxOnly = false; } + /** + * Enable merging of silicon seed tracks during event processing. + * + * When enabled, the module will merge overlapping silicon seed tracks where applicable. + */ + void mergeSeeds() { m_mergeSeeds = true; } private: int getNodes(PHCompositeNode *topNode); - + void printRemainingDuplicates(); TrackSeedContainer *m_siliconTracks{nullptr}; std::string m_trackMapName{"SiliconTrackSeedContainer"}; + /** + * Minimum number of clusters that must be shared between two silicon track seeds + * for them to be considered overlapping. + * + * Defaults to 1. + */ unsigned int m_clusterOverlap{1}; - bool m_mvtxOnly{true}; + + bool m_mergeSeeds{false}; + /** + * Restrict seed processing to the MVTX detector only. + * + * When set to `true`, operations that iterate or merge silicon seed tracks + * will be limited to clusters originating from the MVTX vertex detector. + * When `false`, clusters from other silicon detectors are included. + */ + bool m_mvtxOnly{false}; }; #endif // PHSILICONSEEDMERGER_H diff --git a/offline/packages/trackreco/PHSiliconTpcTrackMatching.cc b/offline/packages/trackreco/PHSiliconTpcTrackMatching.cc index 2e66a6df28..6aaae4bf93 100644 --- a/offline/packages/trackreco/PHSiliconTpcTrackMatching.cc +++ b/offline/packages/trackreco/PHSiliconTpcTrackMatching.cc @@ -445,10 +445,10 @@ int PHSiliconTpcTrackMatching::GetNodes(PHCompositeNode *topNode) svtxNode->addNode(node); } - _cluster_map = findNode::getClass(topNode, "TRKR_CLUSTER"); + _cluster_map = findNode::getClass(topNode, _cluster_map_name); if (!_cluster_map) { - std::cout << PHWHERE << " ERROR: Can't find node TRKR_CLUSTER" << std::endl; + std::cout << PHWHERE << " ERROR: Can't find node " <<_cluster_map_name << std::endl; return Fun4AllReturnCodes::ABORTEVENT; } diff --git a/offline/packages/trackreco/PHSiliconTpcTrackMatching.h b/offline/packages/trackreco/PHSiliconTpcTrackMatching.h index acb157bd83..6de4a1dd3a 100644 --- a/offline/packages/trackreco/PHSiliconTpcTrackMatching.h +++ b/offline/packages/trackreco/PHSiliconTpcTrackMatching.h @@ -139,7 +139,10 @@ class PHSiliconTpcTrackMatching : public SubsysReco, public PHParameterInterface void set_file_name(const std::string &name) { _file_name = name; } void set_pp_mode(const bool flag) { _pp_mode = flag; } void set_use_intt_crossing(const bool flag) { _use_intt_crossing = flag; } - + void set_cluster_map_name(const std::string &name) + { + _cluster_map_name = name; + } int InitRun(PHCompositeNode *topNode) override; int process_event(PHCompositeNode *) override; @@ -210,6 +213,7 @@ class PHSiliconTpcTrackMatching : public SubsysReco, public PHParameterInterface int _n_iteration = 0; std::string _track_map_name = "TpcTrackSeedContainer"; std::string _silicon_track_map_name = "SiliconTrackSeedContainer"; + std::string _cluster_map_name = "TRKR_CLUSTER"; std::string m_fieldMap = "1.4"; std::vector getTrackletClusterList(TrackSeed* tracklet); }; diff --git a/offline/packages/trackreco/PHSimpleVertexFinder.cc b/offline/packages/trackreco/PHSimpleVertexFinder.cc index 3d3e4a9fda..5f9340d8f6 100644 --- a/offline/packages/trackreco/PHSimpleVertexFinder.cc +++ b/offline/packages/trackreco/PHSimpleVertexFinder.cc @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include @@ -263,7 +263,7 @@ int PHSimpleVertexFinder::process_event(PHCompositeNode * /*topNode*/) { unsigned int thisid = it + vertex_id; // the address of the vertex in the event - auto svtxVertex = std::make_unique(); + auto svtxVertex = std::make_unique(); svtxVertex->set_chisq(0.0); svtxVertex->set_ndof(0); diff --git a/offline/packages/trackreco/PHSimpleVertexFinder.h b/offline/packages/trackreco/PHSimpleVertexFinder.h index da0e36fabf..de5cff940b 100644 --- a/offline/packages/trackreco/PHSimpleVertexFinder.h +++ b/offline/packages/trackreco/PHSimpleVertexFinder.h @@ -54,7 +54,7 @@ class PHSimpleVertexFinder : public SubsysReco void setTrackMapName(const std::string &name) { _track_map_name = name; } void setVertexMapName(const std::string &name) { _vertex_map_name = name; } void zeroField(const bool flag) { _zero_field = flag; } - void setTrkrClusterContainerName(std::string &name){ m_clusterContainerName = name; } + void setTrkrClusterContainerName(const std::string &name){ m_clusterContainerName = name; } void set_pp_mode(bool mode) { _pp_mode = mode; } private: @@ -91,7 +91,7 @@ class PHSimpleVertexFinder : public SubsysReco double _beamline_y_cut_hi = 0.2; double _qual_cut = 10.0; bool _require_mvtx = true; - unsigned int _nmvtx_required = 3; + unsigned int _nmvtx_required = 2; double _track_pt_cut = 0.0; double _outlier_cut = 0.015; diff --git a/offline/packages/trackreco/PHTpcDeltaZCorrection.h b/offline/packages/trackreco/PHTpcDeltaZCorrection.h index 46d099f587..4d383cc854 100644 --- a/offline/packages/trackreco/PHTpcDeltaZCorrection.h +++ b/offline/packages/trackreco/PHTpcDeltaZCorrection.h @@ -32,7 +32,7 @@ class PHTpcDeltaZCorrection : public SubsysReco, public PHParameterInterface int process_event(PHCompositeNode *topNode) override; int End(PHCompositeNode *topNode) override; void SetDefaultParameters() override; - void setTrkrClusterContainerName(std::string &name) { m_clusterContainerName = name; } + void setTrkrClusterContainerName(const std::string &name) { m_clusterContainerName = name; } private: /// load nodes diff --git a/offline/packages/trackreco/WeightedFitter.cc b/offline/packages/trackreco/WeightedFitter.cc index af7677f5b8..e35919c479 100644 --- a/offline/packages/trackreco/WeightedFitter.cc +++ b/offline/packages/trackreco/WeightedFitter.cc @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include diff --git a/offline/packages/trigger/CaloTriggerEmulator.cc b/offline/packages/trigger/CaloTriggerEmulator.cc index eaf00e4f33..9397288033 100644 --- a/offline/packages/trigger/CaloTriggerEmulator.cc +++ b/offline/packages/trigger/CaloTriggerEmulator.cc @@ -1767,8 +1767,17 @@ int CaloTriggerEmulator::process_organizer() } TriggerDefs::TriggerSumKey jet_skey = (*iter_sum).first; - - TriggerDefs::TriggerSumKey hcal_skey = TriggerDefs::getTriggerSumKey(TriggerDefs::TriggerId::jetTId, TriggerDefs::GetDetectorId("HCAL"), TriggerDefs::GetPrimitiveId("JET"), TriggerDefs::getPrimitiveLocId_from_TriggerPrimKey(jet_pkey), TriggerDefs::getSumLocId(jet_skey)); + uint16_t jet_sum_loc = TriggerDefs::getSumLocId(jet_skey); + uint16_t jet_prim_loc = TriggerDefs::getPrimitiveLocId_from_TriggerSumKey(jet_skey); + if (jet_prim_loc >= 12) + { + uint16_t sumeta = TriggerDefs::getSumEtaId(jet_skey); + uint16_t sumphi = TriggerDefs::getSumPhiId(jet_skey); + jet_sum_loc = sumphi%2 + sumeta*2; + } + TriggerDefs::TriggerSumKey hcal_skey = TriggerDefs::getTriggerSumKey(TriggerDefs::TriggerId::jetTId, TriggerDefs::GetDetectorId("HCAL"), TriggerDefs::GetPrimitiveId("JET"), TriggerDefs::getPrimitiveLocId_from_TriggerPrimKey(jet_pkey), jet_sum_loc); + + TriggerDefs::TriggerSumKey emcal_skey = TriggerDefs::getTriggerSumKey(TriggerDefs::TriggerId::jetTId, TriggerDefs::GetDetectorId("EMCAL"), TriggerDefs::GetPrimitiveId("JET"), TriggerDefs::getPrimitiveLocId_from_TriggerPrimKey(jet_pkey), TriggerDefs::getSumLocId(jet_skey)); int i = 0; diff --git a/offline/packages/trigger/MinimumBiasClassifier.cc b/offline/packages/trigger/MinimumBiasClassifier.cc index b9e7f18460..c36a9430e1 100644 --- a/offline/packages/trigger/MinimumBiasClassifier.cc +++ b/offline/packages/trigger/MinimumBiasClassifier.cc @@ -39,6 +39,29 @@ int MinimumBiasClassifier::InitRun(PHCompositeNode *topNode) { std::cout << __FILE__ << " :: " << __FUNCTION__ << std::endl; } + + if (m_species == MinimumBiasInfo::SPECIES::AUAU) + { + m_useZDC = true; + m_max_charge_cut = 2100; + m_box_cut = true; + m_hit_cut = 2; + } + if (m_species == MinimumBiasInfo::SPECIES::OO) + { + m_useZDC = false; + m_max_charge_cut = 300; + m_box_cut = false; + m_hit_cut = 1; + } + if (m_species == MinimumBiasInfo::SPECIES::PP) + { + m_useZDC = false; + m_max_charge_cut = 300; + m_box_cut = false; + m_hit_cut = 1; + } + CDBInterface *m_cdb = CDBInterface::instance(); std::string centscale_url = m_cdb->getUrl("CentralityScale"); @@ -132,7 +155,7 @@ int MinimumBiasClassifier::FillMinimumBiasInfo() { std::cout << "Getting ZDC" << std::endl; } - if (!m_issim) + if (!m_issim && m_useZDC) { if (!m_zdcinfo) { @@ -169,7 +192,7 @@ int MinimumBiasClassifier::FillMinimumBiasInfo() } // MBD Background cut - if (m_mbd_charge_sum[1] < m_mbd_north_cut && m_mbd_charge_sum[0] > m_mbd_south_cut && minbiascheck) + if (m_box_cut && m_mbd_charge_sum[1] < m_mbd_north_cut && m_mbd_charge_sum[0] > m_mbd_south_cut && minbiascheck) { minbiascheck = false; // m_mb_info->setIsAuAuMinimumBias(false); @@ -179,13 +202,13 @@ int MinimumBiasClassifier::FillMinimumBiasInfo() // Mbd two hit requirement and ZDC energy sum coincidence requirement for (int iside = 0; iside < 2; iside++) { - if (m_mbd_hit[iside] < 2 && minbiascheck) + if (m_mbd_hit[iside] < m_hit_cut && minbiascheck) { minbiascheck = false; // m_mb_info->setIsAuAuMinimumBias(false); // return Fun4AllReturnCodes::EVENT_OK; } - if (!m_issim) + if (!m_issim && m_useZDC) { if (m_zdcinfo->get_zdc_energy(iside) <= m_zdc_cut && minbiascheck) { @@ -195,7 +218,7 @@ int MinimumBiasClassifier::FillMinimumBiasInfo() } } } - if ((m_mbd_charge_sum[0] + m_mbd_charge_sum[1]) > 2100 && minbiascheck) + if ((m_mbd_charge_sum[0] + m_mbd_charge_sum[1]) > m_max_charge_cut && minbiascheck) { minbiascheck = false; // m_mb_info->setIsAuAuMinimumBias(false); @@ -254,7 +277,7 @@ int MinimumBiasClassifier::GetNodes(PHCompositeNode *topNode) return Fun4AllReturnCodes::ABORTRUN; } - if (!m_issim) + if (!m_issim && m_useZDC) { m_zdcinfo = findNode::getClass(topNode, "Zdcinfo"); if (Verbosity()) diff --git a/offline/packages/trigger/MinimumBiasClassifier.h b/offline/packages/trigger/MinimumBiasClassifier.h index f84add84f8..5f32c10a62 100644 --- a/offline/packages/trigger/MinimumBiasClassifier.h +++ b/offline/packages/trigger/MinimumBiasClassifier.h @@ -8,6 +8,7 @@ #include #include +#include "MinimumBiasInfo.h" // Forward declarations class MinimumBiasInfo; @@ -21,6 +22,8 @@ class MinimumBiasClassifier : public SubsysReco { public: //! constructor + + explicit MinimumBiasClassifier(const std::string &name = "MinimumBiasClassifier"); //! destructor @@ -56,8 +59,17 @@ class MinimumBiasClassifier : public SubsysReco } void setIsSim(const bool sim) { m_issim = sim; } + void setSpecies(MinimumBiasInfo::SPECIES spec) { m_species = spec; }; + private: bool m_issim{false}; + bool m_useZDC{true}; + bool m_box_cut{true}; + int m_hit_cut{2}; + double m_max_charge_cut{2100}; + + MinimumBiasInfo::SPECIES m_species{MinimumBiasInfo::SPECIES::AUAU}; + float getVertexScale(); std::string m_dbfilename; diff --git a/offline/packages/trigger/MinimumBiasInfo.h b/offline/packages/trigger/MinimumBiasInfo.h index 8cd8472e87..94f38b1a8d 100644 --- a/offline/packages/trigger/MinimumBiasInfo.h +++ b/offline/packages/trigger/MinimumBiasInfo.h @@ -6,6 +6,14 @@ class MinimumBiasInfo : public PHObject { public: + + enum SPECIES + { + AUAU = 0, + OO = 1, + PP = 2 + }; + ~MinimumBiasInfo() override {}; void identify(std::ostream &os = std::cout) const override { os << "MinimumBiasInfo base class" << std::endl; }; diff --git a/simulation/g4simulation/g4bbc/MbdVertexFastSimReco.cc b/simulation/g4simulation/g4bbc/MbdVertexFastSimReco.cc index 45458b9b49..97f801771c 100644 --- a/simulation/g4simulation/g4bbc/MbdVertexFastSimReco.cc +++ b/simulation/g4simulation/g4bbc/MbdVertexFastSimReco.cc @@ -2,7 +2,7 @@ #include "MbdVertexFastSimReco.h" #include -#include +#include #include #include @@ -95,7 +95,7 @@ int MbdVertexFastSimReco::process_event(PHCompositeNode *topNode) return Fun4AllReturnCodes::EVENT_OK; } - MbdVertex *vertex = new MbdVertexv2(); + MbdVertex *vertex = new MbdVertexv3(); if (m_T_Smear >= 0.0) { diff --git a/simulation/g4simulation/g4detectors/CreateG4Subsystem.pl b/simulation/g4simulation/g4detectors/CreateG4Subsystem.pl index f74af6957d..a1dbd352c3 100755 --- a/simulation/g4simulation/g4detectors/CreateG4Subsystem.pl +++ b/simulation/g4simulation/g4detectors/CreateG4Subsystem.pl @@ -1007,7 +1007,7 @@ () print F "dnl no point in suppressing warnings people should \n"; print F "dnl at least see them, so here we go for g++: -Wall\n"; print F "if test \$ac_cv_prog_gxx = yes; then\n"; - print F " CXXFLAGS=\"\$CXXFLAGS -Wall -Werror\"\n"; + print F " CXXFLAGS=\"\$CXXFLAGS -Wall -Wextra -Wshadow -Werror\"\n"; print F "fi\n"; print F "\n"; @@ -1027,8 +1027,8 @@ () print F "AM_CPPFLAGS = \\\n"; print F " -I\$(includedir) \\\n"; - print F " -I\$(OFFLINE_MAIN)/include \\\n"; - print F " -I\$(ROOTSYS)/include \n"; + print F " -isystem\$(OFFLINE_MAIN)/include \\\n"; + print F " -isystem\$(ROOTSYS)/include \n"; print F "\n"; print F "AM_LDFLAGS = \\\n"; diff --git a/simulation/g4simulation/g4dst/Makefile.am b/simulation/g4simulation/g4dst/Makefile.am index 7ea76582d4..3bb3eb1a17 100644 --- a/simulation/g4simulation/g4dst/Makefile.am +++ b/simulation/g4simulation/g4dst/Makefile.am @@ -11,6 +11,7 @@ lib_LTLIBRARIES = \ libg4dst_la_LDFLAGS = \ -L$(libdir) \ -L$(OFFLINE_MAIN)/lib \ + -lbcolumicount_io \ -lcalo_io \ -lcalotrigger_io \ -lcentrality_io \ diff --git a/simulation/g4simulation/g4main/PHG4TruthTrackingAction.cc b/simulation/g4simulation/g4main/PHG4TruthTrackingAction.cc index 4db6ecbd51..614712d4d3 100644 --- a/simulation/g4simulation/g4main/PHG4TruthTrackingAction.cc +++ b/simulation/g4simulation/g4main/PHG4TruthTrackingAction.cc @@ -305,28 +305,58 @@ PHG4Particle* PHG4TruthTrackingAction::AddParticle(PHG4TruthInfoContainer& truth return truth.AddParticle(trackid, ti)->second; } +/** + * @brief Create or retrieve a truth vertex for a Geant4 track keyed by position and production process. + * + * Uses the track vertex position combined with the mapped MC production process to look up an existing + * vertex or create a new PHG4VtxPoint and register it in the truth container. The vertex index is chosen + * positive for primary tracks and negative for secondaries. + * + * @param truth Container in which to find or register the vertex. + * @param track Geant4 track whose production vertex and creator process determine the vertex key. + * @return PHG4VtxPoint* Pointer to the vertex instance stored in the truth container. + */ PHG4VtxPoint* PHG4TruthTrackingAction::AddVertex(PHG4TruthInfoContainer& truth, const G4Track& track) { G4ThreeVector v = track.GetVertexPosition(); + + // Get G4Track creator process FIRST (needed for vertex map key) + const auto* const g4Process = track.GetCreatorProcess(); + // Convert G4 Process to MC process + const auto process = PHG4ProcessMapPhysics::Instance().GetMCProcess(g4Process); + int vtxindex = (track.GetParentID() == 0 ? truth.maxvtxindex() + 1 : truth.minvtxindex() - 1); - auto [iter, inserted] = m_VertexMap.insert(std::make_pair(v, vtxindex)); + // Use (position, process) as key to distinguish vertices at same location but different processes + // This is important for cases like K0 -> K0_S/K0_L mixing where particles are produced + // at the same position but by different physics processes + auto key = std::make_pair(v, process); + auto [iter, inserted] = m_VertexMap.insert(std::make_pair(key, vtxindex)); // If could not add a unique vertex => return the existing one if (!inserted) { return truth.GetVtxMap().find(iter->second)->second; } - // get G4Track creator process - const auto* const g4Process = track.GetCreatorProcess(); - // convert G4 Process to MC process - const auto process = PHG4ProcessMapPhysics::Instance().GetMCProcess(g4Process); - // otherwise, create and add a new one + + // Create and add a new vertex PHG4VtxPoint* vtxpt = new PHG4VtxPointv2(v[0] / cm, v[1] / cm, v[2] / cm, track.GetGlobalTime() / ns, vtxindex, process); return truth.AddVertex(vtxindex, vtxpt)->second; } +/** + * @brief Determine whether a PHG4Particle should be considered an sPHENIX primary. + * + * Evaluates the particle's production vertex, PDG id longevity, and ancestry to decide + * if it originates as an sPHENIX primary (produced as a primary or from a decay and + * having no long-lived ancestor produced by material interactions). + * + * @param truth Truth container used to look up particle parents and production vertices. + * @param particle Particle to evaluate. + * @return true if the particle is classified as an sPHENIX primary, `false` otherwise. + * + */ bool PHG4TruthTrackingAction::issPHENIXPrimary(PHG4TruthInfoContainer& truth, PHG4Particle* particle) const { PHG4VtxPoint* vtx = truth.GetVtx(particle->get_vtx_id()); @@ -346,13 +376,15 @@ bool PHG4TruthTrackingAction::issPHENIXPrimary(PHG4TruthInfoContainer& truth, PH // check the production process // if not decay or primary, then it is not a primary // debug print for pid, track id, parent id, and process - /* - std::cout << "PHG4TruthTrackingAction::issPHENIXPrimary - checking particle with track id " << particle->get_track_id() - << ", pid: " << pdgid - << ", parent id: " << particle->get_parent_id() - << ", process: " << process - << std::endl; - */ + // if (pdgid == 311 || pdgid == 130 || pdgid == 310) + //{ + // std::cout << "PHG4TruthTrackingAction::issPHENIXPrimary - checking particle with track id " << particle->get_track_id() + // << ", pid: " << pdgid + // << ", parent id: " << particle->get_parent_id() + // << ", process: " << process + // << std::endl; + //} + if (!(process == PHG4MCProcess::kPPrimary || process == PHG4MCProcess::kPDecay) && particle->get_parent_id()) // all primary particles seems to have unkown process id { return false; diff --git a/simulation/g4simulation/g4main/PHG4TruthTrackingAction.h b/simulation/g4simulation/g4main/PHG4TruthTrackingAction.h index 5ad050c898..99e0c4669e 100644 --- a/simulation/g4simulation/g4main/PHG4TruthTrackingAction.h +++ b/simulation/g4simulation/g4main/PHG4TruthTrackingAction.h @@ -4,10 +4,12 @@ #define G4MAIN_PHG4TRUTHTRACKINGACTION_H #include "PHG4TrackingAction.h" +#include "PHG4MCProcessDefs.h" #include #include +#include #include class G4Track; @@ -17,6 +19,68 @@ class PHG4TruthEventAction; class PHG4Particle; class PHG4VtxPoint; +/** + * Construct a PHG4TruthTrackingAction associated with an event action. + * @param eventAction Pointer to the owning PHG4TruthEventAction used to record per-event truth information. + */ + +/** + * Destroy the PHG4TruthTrackingAction. + */ + +/** + * Handle actions to perform before Geant4 begins tracking a G4 track. + * @param track The Geant4 track about to be processed. + */ + +/** + * Handle actions to perform after Geant4 finishes tracking a G4 track. + * @param track The Geant4 track that has just been processed. + */ + +/** + * Set required node/interface pointers from the given top-level node. + * @param topNode Pointer to the PHCompositeNode root from which required I/O nodes are retrieved. + * @returns Zero on success, non-zero on failure. + */ + +/** + * Reset per-event state using nodes found under the given composite node. + * @param topNode Pointer to the PHCompositeNode for the current event. + * @returns Zero on success, non-zero on failure. + */ + +/** + * Create or update a truth particle entry corresponding to the provided Geant4 track. + * @param truth Container to which the particle entry will be added or updated. + * @param track Geant4 track from which particle information is derived. + * @returns Pointer to the created or updated PHG4Particle. + */ + +/** + * Create or update a truth vertex entry corresponding to the provided Geant4 track. + * @param truth Container to which the vertex entry will be added or updated. + * @param track Geant4 track whose production point will be recorded as a vertex. + * @returns Pointer to the created or updated PHG4VtxPoint. + */ + +/** + * Determine whether a particle type is considered long-lived for truth-building. + * @param pid Particle PDG identifier. + * @returns `true` if the particle with the given PDG id is treated as long-lived, `false` otherwise. + */ + +/** + * Determine whether a particle should be flagged as an sPHENIX primary. + * @param truth Truth information container used to evaluate primary status. + * @param particle Particle to evaluate. + * @returns `true` if the particle is considered an sPHENIX primary, `false` otherwise. + */ + +/** + * Update the internal upstream G4 particle stack when processing a new Geant4 track. + * @param track Geant4 track used to update parent/ancestor particle bookkeeping. + */ class PHG4TruthTrackingAction : public PHG4TrackingAction { public: @@ -37,7 +101,8 @@ class PHG4TruthTrackingAction : public PHG4TrackingAction int ResetEvent(PHCompositeNode*) override; private: - std::map m_VertexMap; + // Key is (position, process) to distinguish vertices at the same location but different processes + std::map, int> m_VertexMap; //! pointer to the "owning" event action PHG4TruthEventAction* m_EventAction;