Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion offline/packages/CaloReco/PhotonClusterBuilder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

#include <fun4all/Fun4AllReturnCodes.h>

#include <ffamodules/CDBInterface.h>

#include <TMVA/RBDT.hxx>

#include <algorithm>
Expand Down Expand Up @@ -64,7 +66,44 @@ int PhotonClusterBuilder::InitRun(PHCompositeNode* topNode)
// BDT
if (m_do_bdt)
{
m_bdt = std::make_unique<TMVA::Experimental::RBDT>("myBDT", m_bdt_model_file);
m_bdt.reset();
if (m_bdt_feature_list.empty())
{
std::cerr << Name() << ": BDT enabled without an ordered feature list" << std::endl;
return Fun4AllReturnCodes::ABORTRUN;
}

std::string model_file = m_bdt_model_file;
if (!m_bdt_model_cdb_domain.empty())
{
model_file = CDBInterface::instance()->getUrl(m_bdt_model_cdb_domain);
if (model_file.empty())
{
std::cerr << Name() << ": no BDT model found for CDB domain '"
<< m_bdt_model_cdb_domain << "'" << std::endl;
return Fun4AllReturnCodes::ABORTRUN;
}
}

if (model_file.empty())
{
std::cerr << Name() << ": BDT model filename is empty" << std::endl;
return Fun4AllReturnCodes::ABORTRUN;
}
try
{
m_bdt = std::make_unique<TMVA::Experimental::RBDT>("myBDT", model_file);
}
catch (const std::exception& error)
{
std::cerr << Name() << ": could not load BDT model '" << model_file
<< "': " << error.what() << std::endl;
return Fun4AllReturnCodes::ABORTRUN;
}
if (Verbosity() > 0)
{
std::cout << Name() << ": BDT model: " << model_file << std::endl;
}
}

// locate input raw cluster container
Expand Down
11 changes: 10 additions & 1 deletion offline/packages/CaloReco/PhotonClusterBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,15 @@ class PhotonClusterBuilder : public SubsysReco
void set_output_photon_node(const std::string& n) { m_output_photon_node = n; }
void set_ET_threshold(float e) { m_min_cluster_et = e; }
void set_shower_shape_min_tower_energy(float e) { m_shape_min_tower_E = e; }
void set_bdt_model_file(const std::string& path) { m_bdt_model_file = path; }
// Select a local model file, overriding any previously selected CDB domain.
void set_bdt_model_file(const std::string& path)
{
m_bdt_model_file = path;
m_bdt_model_cdb_domain.clear();
}
// Select CDB loading with the job's existing global tag and timestamp.
// An empty domain restores file-based loading; no file fallback is used in CDB mode.
void set_bdt_model_cdb_domain(const std::string& domain) { m_bdt_model_cdb_domain = domain; }
void set_bdt_feature_list(const std::vector<std::string>& 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; }
Expand Down Expand Up @@ -66,6 +74,7 @@ class PhotonClusterBuilder : public SubsysReco
float m_min_cluster_et{5.0f};
float m_shape_min_tower_E{0.070f};
std::string m_bdt_model_file{"myBDT_5.root"};
std::string m_bdt_model_cdb_domain;
std::vector<std::string> m_bdt_feature_list;
float m_vertex{std::numeric_limits<float>::quiet_NaN()};
float m_subtracted_iso_defval{-999};
Expand Down
81 changes: 81 additions & 0 deletions offline/packages/CaloReco/README.PhotonClusterBuilder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# PhotonClusterBuilder BDT loading

BDT scoring is optional and disabled by default. When enabled, the builder
loads a TMVA `RBDT` named `myBDT` during `InitRun` and stores the score as the
`bdt_score` shower-shape parameter. The caller supplies the ordered features
expected by the model.

## Load a model from CDB

Set `set_bdt_model_cdb_domain(...)` before registering the builder. The lookup
uses the standard `CDBInterface` and the job's existing `CDB_GLOBALTAG` and
`TIMESTAMP`. The builder does not set or change either flag.

For the PPG12 baseV3E photon-ID model, configure the builder as follows in a
Fun4All macro after the input clusters, calibrated towers and geometry have
been configured:

```cpp
#include <TMVA/RBDT.hxx>
#include <caloreco/PhotonClusterBuilder.h>
#include <fun4all/Fun4AllServer.h>

R__LOAD_LIBRARY(libcalo_reco.so)

auto* photons = new PhotonClusterBuilder();
photons->set_do_bdt(true);
photons->set_bdt_model_cdb_domain("PPG12_PHOTON_ID_BDT");
photons->set_bdt_feature_list({
"cluster_Et", "cluster_weta_cogx", "cluster_wphi_cogx",
"vertexz", "cluster_Eta", "e11_over_e33",
"cluster_et1", "cluster_et2", "cluster_et3", "cluster_et4",
"e32_over_e35"});
photons->Verbosity(1); // Print the resolved model filename.
Fun4AllServer::instance()->registerSubsystem(photons);
```

The published baseV3E payload is available for these settings:

| Sample | `CDB_GLOBALTAG` | `TIMESTAMP` |
| --- | --- | --- |
| DATA | `newcdbtag` | Actual run number, 47289 through 53999 |
| PPG12 MC | `MDC2` | 28 |

These are job-level reconstruction settings, not an extra model-specific
global tag. In the job's normal CDB setup, for example:

```cpp
#include <phool/recoConsts.h>

auto* rc = recoConsts::instance();
rc->set_StringFlag("CDB_GLOBALTAG", "newcdbtag");
rc->set_uint64Flag("TIMESTAMP", 47289); // Use the actual DATA run.
// PPG12 MC instead uses "MDC2" and 28.
```

Keep the 11 features in exactly the order shown. Ratios with a non-positive
denominator resolve to zero. The model is the baseV3E classifier used in the
PPG12 `8 <= ET < 35 GeV` range; the separate `base_E` classifier outside that
range is not selected automatically. Working-point cuts, preselection and
photon-selection logic remain the analysis's responsibility.

## Use a local file

Existing file-based configurations continue to work. To override a CDB
selection, call this after configuring the CDB domain, before `InitRun`:

```cpp
photons->set_bdt_model_file("/path/to/model_base_v3E_single_tmva.root");
```

`set_bdt_model_file` clears the CDB selection. A subsequent nonempty
`set_bdt_model_cdb_domain` selects CDB again. Without a CDB domain, the legacy
default filename remains `myBDT_5.root` unless explicitly changed.

An empty feature list, empty resolved path, or model-loading exception aborts
run initialization with a diagnostic. CDB mode never falls back to the local
filename. It follows the standard `CDBInterface` behavior, including any
enabled `_default` domain lookup or calibration-file cache; the builder does
not change these job-wide settings. Nonempty feature lists still must match the model's
input count, order and definitions; this interface does not infer them from
the CDB name or change the existing feature evaluation.