Page History
Include Page | ||||
---|---|---|---|---|
|
Table of Contents |
---|
Include Page | ||||
---|---|---|---|---|
|
Introduction
This document describes C++ analysis framework for LCLS and how users can make use of its features. Psana design borrows ideas from multitude of other framworks such as pyana, myana, BaBar framework, etc. It's main principles are summarized here:
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include "psana/Module.h"
namespace Package {
class ExampleModule: public Module {
public:
// Constructor takes module name as a parameter
ExampleModule(const std::string& name);
// Implementation of event() from base class
virtual void event(Event& evt, Env& env);
};
} // namespace Package
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include "Package/ExampleModule.h"
#include "MsgLogger/MsgLogger.h"
#include "PSEvt/EventId.h"
// define factory function
using namespace Package;
PSANA_MODULE_FACTORY(ExampleModule)
// Constructor
ExampleModule::ExampleModule(const std::string& name)
: Module(name)
{
}
void
ExampleModule::event(Event& evt, Env& env)
{
// get event ID
shared_ptr<EventId> eventId = evt.get();
if (not eventId.get()) {
MsgLog(name(), info, "event ID not found");
} else {
MsgLog(name(), info, "event ID: " << *eventId);
}
}
|
...
The easiest way to write new user modules is to use codegen
script to generate class from predefined template. This command will create new module ExampleModule
in package TestPackage
and will copy generated files to the directories in TestPackage:
Code Block |
---|
codegen -l psana-module TestPackage ExampleModule
|
...
Here is an example of the code using above functions:
Code Block |
---|
void ExampleModule::event(Event& evt, Env& env) {
...
if (pixelsAboveThreshold < 1000) {
// This event is not worth looking at, skip it
skip();
// I do not want to continue with this algorithm either
return;
}
if (nGoodEvents > 1000) {
// we collected enough data, can stop now and go to endJob()
stop();
// I do not want to continue with this algorithm either
return;
}
if (temperatureKelvin < 0) {
// data is junk, stop right here and don't call endJob()
terminate();
// I do not want to continue with this algorithm either
return;
}
}
|
...
Configuration file has a simple format which is similar to well-known INI file format
. The file consists of the sections, each section begins with the section header in the form:
Code Block |
---|
[<section-name>]
|
Section names can be arbitrary strings, but in psana case section names are the names of the modules which cannot be arbitrary and should not contain spaces.
Following the section header there may be zero or more parameter lines in the form
Code Block |
---|
<param-name> = <param-value>
|
Parameter name is anything between beginning of line and '=' character with leading and trailing spaces and tabs stripped. Parameter value is anything after '=' character with leading and trailing spaces and tabs stripped, parameter value can be empty. Long parameter value can be split over multiple lines if the line ends with the backslash character, e.g.:
Code Block |
---|
files = /reg/d/psdm/AMO/amo00000/xtc/e00-r0000-s00-c00.xtc \
/reg/d/psdm/AMO/amo00000/xtc/e00-r0000-s01-c00.xtc \
/reg/d/psdm/AMO/amo00000/xtc/e00-r0000-s02-c00.xtc
|
...
modules
list of module names to include in the analysis job. Each module name is built of a package name and class name separated by dot (e.g.TestPackage.ExampleModule
) optionally followed by colon and modifier. Modifier is not needed if there is only one instance of the module in the job. If there is more than on instance then modules need to include unique modifier to distinguish instances. If the module comes from psana package then package name can be omitted. Module names can also be specified on the command line with-m
option, for multiple modules use multiple-m
options or comma-separated names in single -m option.files
list of file names to process. File names can also be specified on the command line which will override anything specified in configuration file. Long file names can be substituted by the string-structure likeexp=cxitut13:run=11,15-22,25:xtc
, which format is explained here.events
maximum number of events to process in a job, can also be given on the commnad line with-n
or--num-events
option.skip-events
number of events to skip before starting even processing, can also be given on the commnad line with-s
or--skip-events
option.instrument
Instrument name.experiment
Experiment name. Instrument and expriment names can be specified on the commnad line with-e
or--experiment
option, option value has formatXPP:xpp12311
orxpp12311
. By default instrument and experiment names are determined from input file names, you can use these options to override defaults (or when your file has non-standard naming).calib-dir
Path to the calibration directory, can also be given on the commnad line with-b
or--calib-dir
option. Path can include {instr
} and {exp
} strings which will be replaced with instrument and experiment names respectively. Default value for path is/reg/d/psdm/{instr}/{exp}/calib
.
Here is an example of the framework configuration section:
Code Block |
---|
[psana]
# list of file names
files = /reg/d/psdm/AMO/amo00000/xtc/e00-r0000-s00-c00.xtc \
/reg/d/psdm/AMO/amo00000/xtc/e00-r0000-s01-c00.xtc \
/reg/d/psdm/AMO/amo00000/xtc/e00-r0000-s02-c00.xtc
# list of modules, PrintSeparator and PrintEventId are from psana package
# and do not need package name
modules = PrintSeparator PrintEventId psana_examples.DumpAcqiris
|
...
Here is an example of configuration for some fictional analysis job:
Code Block |
---|
[psana]
modules = TestPackage.Analysis:mode1 TestPackage.Analysis:mode2
[TestPackage.Analysis]
# these are common parameters for all TestPackage.Analysis modules,
# but instances can override then in their own sections
calib-mode = fancy
subpixel = off
threshold = 0.001
[TestPackage.Analysis:mode1]
# parameters specific to :mode1 module
range-min = 0
range-max = 1000000
[TestPackage.Analysis:mode2]
# parameters specific to :mode2 module
range-min = 1000
range-min = 10000
subpixel = on
|
...
Here is an example of the code in user module which uses these methods:
Code Block |
---|
Source src = configStr("source", "DetInfo(:Evr)");
int repeat = config("repeat");
std::list<std::string> options = configList("options");
|
...
Here are few examples of using these macros:
Code Block |
---|
MsgLog("MyModule", info, "reading pedestals from file " << fileName);
MsgLog("MyModule", debug, "intermediate result: count=" << count << " sum=" << sum);
MsgLogRoot(warning, "warp engine overheating");
|
...
Above macros are simple to use in most cases as they hide all details from user. In more complex situations (printing array elements) there are two macros which provide access to underlying stream object which can be used in more interesting ways:
this macro declares stream object which can be used by the code in compound statement which follows the macro. The lifetime of the stream is the code block, after the code block is executed the message is published and stream disappears.
variation of the above macro which publishes message to root logger.
Here is an example of their use:
Code Block |
---|
WithMsgLog("MyModule", debug, str) {
str << "array elements:";
for (int i = 0; i < size; ++ i) {
str << " " << array[i];
}
}
|
...
PSHist::H1* hist1i(const std::string& name, const std::string& title, const Axis& axis)
creates one-dimensional histogram with integer bin contents. Returns pointer to histogram object.PSHist::H1* hist1d(name, title, axis)
(argument types same as above) creates one-dimensional histogram with double (64-bit) bin contents. Returns pointer to histogram object.PSHist::H1* hist1f(name, title, axis)
creates one-dimensional histogram with float (32-bit) bin contents. Returns pointer to histogram object.PSHist::H2* hist2i(name, title, xaxis, yaxis)
creates two-dimensional histogram with integer bin contents. Returns pointer to histogram object.PSHist::H2* hist2d(name, title, xaxis, yaxis)
creates two-dimensional histogram with double (64-bit) bin contents. Returns pointer to histogram object.PSHist::H2* hist2f(name, title, xaxis, yaxis)
creates two-dimensional histogram with float (32-bit) bin contents. Returns pointer to histogram object.PSHist::Profile* prof1(name, title, xaxis, const std::string& option="")
creates profile histogram, option string can be empty, "s", or "i", for meaning see reference. Returns pointer to histogram object.
...
Here is an example of the correct use of the histogramming package (from psana_examples.EBeamHist module):
Code Block |
---|
// ==== EBeamHist.h ====
class EBeamHist: public Module {
public:
.....
private:
Source m_ebeamSrc;
PSHist::H1* m_ebeamHisto;
PSHist::H1* m_chargeHisto;
};
// ==== EBeamHist.cpp ====
EBeamHist::EBeamHist(const std::string& name)
: Module(name)
, m_ebeamHisto(0)
, m_chargeHisto(0)
{
m_ebeamSrc = configStr("eBeamSource", "BldInfo(EBeam)");
}
void EBeamHist::beginJob(Env& env)
{
m_ebeamHisto = env.hmgr().hist1i("ebeamHisto", "ebeamL3Energy value", Axis(1000, 0, 50000));
m_chargeHisto = env.hmgr().hist1i("echargeHisto", "ebeamCharge value", Axis(250, 0, 0.25));
}
void EBeamHist::event(Event& evt, Env& env)
{
shared_ptr<Psana::Bld::BldDataEBeamV1> ebeam = evt.get(m_ebeamSrc);
if (ebeam.get()) {
m_ebeamHisto->fill(ebeam->ebeamL3Energy());
m_chargeHisto->fill(ebeam->ebeamCharge());
}
}
|
...
- Everything is done in the context of the off-line analysis releases, your environment should be prepared and you should have test release setup based on one of the recent analysis releases. Consult Workbook which should help you going.
You need your own package which may host several analysis modules. Package name must be unique. If the package has not be created yet run this command:
Code Block newpkg MyPackage mkdir MyPackage/include MyPackage/src
Generate skeleton module class from template:
Code Block codegen -l psana-module MyPackage MyModule
this will create two files:
MyPackage/include/MyModule.h
andMyPackage/src/MyModule.cpp
- Edit these two files, add necessary data members and implementation of the methods.
- For examples of accessing different data types see collection of modules in
psana_examples
package. Reference for all event and configuration data types is located at https://pswww.slac.stanford.edu/swdoc/releases/ana-current/psddl_psana/ - Reference for other classes in psana framework: Psana Reference Manual
- Run
scons
to build the module library. - Create psana config file if necessary.
- Run
psana
providing input data, configuration file, etc. - It is also possible that somebody wrote a module which you can reuse for your analysis, check the module catalog: Psana Module Catalog
...
After writing and compiling the modules (or choosing standard modules) one can run psana application with these modules. Psana application is pre-built and does not need to be recompiled. To start application one needs to either provide a configuration file or corresponding command-line options. Some information (e.g. user module options) cannot be specified on the command line and always require configuration file. Here is the list of command-line options recognized by psana:
Code Block |
---|
Usage: psana [options] [dataset ...]
Available options:
{-h|-?|--help } print help message
{-v|--verbose } (incr) verbose output, multiple allowed (initial: 0)
{-q|--quiet } (incr) quieter output, multiple allowed (initial: 2)
{-b|--calib-dir } path calibration directory name, may include {exp} and {instr}, if left empty then do not do calibrations (default: "")
{-c|--config } path configuration file, by default use psana.cfg if it exists (default: "")
{-e|--experiment } string experiment name, format: XPP:xpp12311 or xpp12311, by default guess it from data (default: "")
{-j|--job-name } string job name, default is to generate from input file names (default: "")
{-m|--module } name module name, more than one possible
{-n|--num-events } number maximum number of events to process, 0 means all (default: 0)
{-s|--skip-events} number number of events to skip (default: 0)
{-o|--option } string configuration options, format: module.option[=value]
Positional parameters:
dataset - input dataset specification (list of file names or exp=cxi12345:run=123:...)
|
...
Modules loaded by psana can be specified in configuration and on command line with -m
option. If -m
option is provided then its value overrides module list specified in the configuration file. One can provide comma-separated list of module names or multiple -m
options on the command line, following command lines are all equivalent:
Code Block |
---|
% psana -m ModuleA,ModuleB,ModuleC ...
% psana -m ModuleA -m ModuleB -m ModuleC ...
% psana -m ModuleA,ModuleB -m ModuleC ...
|
...
Here are few examples of running psana applications:
Code Block |
---|
% psana -m EventKeys /reg/d/psdm/...
% psana -m psana_examples.EBeamHist -j ebeam-hist-r1000 /reg/d/psdm/...
% psana -c psana_examples/data/DumpAll.cfg /reg/d/psdm/...
% psana # everything will be specified in psana.cfg file
|
...