Writing OpenHLT emulations

ALERT! Work in progress, under construction page under construction Work in progress, under construction ALERT!

Aim : give guidelines and examples to implement emulations in a concise way.

Introduction

The emulations are implemented in OHltTreeOpen.cpp, and sometimes require some modifications of OHltTree.h. The main function, OHltTree::CheckOpenHlt relies on matching trigger names :

else if (menu->GetTriggerName(it).CompareTo("OpenHLT_Jet30") == 0) {    
    if (map_L1BitOfStandardHLTPath.find(menu->GetTriggerName(it))->second==1) { 
      if(OpenHlt1CorJetPassed(30)>=1) { 
        if (prescaleResponse(menu,cfg,rcounter,it)) { triggerBit[it] = true; }   
      }    
    }    
  }    
  else if (menu->GetTriggerName(it).CompareTo("OpenHLT_Jet50") == 0) {     
    if (map_L1BitOfStandardHLTPath.find(menu->GetTriggerName(it))->second==1) { 
      if(OpenHlt1CorJetPassed(50)>=1) { 
        if (prescaleResponse(menu,cfg,rcounter,it)) { triggerBit[it] = true; }    
      }     
    }     
  }     
  else if (menu->GetTriggerName(it).CompareTo("OpenHLT_Jet80") == 0) {      
    if (map_L1BitOfStandardHLTPath.find(menu->GetTriggerName(it))->second==1) { 
      if(OpenHlt1CorJetPassed(80)>=1) { 
        if (prescaleResponse(menu,cfg,rcounter,it)) { triggerBit[it] = true; }     
      }      
    }      
  }      
...

The above implementation is fine when a reasonable number of emulations is needed, but, as time goes by, we keep adding more emulations and end up with thousand lines of code frown (it makes it hard to see mistakes). This may be made more concise using regexp matching (and for more complicated objects, maps). There is no need to be an expert in regexp though, just mimic the examples...

Jets, MET, MHT, HT....objects using a single threshold

First example with a single object path

Taking up the above example with jets, this can be made more concise using regexp matching as follows :

else if (isJetXTrigger(triggerName, thresholds))   <--- this has to be defined "elsewhere"
    {
      if (map_L1BitOfStandardHLTPath.find(triggerName)->second==1)
   {
     if (prescaleResponse(menu, cfg, rcounter, it))
       {
         if (OpenHlt1CorJetPassed(thresholds[0])>=1)
      {
        triggerBit[it] = true;
      }
       }
   }
    }
   

The function isJetXTrigger(triggerName, thresholds) takes as argument a TString (triggerName) defined at the begining of OHltTree::CheckOpenHlt (line 1938 at the time of writing), and a vector of double filled by isJetXTrigger. This function is defined before OHltTree::CheckOpenHlt as follows :

bool isJetXTrigger(TString triggerName, vector<double> &thresholds)
{
   
  TString pattern = "(OpenHLT_Jet([0-9]+)){1}$";
  TPRegexp matchThreshold(pattern);
   
  if (matchThreshold.MatchB(triggerName))
    {
      TObjArray *subStrL = TPRegexp(pattern).MatchS(triggerName);
      double thresholdJet = (((TObjString *)subStrL->At(2))->GetString()).Atof();
      thresholds.push_back(thresholdJet);
      delete subStrL;
      return true;
    }
  else
    return false;
}

