NAIA

Ntuples for AMS-Italy Analysis

Status of the framework and tools

Status

# STATUS
  • Last relased version: v1.0.2
    • Several bugfixes and infrastructural improvements on the library side
  • Next planned version: v1.1.0
    • Some bugs spotted on the production side and new variables are needed, will need a new production.
    • Work will begin after this meeting, and production start is planned for ~July
    • Currently considering yearly production runs, depending on the need for reprocessing due to bugs / new variables.
  • Currently available datasets:
    • ISS.B1236/pass8 (11.5 years of data)
    • Ar.B1236 Be.B1236 C.B1236 Fe.B1236 Li.B1236 N.B1236 O.B1236 Pr.B1236 Si.B1236 B.B1236 Ca.B1236 el.B1236 He.B1236 Mg.B1236 Ne.B1236 pos.B1236 S.B1236 Ti.B1236

Tools: Were we left off

# TOOLS

NAIA is just a data model and framework for AMS analysis. We can think of it as the foundational layer, but there is room for creating useful tools to further the data analysis experience.

We currently have in the works:

  • A NAIA adapter for ROOT's TSelector framework (NaiaTSelector)
  • A common selection library (NSL)
  • A ROOT-based spline fitting library (RSpline)
  • A rewrite of the plugin system initially proposed for the dbar analysis

Tools: NSL

# TOOLS

NSL: A common selection library

 

This project aims at providing a set of commonly used selections that:

  • can be easily and arbitrarily combined (and/or parametrized)
  • allow to quickly build an analysis
  • are easy to read and understand (on a concept level, at least)
  • can be used to share the logic of a set of selections without having to worry too much about implementation details

 

Manual available at: https://nsl-readthedocs.readthedocs.io/en/latest/index.html

NSL: basics

# TOOLS

A story as old as time

    //Trigger selection
    if( (PhysBPatt & triggerPatt) == 0 ) continue; //Any non-prescaled trigger

    //Inner Tracker selection
    if( trtrackc->InnerCharge[chargeRecoType] < ITrTrackCharge_low || trtrackc->InnerCharge[chargeRecoType] > ITrTrackCharge_high ) continue;
    if( trtrackc->TrChiSqY[TrTrackCont::Span::InnerOnly] > 10 ) continue;
    if( trtrackc->InnerChargeRMS[chargeRecoType]/trtrackc->InnerCharge[chargeRecoType] > TrackChargeRMS ) continue;
    if( !trtrackc->CheckInnerPattern() ) continue;

    if( !option.CompareTo("") || option.Contains("PG") ){
      if( trtrackc->NGoodCluster < 3 ) continue;
    }

    if( !option.CompareTo("qi") ){
      if( trtrackc->GetNHitsInnerY() < 5 ) continue;
    }

    //Upper ToF selection
    if( betahc->Beta < Beta_thr ) continue;

    if(Charge < 9){
      if( !betahc->TofGoodPathL[0] && !betahc->TofGoodPathL[1] ) continue;
    }

    if( betahc->UTofCharge < UTofCharge_lthr || betahc->UTofCharge > UTofCharge_hthr ) continue;

    //L1 selection
    if( !trtrackc->SpanType[TrTrackCont::Span::InnerL1] ) continue;
    if (trtrackc->TrChiSqY[TrTrackCont::Span::InnerL1] > 10) continue;
    if( trtrackc->GetL1NormRes() > 10 ) continue;

NSL: basics

# TOOLS

A story as old as time:

  • A long sequence of ifs inside the main event loop
  • At the end of the loop (or interleaved among the selections) fill histograms / trees
  • After looping, save results

 

The first item can be summarized as:

We are only interested in a precise subset of events, and we filter out events we don’t care about by asking simple yes/no questions about the value of some variables.

 

The whole library is designed around this concept 

NSL: The Selection

# TOOLS

In short, a selection is just a yes/no question about variables in an event.

Whenever you instantiate a NSL::Selection object you can always query wether a NAIA::Event passes that selection

NSL::Selection my_selection = get_some_selection();

// ...
for (NAIA::Event &ev : chain) {
  if (my_selection(event)){
    // do stuff...
  }
}

things can still get out of hands pretty soon

