Difference between revisions of "Analysis FAQ"

From GlueXWiki
Jump to: navigation, search
(Histogramming)
(How do I branch an analysis?)
 
(41 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== Neutrals ==
+
== JANA ==
  
* Given a DNeutralParticleHypothesis or DNeutralShower object, how do I get the FCAL/BCAL shower objects?
+
=== How do I skip events? ===
** Answer: By calling the inherited JObject::GetSingle() function:
+
 
 +
* To skip the first 'X' events, add the following to the command line when running hd_root:
  
 
<syntaxhighlight>
 
<syntaxhighlight>
//given a hypothesis, get the neutral shower:
+
-PEVENTS_TO_SKIP=X
const DNeutralShower* locNeutralShower = NULL;
+
</syntaxhighlight>
locNeutralParticleHypothesis->GetSingle(locNeutralShower);
+
  
//given a neutral shower, get the BCAL shower:
+
=== How do I limit the number of events analyzed? ===
const DFCALShower* locFCALShower = NULL;
+
if(locNeutralShower->dDetectorSystem == SYS_FCAL)
+
  locNeutralShower->GetSingle(locFCALShower);
+
  
//given a neutral shower, get the FCAL shower:
+
* To analyze only 'X' events, add the following to the command line when running hd_root:
const DBCALShower* locBCALShower = NULL;
+
 
if(locNeutralShower->dDetectorSystem == SYS_BCAL)
+
<syntaxhighlight>
  locNeutralShower->GetSingle(locBCALShower);
+
-PEVENTS_TO_KEEP=X
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Histogramming ==
+
=== How do I find out which factories are being called, and how much time they take? ===
  
* How do I manually create and fill a histogram in my plugin's processor in a way that is thread-safe?
+
* Run with the 'janadot' plugin. For example:
  
 
<syntaxhighlight>
 
<syntaxhighlight>
//Define your histogram in your processor class definition:
+
hd_root dana_rest.hddm -PPLUGINS=b1pi_hists,monitoring_hists,janadot
TH1D* dMyHist;
+
</syntaxhighlight>
  
//Create your histogram in your processor init() method:
+
* When that finishes, use the dot program to convert jana.dot to postscript, and then convert to pdf:
  //Note that you do not need a ROOT lock here, since the init() method of event processors is only called by one of the threads.  
+
  //If you were doing this in a factory, you would need a ROOT lock here.
+
dMyHist = new TH1D("HistName", "Hist Title;X-axis Title;Y-axis Title", 100, 0.0, 1.0);
+
  
//Fill the histogram in your processor evnt() method, but within a ROOT lock:
+
<syntaxhighlight>
double locValue = 1.0;
+
dot -Tps2 jana.dot -o jana.ps
 +
ps2pdf jana.ps
 +
</syntaxhighlight>
 +
 
 +
=== What do I need to know about multithreading with JANA? ===
 +
 
 +
* To run JANA with 'X' threads, add the following to the command line when running hd_root:
 +
 
 +
<syntaxhighlight>
 +
-PNTHREADS=X
 +
</syntaxhighlight>
 +
 
 +
* Event Processors (They drive JANA, and are in your plugins):
 +
** All threads share/use the same instance of an event processor. Thus, you must be careful when setting/modifying processor member variables.
 +
** The init() method is guaranteed to be called by only one thread.  Any code in here will be thread safe. 
 +
** The brun() method will be called by each thread.  Be VERY careful when modifying processor member variables here, as one thread may still be analyzing an event with the previous run number.
 +
** The evnt() method will be called by each thread. See the histogramming section about how to safely fill histograms.
 +
 
 +
* Factories (They create most JANA objects):
 +
** Each thread will have it's own instance of each factory. Thus, factory member variables can be safely modified without locks. You still need to be careful about ROOT objects (below).
 +
 
 +
* ROOT:
 +
** Only one instance of a given ROOT file, directory, histogram, or tree should be created.
 +
*** In processors, they should be created in the init() method, so that only one thread will attempt to create them.
 +
*** In factories and analysis actions, each thread should acquire a ROOT lock (see histogramming section), and first check to see if the histogram/etc. has already been created. If so, it should grab a pointer to the existing histogram/etc. instead of creating a duplicate. Example:
 +
 
 +
<syntaxhighlight>
 
japp->RootWriteLock(); //ACQUIRE ROOT LOCK!!
 
japp->RootWriteLock(); //ACQUIRE ROOT LOCK!!
 
{
 
{
   dMyHist->Fill(locValue);
+
   if(gDirectory->Get("MyHistName") != NULL) //already created by another thread
 +
      dMyHist = static_cast<TH1D*>(gDirectory->Get("MyHistName"); //grab the pointer to the pre-existing object
 +
  else
 +
      dMyHist = new TH1D("MyHistName", "MyHistTitle", 100, 0.0, 1.0); //create the histogram
 
}
 
}
 
japp->RootUnLock(); //RELEASE ROOT LOCK!!
 
japp->RootUnLock(); //RELEASE ROOT LOCK!!
 +
</syntaxhighlight>
  
//The histogram is automatically saved to hd_root.root, or the file you specified with "-o" on the command line.  
+
* Except within the processor init() method, any time a ROOT histogram/file/tree/directory is created/modified/filled, it should occur within a lock.
 +
 
 +
== Analysis Action Cuts ==
 +
 
 +
=== How do I perform an opposite (anti-, not-) cut? ===
 +
 
 +
* After creating an action, set the inherited DAnalysisAction::dPerformAntiCut member to true (default false):
 +
<syntaxhighlight>
 +
DMyAction* locAction = new DMyAction(...);
 +
locAction->dPerformAntiCut = true;
 +
locReaction->Add_AnalysisAction(locAction);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Cuts ==
+
== Analysis Actions (General) ==
  
* How do I place a cut prior to kinematic fitting?
+
=== How do I execute an analysis action from within another, custom action? ===
** Answer: Add an analysis action to the DReaction that performs the cut. It should be added prior to any action that uses the kinematic fit results. If no action uses the fit results, then it can be added anywhere.
+
  
 +
* To encompass a reaction-independent action, just add it to your action like you would normally:
 +
** However, be careful that the action has a unique name if it creates objects in the output ROOT file. If you are executing it more than once, use it as a pointer and call a different constructor in Initialize(), one where you can pass a unique name.
 
<syntaxhighlight>
 
<syntaxhighlight>
  //place cut on pi0 invariant mass (assuming a Pi0 decay step is defined in your DReaction):  
+
//In your custom action header file:
      //the false means "used measured data" as opposed to kinfit data
+
#include "ANALYSIS/DHistogramActions.h"
      //0.04 and 0.24 specify the minimum and maximum invariant mass
+
#include "ANALYSIS/DCutActions.h"
  locReaction->Add_AnalysisAction(new DCutAction_InvariantMass(locReaction, Pi0, false, 0.04, 0.24)); //does not require kinfit results
+
 
  locReaction->Add_AnalysisAction(new DHistogramAction_KinFitResults(locReaction, 0.05)); //requires kinfit results
+
//In the custom action class definition:
  //Thus, the kinematic fit is performed between execution of these actions. If a combo fails a cut prior to the kinfit, then it is not performed for that combo.
+
DHistogramAction_DetectedParticleKinematics dMyAction; //or whichever action you wanted to add
 +
 
 +
//In the custom action Initialize() method:
 +
dMyAction.Initialize(locEventLoop);
 +
 
 +
//In the custom action Perform_Action() method, execute the action:
 +
dMyAction(locEventLoop);
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
* To encompass a reaction-dependent action:
 +
<syntaxhighlight>
 +
//In your custom action header file:
 +
#include "ANALYSIS/DHistogramActions.h"
 +
#include "ANALYSIS/DCutActions.h"
 +
 +
//In the custom action class definition:
 +
DHistogramAction_InvariantMass* dMyAction; //or whichever action you wanted to add //Note it's a POINTER
 +
 +
//In the custom action Initialize() method:
 +
dMyAction = new DHistogramAction_InvariantMass(Get_Reaction(), Pi0, false, 1000, 0.1, 0.18); //setup the action like you would normally (unique name rules still apply!)
 +
dMyAction->Initialize(locEventLoop);
 +
 +
//In the custom action Perform_Action() method, execute the action:
 +
bool locActionResult = (*dMyAction)(locEventLoop, locParticleCombo); //locActionResult is true/false if it passed/failed the action's cut (if any)
 +
</syntaxhighlight>
 +
 +
* Note that, with a little modification to the above examples, you can execute actions directly in your plugin's event processor instead.
 +
 +
=== How do I branch an analysis? ===
 +
 +
* You cannot directly branch an analysis, where actions are only applied to a subset of the combos. Instead, you need to either write a custom action that encompasses all of the desired branching, or create a separate DReaction and place different cuts on it.

Latest revision as of 07:51, 3 November 2017

JANA

How do I skip events?

  • To skip the first 'X' events, add the following to the command line when running hd_root:
-PEVENTS_TO_SKIP=X

How do I limit the number of events analyzed?

  • To analyze only 'X' events, add the following to the command line when running hd_root:
-PEVENTS_TO_KEEP=X

How do I find out which factories are being called, and how much time they take?

  • Run with the 'janadot' plugin. For example:
hd_root dana_rest.hddm -PPLUGINS=b1pi_hists,monitoring_hists,janadot
  • When that finishes, use the dot program to convert jana.dot to postscript, and then convert to pdf:
dot -Tps2 jana.dot -o jana.ps
ps2pdf jana.ps

What do I need to know about multithreading with JANA?

  • To run JANA with 'X' threads, add the following to the command line when running hd_root:
-PNTHREADS=X
  • Event Processors (They drive JANA, and are in your plugins):
    • All threads share/use the same instance of an event processor. Thus, you must be careful when setting/modifying processor member variables.
    • The init() method is guaranteed to be called by only one thread. Any code in here will be thread safe.
    • The brun() method will be called by each thread. Be VERY careful when modifying processor member variables here, as one thread may still be analyzing an event with the previous run number.
    • The evnt() method will be called by each thread. See the histogramming section about how to safely fill histograms.
  • Factories (They create most JANA objects):
    • Each thread will have it's own instance of each factory. Thus, factory member variables can be safely modified without locks. You still need to be careful about ROOT objects (below).
  • ROOT:
    • Only one instance of a given ROOT file, directory, histogram, or tree should be created.
      • In processors, they should be created in the init() method, so that only one thread will attempt to create them.
      • In factories and analysis actions, each thread should acquire a ROOT lock (see histogramming section), and first check to see if the histogram/etc. has already been created. If so, it should grab a pointer to the existing histogram/etc. instead of creating a duplicate. Example:
japp->RootWriteLock(); //ACQUIRE ROOT LOCK!!
{
   if(gDirectory->Get("MyHistName") != NULL) //already created by another thread
      dMyHist = static_cast<TH1D*>(gDirectory->Get("MyHistName"); //grab the pointer to the pre-existing object
   else
      dMyHist = new TH1D("MyHistName", "MyHistTitle", 100, 0.0, 1.0); //create the histogram
}
japp->RootUnLock(); //RELEASE ROOT LOCK!!
  • Except within the processor init() method, any time a ROOT histogram/file/tree/directory is created/modified/filled, it should occur within a lock.

Analysis Action Cuts

How do I perform an opposite (anti-, not-) cut?

  • After creating an action, set the inherited DAnalysisAction::dPerformAntiCut member to true (default false):
DMyAction* locAction = new DMyAction(...);
locAction->dPerformAntiCut = true;
locReaction->Add_AnalysisAction(locAction);

Analysis Actions (General)

How do I execute an analysis action from within another, custom action?

  • To encompass a reaction-independent action, just add it to your action like you would normally:
    • However, be careful that the action has a unique name if it creates objects in the output ROOT file. If you are executing it more than once, use it as a pointer and call a different constructor in Initialize(), one where you can pass a unique name.
//In your custom action header file:
#include "ANALYSIS/DHistogramActions.h"
#include "ANALYSIS/DCutActions.h"
 
//In the custom action class definition:
DHistogramAction_DetectedParticleKinematics dMyAction; //or whichever action you wanted to add
 
//In the custom action Initialize() method:
dMyAction.Initialize(locEventLoop);
 
//In the custom action Perform_Action() method, execute the action:
dMyAction(locEventLoop);
  • To encompass a reaction-dependent action:
//In your custom action header file:
#include "ANALYSIS/DHistogramActions.h"
#include "ANALYSIS/DCutActions.h"
 
//In the custom action class definition:
DHistogramAction_InvariantMass* dMyAction; //or whichever action you wanted to add //Note it's a POINTER
 
//In the custom action Initialize() method:
dMyAction = new DHistogramAction_InvariantMass(Get_Reaction(), Pi0, false, 1000, 0.1, 0.18); //setup the action like you would normally (unique name rules still apply!)
dMyAction->Initialize(locEventLoop);
 
//In the custom action Perform_Action() method, execute the action:
bool locActionResult = (*dMyAction)(locEventLoop, locParticleCombo); //locActionResult is true/false if it passed/failed the action's cut (if any)
  • Note that, with a little modification to the above examples, you can execute actions directly in your plugin's event processor instead.

How do I branch an analysis?

  • You cannot directly branch an analysis, where actions are only applied to a subset of the combos. Instead, you need to either write a custom action that encompasses all of the desired branching, or create a separate DReaction and place different cuts on it.