subStrL, the list of substrings returned by root contains 0) the full string 1) the substring within which the pattern has been found, that is the largest brackets enclosing the pattern, 2) the pattern itself. Hence the "At(2)". The {1} ensures that the full string is matched once exactly (not mandatory provided we don't try exotic names)

Example with a cross-trigger path

To store the jet threshold, a double would have been sufficient in the single jet example. However, for the sake of harmonization, a vector is used, so that we can have cross triggers like

bool isHTX_MHTXTrigger(TString triggerName, vector<double> &thresholds)
{
   
  TString pattern = "(OpenHLT_HT([0-9]+)_MHT([0-9]+))$";
  TPRegexp matchThreshold(pattern);
   
  if (matchThreshold.MatchB(triggerName))
    {
      TObjArray *subStrL = TPRegexp(pattern).MatchS(triggerName);
      double thresholdHT = (((TObjString *)subStrL->At(2))->GetString()).Atof();
      double thresholdMHT = (((TObjString *)subStrL->At(3))->GetString()).Atof();
      thresholds.push_back(thresholdHT);
      thresholds.push_back(thresholdMHT);
      delete subStrL;
      return true;
    }
  else
    return false;
}

called in :

else if (isHTX_MHTXTrigger(triggerName, thresholds))
    {
      if (map_L1BitOfStandardHLTPath.find(triggerName)->second==1)
   {
     if (prescaleResponse(menu, cfg, rcounter, it))
       {
         if (OpenHltMHT(thresholds[1], 30.)==1 && (OpenHltSumCorHTPassed(
                                 thresholds[0],
                                 40.) == 1))
      {
        triggerBit[it] = true;
      }
       }
   }
    }
   

Be careful that you call the thresholds in "the proper order".

Muons...objects using a set of three thresholds depending on a double

Muons trigger name reads one threshold ("L3") but actually relies on a set of three : L1 pt, L2 pt and L3 pt. These thresholds are defined in map_muThresholds in OHltTree.h, which use follows :

  map_muThresholds[3.].push_back(0.); 
  map_muThresholds[3.].push_back(0.);
  map_muThresholds[3.].push_back(3.);

  map_muThresholds[5.].push_back(0.);
  map_muThresholds[5.].push_back(3.);
  map_muThresholds[5.].push_back(5.);

  map_muThresholds[8.].push_back(0.);
  map_muThresholds[8.].push_back(3.);
  map_muThresholds[8.].push_back(8.);
.....
defined thresholds : 3, 5, 8, 12, 13, 15, 17, 20, 24, 30, 40, 60, 100.

Disclaimer : this won't give reliable rates if the muons used by your path are non-standard.

For the record, the boolean function and the else if blocks look like :

bool isMuXTrigger(TString triggerName, vector<double> &thresholds)
{
  TString pattern = "(OpenHLT_Mu([0-9]+)){1}$";
  TPRegexp matchThreshold(pattern);

  if (matchThreshold.MatchB(triggerName))
    {
      TObjArray *subStrL   = TPRegexp(pattern).MatchS(triggerName);
      double thresholdL3Mu = (((TObjString *)subStrL->At(2))->GetString()).Atof();
      thresholds.push_back(thresholdL3Mu);
      delete subStrL;
      return true;
    }
  else
    return false;
}


****************************************************************************************

 else if (isMuXTrigger(triggerName, thresholds))
    {
      if (map_L1BitOfStandardHLTPath.find(triggerName)->second==1)
   {
     if (prescaleResponse(menu, cfg, rcounter, it))
       {
         if (OpenHlt1MuonPassed(map_muThresholds[thresholds[0]], 2., 0)>=1)
      {
        triggerBit[it] = true;
      }
       }
   }
    }   

EGamma...objects that calls set of thresholds summarized in strings

How to implement Ele?_CaloId?_CaloIso?_TrkId?_TrkIso? for any set of ? in (int, {VL, L, T, VT}, {VL, L, T, VT} etc...) in a single emulation (that is a single else if block) ?

First some maps have been implemented in OHltTree.h (look for _map_EG) :...

Mixing the above

Jets, MET, muons, electrons, photons may of course be mixed in cross triggers. One last example :

The examples given here might still be subject to improvements smile

-- LucieGAUTHIER - 06-Jul-2011

Edit | Attach | Watch | Print version | History: r1 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r1 - 2011-07-06 - LucieGAUTHIER
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    Main All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright &© 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use Discourse or Send feedback