Step by Step |
This section explains step by step how to create an analysis program with the ROME framework generator. On this page a very simple framework will be generated step by step. The framework code is located under 'examples/stepbystep' after you download rome. Please see stepbystep.xml in the directory as a starting point.
The following links point to step by step instructions to extend this framework :
ROME is not a framework. It is a framework generator. All analysis tools are generated by a program, which is called the ROMEBuilder. The ROMEBuilder creates the analysis framework out of framework definition. This framework definition has to be written by the user in a xml file. For information about xml please visit the W3 Schools home page. In the framework definition file the user can define all experiment specific stuff. The next steps explain the most important parts of this file. Not all possible xml tags will be discussed. For a complete list of all available tags visit the rome framework definition schema documentation.
The xml file has to start with the following tag :
<ROMEFrameworkDefinition> </ROMEFrameworkDefinition> |
if you are using a xml editor, you should add the following to this tag (maybe you have to adjust the path of the xsd file):
<ROMEFrameworkDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="c:/rome/rome.xsd"> </ROMEFrameworkDefinition> |
the xsd file holds the format of a valid ROME definition file. In a xml editor you can now validate your xml file.
In the first tag you must define the experiment. ROME needs to know the short cut of your experiment or of your analyzing tool. Specify some letters which describe your final program (2-5 letters recommended). This letters will be used for all generated files like 'XYZMyFile.cpp' if XYZ is the short cut.
<ROMEFrameworkDefinition> <Experiment> <ExperimentShortCut>SBS</ExperimentShortCut> <ProgramName>Analyzer</ProgramName> </Experiment> </ROMEFrameworkDefinition> |
In this example we also specify a program name. Thus our final program will be named 'SBSAnalyzer.exe'.
A data analysis tool must handle data. In ROME the data is stored in so called folders. The user has to define the folders in folder tags;
<ROMEFrameworkDefinition> <Folders> <Folder> <FolderName>PMTData</FolderName> <Field> <FieldName>ADC</FieldName> <FieldType>Int_t</FieldType> <FieldComment>ADC Value of a PMT</FieldComment> </Field> </Folder> </Folders> </ROMEFrameworkDefinition> |
In the example we define a folder containing raw data from an adc. The folder should contain values from the same detector or from the same sub-detector.
One can also define an array of folders. If you want to store for example the ADC data of 10 PMTs you can add the following line.
<Folder> <FolderName>PMTData</FolderName> <ArraySize>10</ArraySize> <Field> <FieldName>ADC</FieldName> <FieldType>Int_t</FieldType> <FieldComment>ADC Value of a PMT</FieldComment> </Field> </Folder> |
One can also define an array of variables. If you want to store for example the pulse heigh of each PMT you can add PulseHeight as following line. The array size can be fixed number (for example 2) or vector if the size can change.
<Folder> <FolderName>PMTData</FolderName> <ArraySize>10</ArraySize> <Field> <FieldName>ADC</FieldName> <FieldType>Int_t</FieldType> <FieldComment>ADC Value of a PMT</FieldComment> </Field> <Field> <FieldName>PulseHeight</FieldName> <FieldType>Float_t</FieldType> <ArraySize>vector</ArraySize> <FieldComment>Pulse heigh of a pulse</FieldComment> </Field> </Folder> |
Tasks are the objects to which the user can add code. For every part of a detector analysis you should make a task. The definition of a task looks as follows:
<ROMEFrameworkDefinition> <Tasks> <Task> <TaskName>PrintADCValues</TaskName> </Task> </Tasks> </ROMEFrameworkDefinition> |
This is a definition for a task which we want to print out the ADC values of the PMTData folder. The code to actually print out the values will be added later.
A tree is an object which can handle a large amount of data. It is used to write the data to disk. The data stored in the folders are only available for one event, they will be overwritten by the next event. To store the data one has to use trees. A tree has the same structure as the folders, therefore it is a one to one image of the folder structure, but it can hold all analyzed events. To define a folder one has to tell ROME which folder data should be written to disk and which is just for temporary use. The definition of a tree looks as follows:
<ROMEFrameworkDefinition> <Trees> <Tree> <TreeName>DataTree</TreeName> <Branch> <BranchName>PMTDataBranch</BranchName> <RelatedFolder>PMTData</RelatedFolder> </Branch> </Tree> </Trees> </ROMEFrameworkDefinition> |
A steering parameter is a value which can be set in a configuration file before starting the final program. They can be used to steer the program. Global steering parameter are available in all tasks. There's also the possibility to define steering parameters for each task, which are then only available inside this task (see the task tag in the rome framework definition schema documentation). The definition of a steering parameter looks as follows:
<ROMEFrameworkDefinition> <GlobalSteeringParameters> <SteeringParameterField> <SPFieldName>OutputOnOff</SPFieldName> <SPFieldType>bool</SPFieldType> </SteeringParameterField> </GlobalSteeringParameters> </ROMEFrameworkDefinition> |
We will use this steering parameter to turn the output of the ADC value on or off.
There is also the possibility to group steering parameters. Use the 'SteeringParameterGroup' tag for grouping.
When you have written the first draft of your framework definition file, you are ready to run the ROMEBuilder. Before running the ROMEBuilder make sure you have downloaded rome and compiled the ROMEBuilder. If not, please visit the Download Page.
Before running romebuilder, please set environment variable
ROMESYS to be the directory where you have the ROME package.
To run the ROMEBuilder go to the directory where you have stored the framework definition file and type :
> $ROMESYS/bin/romebuilder.exe -i stepbystep.xml |
The ROMEBuilder creates now all objects which are defined in the framework definition file. The class files will be located under './include' and the source files under './src'. The ROMEBuilder also compiles your project and creates an executable. This executable is a fully running analyzer, but with empty tasks.
Now you should add code to the source files of the tasks. They are located under './src/tasks'. A newly created task looks as follows:
#include <include/tasks/SBSTPrintADCValues.h> #include <Riostream.h> ClassImp(SBSTPrintADCValues) void SBSTPrintADCValues::Init() { } void SBSTPrintADCValues::BeginOfRun() { } void SBSTPrintADCValues::Event() { } void SBSTPrintADCValues::EndOfRun() { } void SBSTPrintADCValues::Terminate() { } |
There are five user methods which are called by the framework at the given time (Init,BeginOfRun,...). Now we add the print statement to the event method. Since we don't have an input file or DAQ system yet, we just write the array index to the adc field. This should of course be changed later. If the steering parameter 'OutputOnOff' is true we print out all 10 ADC values of the PMTData folder.
void SBSTPrintADCValues::Event() { for (int i=0;i<10;i++) gAnalyzer->GetPMTDataAt(i)->SetADC(i); if (gAnalyzer->GetGSP()->GetOutputOnOff()) { for (int i=0;i<10;i++) cout << gAnalyzer->GetPMTDataAt(i)->GetADC() << endl; cout << endl; } } |
Now we run the ROMEBuilder again. This time it only compiles and links the project and does not create any new files, since we didn't change the framework definition file. Therefore one could alternatively run the Makefile directly (the Makefile was generated by the ROMEBuilder in the first run). Nevertheless every time you make changes to the framework definition file you have to run the ROMEBuilder.
Now we have an analyzer with one task. We can now run the analyzer.
> ./sbsanalyzer.exe |
When the program is launched for the first time, if a configuration file is missing, it will ask the user if a default configuration file should be created. Press 'R' for the first question, and hit return key for other questions.
The framework can generate a new configuration file for you. Available configuration types are : [R] ROME Framework [A] ARGUS Monitor [M] ROME Framework with ARGUS Monitor [N] Don't generate a configuration file Please select a configuration type[R/A/M/N]: R Please specify file name (default='romeConfig.xml'): Please specify amount of comments in file [0-5], default=1(few comments): The framework generated a new configuration file. romeConfig.xml Please edit this file and restart the program. |
The program writes the configuration file and terminates. Open the file named 'romeConfig.xml' located in your working directory. It will look like this:
<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="c:/rome/rome/romeConfig.xsd"> <MainConfiguration> <RunNumbers></RunNumbers> <EventNumbers></EventNumbers> <InputFileNames></InputFileNames> <Modes> <AnalyzingMode>offline</AnalyzingMode> <DAQSystem>none</DAQSystem> <BatchMode>false</BatchMode> <ShowSplashScreen>true</ShowSplashScreen> </Modes> <Online> <Host></Host> <Experiment></Experiment> </Online> <SocketInterface> <PortNumber>9090</PortNumber> <AvailableOffline>false</AvailableOffline> </SocketInterface> <Paths> <InputFilePath>./</InputFilePath> <OutputFilePath>./</OutputFilePath> </Paths> <Tasks> <Task> <TaskName>PrintADCValues</TaskName> <Active>false</Active> </Task> </Tasks> <Trees> <Accumulate>false</Accumulate> <Tree> <TreeName>DataTree</TreeName> <Read>false</Read> <Write>false</Write> <Fill>false</Fill> <CompressionLevel>0</CompressionLevel> <MaxNumberOfEntries>0</MaxNumberOfEntries> <TreeOutputFileName></TreeOutputFileName> </Tree> </Trees> <GlobalSteeringParameters> <SteeringParameterField> <SPName>OutputOnOff</SPName> <SPValue>false</SPValue> </SteeringParameterField> </GlobalSteeringParameters> <Midas/> </MainConfiguration> </Configuration> |
The 'RunNumbers', 'EventNumbers' and 'InputFileNames' tags are used by the DAQ system. Since we don't want a DAQ system yet we ignore these tags. How to include a DAQ system into your analyzer is explained in include a DAQ system.
The 'Modes' section doesn't need any changes either. We want to run offline without a DAQ system.
The 'Online' section will be explained on the include a DAQ system page too.
The 'Paths' section tells the framework where the input and output files are located. We don't have any input files for our analyzer, but we write out a tree. Therefore we specify a path in the 'OutputFilePath' tag :
<Paths>
<InputFilePath>./</InputFilePath>
<OutputFilePath>./data</OutputFilePath>
</Paths>
In the 'Tasks' section there is one task 'PrintADCValues'. We want this task to be executed, therefore we set it active :
<Tasks>
<Task>
<TaskName>PrintADCValues</TaskName>
<Active>true</Active>
</Task>
</Tasks>
In the 'Trees' section there is one tree 'DataTree'. We want this tree to be filled and written to disc, therefore we set the write and the fill flag :
<Trees>
<Accumulate>false</Accumulate>
<Tree>
<TreeName>DataTree</TreeName>
<Read>false</Read>
<Write>true</Write>
<Fill>true</Fill>
<CompressionLevel>0</CompressionLevel>
<MaxNumberOfEntries>0</MaxNumberOfEntries>
<TreeOutputFileName></TreeOutputFileName>
</Tree>
</Trees>
In the 'GlobalSteeringParameters' section there is one steering parameter 'OutputOnOff'. For the first run we turn the output off :
<GlobalSteeringParameters>
<SteeringParameterField>
<SPName>OutputOnOff</SPName>
<SPValue>false</SPValue>
</SteeringParameterField>
</GlobalSteeringParameters>
Now we launch the program again. You can stop the program with '.q' command as ROOT interaction mode.
The program shows a start screen and the 'Program steering' :
Program steering
----------------
q : Terminates the program
e : Ends the program
s : Stops the program
r : Restarts the program
c : Continuous Analysis
o : Step by step Analysis
g : Run until event #
i : Root interpreter
The user can control the program execution by typing one of the above described letters.
Then the program tells you which run has been started and which event is being processed. Since our analyzer doesn't do much the progress is quite fast. Type 'q' to stop the program execution.
If we set the steering parameter 'OutputOnOff' to true and restart the program, it will now write out the contents of the 'PMTData' folder.
Matthias Schneebeli, Ryu Sawada | |
e-mail: ryu.sawada@cern.ch |