if (my_selection_1(event) && my_selection_2(event) && /* ... */ my_selection_N(event)) {

NSL: The Selection

# TOOLS

Another main point of this library is allowing to define the whole selection logic ahead of time before the event loop, so that in the event loop you can focus on what you actually do with the events you select, rather than how you select them.

namespace ns = NSL::Selections;

auto triggerSel = ns::Trigger::HasPhysicsTrigger();

auto innerTrackerSel =
    ns::InnerTracker::HitPattern() &&
    ns::Track::ChiSquareLessThan(10.0f, NAIA::TrTrack::Side::Y, NAIA::TrTrack::Fit::GBL, NAIA::TrTrack::Span::InnerOnly);

for (NAIA::Event &ev : chain) {
  if (!triggerSel(event))
    continue;

  if (!innerTrackerSel(event))
    continue;

  // fill histos or whatever :)
}

A full list of already defined selections is available here

NSL: Hooks

# TOOLS

In some cases it might be useful to perform some check between the evaluation of two or more selections, maybe you want to print some value to the screen, fill some histogram, check if some precondition is satisfied, etc…

NSL: Hooks

# TOOLS

In some cases it might be useful to perform some check between the evaluation of two or more selections, maybe you want to print some value to the screen, fill some histogram, check if some precondition is satisfied, etc…

But if you defined you entire Selection sequence in one go there is no way of inserting code between one check and the next one. On the other hand, keeping all selections separated only to be able to fill a histogram in between kinda defeats the purpose of the whole design of this library.

NSL: Hooks

# TOOLS

In some cases it might be useful to perform some check between the evaluation of two or more selections, maybe you want to print some value to the screen, fill some histogram, check if some precondition is satisfied, etc…

But if you defined you entire Selection sequence in one go there is no way of inserting code between one check and the next one. On the other hand, keeping all selections separated only to be able to fill a histogram in between kinda defeats the purpose of the whole design of this library.

For this exact application NSL allows to define for each selection a “hook”, which is a snippet of code that can be run before or after the evaluation of the selection. The former case is named a “pre-hook”, while the latter is called a “post-hook” and can be selectively run when the check succeeds, fails or in both cases.

NSL: Hooks

# TOOLS

The way you attach a hook to a Selection is by calling AddPreHook or AddPostHook

// NSL namespace omitted for clarity
auto my_selection_chain = MySelection1(...).AddPreHook([](NAIA::Event &ev){ /* your hook code here */ }) &&
                          MySelection2(...).AddPostHook([](NAIA::Event &ev){ /* ... */ }, PostHookCondition::OnSuccess) &&
                          /* All your selections ... */;

NSL: Hooks

# TOOLS

The way you attach a hook to a Selection is by calling AddPreHook or AddPostHook

// NSL namespace omitted for clarity
auto my_selection_chain = MySelection1(...).AddPreHook([](NAIA::Event &ev){ /* your hook code here */ }) &&
                          MySelection2(...).AddPostHook([](NAIA::Event &ev){ /* ... */ }, PostHookCondition::OnSuccess) &&
                          /* All your selections ... */;

A hook is represented in code by any kind of function that takes a NAIA::Event & and returns void. Also, for post-hooks the PostHookCondition enum controls when the hook is actually executed. In the last example we added a “pre-hook” to MySelection1 which will always be executed before the selection is checked, and a “post-hook” to MySelection2 which will only be executed when the selection is passed.

NSL: Hooks (example)

# TOOLS
// create a chain and add a rootfile to it
NAIA::NAIAChain chain;
chain.Add("some_root_file.root");

// define your selections
auto my_selections = NSL::Trigger::HasPhysicsTrigger() &&
                     NSL::Tof::BetaInRange(0.3, 1.5, NAIA::Tof::BetaType::BetaH);

// create a histogram for the charge distribution plot
TH1D charge_distribution{"charge", ";Q;Counts", 100, 0, 15};

// create the action that fills the charge histogram
// NOTE: since NSL requires that hooks take an event and return void, we need to use lambda capture-by-reference to
//       have the histogram available inside our hook function
auto fill_charge_distribution = [&charge_distribution](NAIA::Event &ev){
    charge_distribution.Fill(ev.trTrackBase->InnerCharge[NAIA::TrTrack::ChargeRecoType::YJ]);
};

// add our function to our selectinos as a post-hook, to be run when the selections pass
my_selections.AddPostHook(fill_charge_distribution, NSL::PostHookCondition::OnSuccess);

// loop over the events and evaluate the selection(s).
for (NAIA::Event &event : chain){
    if (!my_selections(event)){
        continue;
    }
}

charge_distribution.Draw();

Happy coding :)

# 

230421 - NAIA Status and tools

By Valerio Formato

230421 - NAIA Status and tools

  • 121