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
1 change: 1 addition & 0 deletions analysis/AnaLinkDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#pragma link off all functions;

#pragma link C++ class R3BAnalysisIncomingID+;
#pragma link C++ class R3BEventFilter+;
#pragma link C++ class R3BIncomingBeta+;
#pragma link C++ class R3BIncomingIDPar+;
#pragma link C++ class R3BAnalysisContFact+;
Expand Down
230 changes: 230 additions & 0 deletions analysis/offline/R3BEventFilter.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/******************************************************************************
* Copyright (C) 2025 GSI Helmholtzzentrum für Schwerionenforschung GmbH *
* Copyright (C) 2025 Members of R3B Collaboration *
* *
* This software is distributed under the terms of the *
* GNU General Public Licence (GPL) version 3, *
* copied verbatim in the file "LICENSE". *
* *
* In applying this license GSI does not waive the privileges and immunities *
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
******************************************************************************/

// ----------------------------------------------------------------
// ----- R3BEventFilter -----
// ----- Created 05/10/25 by J.L. Rodriguez-Sanchez -----
// ----------------------------------------------------------------

/*
* This class selects which events should be stored in the ROOT file.
* It acts as a filter, deciding whether an event is kept or discarded.
*/

#include "FairRunOnline.h"
#include <FairLogger.h>
#include <FairRootManager.h>
#include <FairRunAna.h>
#include <FairRuntimeDb.h>

#include "R3BEventFilter.h"
#include "R3BEventHeader.h"
#include "R3BFrsData.h"
#include "R3BLogger.h"
#include "R3BTofdHitData.h"

#include <TClonesArray.h>
#include <TMath.h>

R3BEventFilter::R3BEventFilter()
: R3BEventFilter("R3BEventFilter", 1)
{
}

R3BEventFilter::R3BEventFilter(const TString& name, Int_t iVerbose)
: FairTask(name, iVerbose)
{
}

void R3BEventFilter::SetParContainers()
{
R3BLOG(info, "");
// Reading IncomingIDPar from FairRuntimeDb
auto rtdb = FairRuntimeDb::instance();
R3BLOG_IF(fatal, !rtdb, "FairRuntimeDb not found");

return;
}

void R3BEventFilter::SetParameter()
{
//--- Parameter Containers ---
return;
}

InitStatus R3BEventFilter::Init()
{
R3BLOG(info, "");

auto mgr = FairRootManager::Instance();
R3BLOG_IF(fatal, nullptr == mgr, "FairRootManager not found");

fHeader = dynamic_cast<R3BEventHeader*>(mgr->GetObject("EventHeader."));

fTofdHit = dynamic_cast<TClonesArray*>(mgr->GetObject("TofdHit"));

fFrsData = dynamic_cast<TClonesArray*>(mgr->GetObject("FrsData"));

if (!fCutFrsId)
{
auto tmp = std::make_unique<TCutG>("fCutFrsId", 5);
tmp->SetPoint(0, 0.5, 0.5);
tmp->SetPoint(1, 4., 0.5);
tmp->SetPoint(2, 4., 4.);
tmp->SetPoint(3, 0.5, 4.);
tmp->SetPoint(4, 0.5, 0.5);
fCutFrsId = std::move(tmp);
}

if (fChargeLimits.empty())
{
R3BLOG(warn, "Charge limits not set.");
fUseTofd = false;
}

SetParameter();
return kSUCCESS;
}

InitStatus R3BEventFilter::ReInit()
{
SetParContainers();
SetParameter();
return kSUCCESS;
}

inline bool CheckFireConditionsTwoPlanes(const std::vector<int>& v)
{

bool planes13ok = false;
bool planes24ok = false;

if ((v[0] == 1) && (v[2] == 1))
planes13ok = true;

if ((v[1] == 1) && (v[3] == 1))
planes24ok = true;
Comment on lines +106 to +116
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing bounds check. The function accesses v[0], v[1], v[2], and v[3] without verifying that the vector has at least 4 elements. Add a size check similar to CheckFireConditionsAllPlanes to prevent out-of-bounds access.

Copilot uses AI. Check for mistakes.

if (planes13ok || planes24ok)
return true;
else
return false;
}

inline bool CheckFireConditionsAllPlanes(const std::vector<int>& v)
{
Comment on lines +118 to +125
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplified return statement recommended. The if-else can be replaced with a direct return of the boolean expression.

Suggested change
if (planes13ok || planes24ok)
return true;
else
return false;
}
inline bool CheckFireConditionsAllPlanes(const std::vector<int>& v)
{
return planes13ok || planes24ok;
}
inline bool CheckFireConditionsAllPlanes(const std::vector<int>& v)
{
inline bool CheckFireConditionsAllPlanes(const std::vector<int>& v)
{

Copilot uses AI. Check for mistakes.
if (v.size() < 4)
return false;

// if (std::all_of(v.begin(), v.end(), [](int x) { return x == -1; }))
// return false;
for (const auto& val : v)
if (val != 1)
return false;
return true;
}

void R3BEventFilter::Exec(Option_t*)
{
bool fValidEvent = false;

Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential null pointer dereference. The fHeader pointer is used without null checking on line 141. If fHeader is nullptr, this will cause a crash. Add a null check for fHeader before accessing GetExpId().

Suggested change
if (!fHeader)
{
R3BLOG(error, "R3BEventFilter: Event header not available, skipping event");
StoreEvent(false);
return;
}

Copilot uses AI. Check for mistakes.
if (fHeader->GetExpId() == 249)
{
if (fFrsData != nullptr && fFrsData->GetEntriesFast() > 0 && fCutFrsId != nullptr)
{
auto nHits = fFrsData->GetEntriesFast();
for (size_t ihit = 0; ihit < nHits; ihit++)
{
auto frsdata = dynamic_cast<R3BFrsData*>(fFrsData->At(ihit));
auto charge = frsdata->GetZ();
auto aoq = frsdata->GetAq();
Comment on lines +148 to +150
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing null check after dynamic_cast. If the cast fails, frsdata will be nullptr and calling GetZ() or GetAq() on it will cause a crash. Add a null check after the dynamic_cast.

Copilot uses AI. Check for mistakes.
if (fCutFrsId->IsInside(charge, aoq))
{
fValidEvent = true;
}
}
}

// Function to determinate the charge in terms of the limits
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in comment: "determinate" should be "determine".

Suggested change
// Function to determinate the charge in terms of the limits
// Function to determine the charge in terms of the limits

Copilot uses AI. Check for mistakes.
auto isSelectedCharge = [&](int plane, double charge)
{
if ((charge > fChargeLimits[plane - 1][0]) && (charge < fChargeLimits[plane - 1][1]))
return 1;
else
return 0;
Comment on lines +159 to +164
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lambda function isSelectedCharge accesses fChargeLimits[plane - 1] without validating that the index is within bounds. If plane is 0 or if fChargeLimits has fewer than 'plane' elements, this will cause undefined behavior. Add bounds checking before accessing the vector.

Copilot uses AI. Check for mistakes.
};

if (fUseTofd)
{
if (!fTofdHit || fTofdHit->GetEntriesFast() <= 0)
{
StoreEvent(false);
return;
}
}

if (fTofdHit != nullptr && fTofdHit->GetEntriesFast() > 0 && fValidEvent && !fChargeLimits.empty() && fUseTofd)
{
std::vector<int> chargeSelected(4, -1);
auto nHits = fTofdHit->GetEntriesFast();

for (size_t ihit = 0; ihit < nHits; ihit++)
{
auto tofdhit = dynamic_cast<R3BTofdHitData*>(fTofdHit->At(ihit));
auto plane = tofdhit->GetPlaneId();

// Add a method to calculate the charge in each plane
chargeSelected[plane - 1] = isSelectedCharge(plane, tofdhit->GetChargeZ());
Comment on lines +183 to +187
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing null check after dynamic_cast. If the cast fails, tofdhit will be nullptr and calling GetPlaneId() or GetChargeZ() on it will cause a crash. Add a null check after the dynamic_cast.

Copilot uses AI. Check for mistakes.
Comment on lines +184 to +187
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential out-of-bounds access. The plane ID from GetPlaneId() is used to index into chargeSelected and fChargeLimits without validation. If plane is 0 or greater than 4, this will cause out-of-bounds access. Consider adding bounds checking to ensure plane is within the valid range (1-4) before using it as an array index.

Copilot uses AI. Check for mistakes.
}

// To identify something as a good hit it is necessary that in 1-3 or 2-4 we have the same
// charge
if (fUseAllPlanes)
fValidEvent = CheckFireConditionsAllPlanes(chargeSelected);
else
fValidEvent = CheckFireConditionsTwoPlanes(chargeSelected);
}
}
else
{
R3BLOG(fatal, "Unknown experiment ID: event filter not yet implemented");
}
StoreEvent(fValidEvent);
}

void R3BEventFilter::FinishEvent()
{
if (fFrsData)
{
fFrsData->Clear();
}

if (fTofdHit)
{
fTofdHit->Clear();
}
}

void R3BEventFilter::StoreEvent(bool valid)
{
if (valid)
{
FairRunOnline::Instance()->MarkFill(kTRUE);
}
else
{
FairRunOnline::Instance()->MarkFill(kFALSE);
}
}

ClassImp(R3BEventFilter)
120 changes: 120 additions & 0 deletions analysis/offline/R3BEventFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/******************************************************************************
* Copyright (C) 2025 GSI Helmholtzzentrum für Schwerionenforschung GmbH *
* Copyright (C) 2025 Members of R3B Collaboration *
* *
* This software is distributed under the terms of the *
* GNU General Public Licence (GPL) version 3, *
* copied verbatim in the file "LICENSE". *
* *
* In applying this license GSI does not waive the privileges and immunities *
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
******************************************************************************/

// ----------------------------------------------------------------
// ----- R3BEventFilter -----
// ----- Created 05/10/25 by J.L. Rodriguez-Sanchez -----
// ----------------------------------------------------------------

/*
* This class selects which events should be stored in the ROOT file.
* It acts as a filter, deciding whether an event is kept or discarded.
*/

#pragma once

// ROOT headers
#include <TCutG.h>
#include <TMath.h>
#include <TString.h>

// FAIR headers
#include <FairTask.h>

// R3B headers
#include "R3BEventHeader.h"
#include "R3BFrsData.h"

class TClonesArray;

class R3BEventFilter : public FairTask
{
public:
/**
* Default constructor.
* Creates an instance of the task with default parameters.
*/
R3BEventFilter();

/**
* Standard constructor.
* Creates an instance of the task.
* @param name a name of the task.
* @param iVerbose a verbosity level.
*/
explicit R3BEventFilter(const TString& name, Int_t iVerbose = 1);

/**
* Destructor.
* Frees the memory used by the object.
*/
~R3BEventFilter() = default;

/**
* Method for task initialization.
* This function is called by the framework before
* the event loop.
* @return Initialization status. kSUCCESS, kERROR or kFATAL.
*/
InitStatus Init() override;

InitStatus ReInit() override;
/**
* Method for event loop implementation.
* Is called by the framework every time a new event is read.
* @param option an execution option.
*/
void Exec(Option_t* option) override;

/**
* A method for finish of processing of an event.
* Is called by the framework for each event after executing
* the tasks.
*/
void FinishEvent() override;

void SetParContainers() override;

void SetTCutFrsId(const TCutG* cut)
{
if (cut)
{
fCutFrsId.reset(static_cast<TCutG*>(cut->Clone()));
fCutFrsId->SetName("fCutFrsId");
}
else
{
fCutFrsId.reset();
}
}
void SetChargeLimits(const std::vector<std::vector<double>>& vec) { fChargeLimits = vec; }
void SetTofd() { fUseTofd = true; }
void UseTwoPlanes() { fUseAllPlanes = false; }

private:
void SetParameter();
void StoreEvent(bool valid = true);

R3BEventHeader* fHeader = nullptr;
TClonesArray* fTofdHit = nullptr;
TClonesArray* fFrsData = nullptr;

std::unique_ptr<TCutG> fCutFrsId;
std::vector<std::vector<double>> fChargeLimits;

bool fUseTofd = false;
bool fUseAllPlanes = true;

public:
ClassDefOverride(R3BEventFilter, 1); // NOLINT
};
5 changes: 1 addition & 4 deletions analysis/offline/R3BIncomingBeta.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
* or submit itself to any jurisdiction. *
******************************************************************************/

#ifndef R3BIncomingBeta_H
#define R3BIncomingBeta_H 1
#pragma once

// ROOT header
#include "TMath.h"
Expand Down Expand Up @@ -150,5 +149,3 @@ class R3BIncomingBeta : public FairTask
public:
ClassDef(R3BIncomingBeta, 1)
};

#endif /* R3BIncomingBeta_H */
Loading
Loading