Commit c28332be authored by Breno Rilho Lemos's avatar Breno Rilho Lemos 💬
Browse files

Include aliRoot execution

parent ecaa9acf
/**************************************************************************
* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
* *
* Author: The ALICE Off-line Project. *
* Contributors are mentioned in the code where appropriate. *
* *
* Permission to use, copy, modify and distribute this software and its *
* documentation strictly for non-commercial purposes is hereby granted *
* without fee, provided that the above copyright notice appears in all *
* copies and that both the copyright notice and this permission notice *
* appear in the supporting documentation. The authors make no claims *
* about the suitability of this software for any purpose. It is *
* provided "as is" without express or implied warranty. *
**************************************************************************/
/* AddMyTask
*
* empty task which can serve as a starting point for building an analysis
* as an example, one histogram is filled
*/
// Author: Redmer A. Bertens, Utrecht University, 2012
class AliAnalysisDataContainer;
AliAnalysisTaskMyTask* AddMyTask(TString name = "name")
{
// get the manager via the static access member. since it's static, you don't need
// an instance of the class to call the function
AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
if (!mgr) {
return 0x0;
}
// get the input event handler, again via a static method.
// this handler is part of the managing system and feeds events
// to your task
if (!mgr->GetInputEventHandler()) {
return 0x0;
}
// by default, a file is open for writing. here, we get the filename
TString fileName = AliAnalysisManager::GetCommonFileName();
fileName += ":MyTask"; // create a subfolder in the file
// now we create an instance of your task
AliAnalysisTaskMyTask* task = new AliAnalysisTaskMyTask(name.Data());
if(!task) return 0x0;
// add your task to the manager
mgr->AddTask(task);
// your task needs input: here we connect the manager to your task
mgr->ConnectInput(task,0,mgr->GetCommonInputContainer());
// same for the output
mgr->ConnectOutput(task,1,mgr->CreateContainer("MyOutputContainer", TList::Class(), AliAnalysisManager::kOutputContainer, fileName.Data()));
// in the end, this macro returns a pointer to your task. this will be convenient later on
// when you will run your analysis in an analysis train on grid
return task;
}
/**************************************************************************
* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
* *
* Author: The ALICE Off-line Project. *
* Contributors are mentioned in the code where appropriate. *
* *
* Permission to use, copy, modify and distribute this software and its *
* documentation strictly for non-commercial purposes is hereby granted *
* without fee, provided that the above copyright notice appears in all *
* copies and that both the copyright notice and this permission notice *
* appear in the supporting documentation. The authors make no claims *
* about the suitability of this software for any purpose. It is *
* provided "as is" without express or implied warranty. *
**************************************************************************/
/* AliAnaysisTaskMyTask
*
* empty task which can serve as a starting point for building an analysis
* as an example, one histogram is filled
*/
#include "TChain.h"
#include "TH1F.h"
#include "TList.h"
#include "AliAnalysisTask.h"
#include "AliAnalysisManager.h"
#include "AliESDEvent.h"
#include "AliESDInputHandler.h"
#include "AliAnalysisTaskMyTask.h"
#include "AliESDtrack.h"
#include "AliESDVertex.h"
#include "AliVertex.h"
#include "Riostream.h"
Int_t esd_event_id = 0; // global variable to store unique event id
Int_t smallEventID = 0; // is equal to esd-event-id until the selected event (one with an appropriate number of tracks) is reached
Int_t mediumEventID = 0; // for events with ~200 tracks
Int_t largeEventID = 0; // for events with many many tracks
class AliAnalysisTaskMyTask; // your analysis class
using namespace std; // std namespace: so you can do things like 'cout'
ClassImp(AliAnalysisTaskMyTask) // classimp: necessary for root
AliAnalysisTaskMyTask::AliAnalysisTaskMyTask() : AliAnalysisTaskSE(),
fESD(0), fOutputList(0), fHistPt(0), fHistEvents(0), fHistMass(0)
{
// default constructor, don't allocate memory here!
// this is used by root for IO purposes, it needs to remain empty
}
//_____________________________________________________________________________
AliAnalysisTaskMyTask::AliAnalysisTaskMyTask(const char* name) : AliAnalysisTaskSE(name),
fESD(0), fOutputList(0), fHistPt(0), fHistEvents(0), fHistMass(0)
{
// constructor
DefineInput(0, TChain::Class()); // define the input of the analysis: in this case we take a 'chain' of events
// this chain is created by the analysis manager, so no need to worry about it,
// it does its work automatically
DefineOutput(1, TList::Class()); // define the ouptut of the analysis: in this case it's a list of histograms
// you can add more output objects by calling DefineOutput(2, classname::Class())
// if you add more output objects, make sure to call PostData for all of them, and to
// make changes to your AddTask macro!
}
//_____________________________________________________________________________
AliAnalysisTaskMyTask::~AliAnalysisTaskMyTask()
{
// destructor
if(fOutputList) {
delete fOutputList; // at the end of your task, it is deleted from memory by calling this function
}
}
//_____________________________________________________________________________
void AliAnalysisTaskMyTask::UserCreateOutputObjects()
{
// create output objects
//
// this function is called ONCE at the start of your analysis (RUNTIME)
// here you ceate the histograms that you want to use
//
// the histograms are in this case added to a tlist, this list is in the end saved
// to an output file
//
fOutputList = new TList(); // this is a list which will contain all of your histograms
// at the end of the analysis, the contents of this list are written
// to the output file
fOutputList->SetOwner(kTRUE); // memory stuff: the list is owner of all objects it contains and will delete them
// if requested (dont worry about this now)
// example of a histogram
fHistPt = new TH1F("fHistPt", "fHistPt", 100, 0, 10); // create your histogra
fOutputList->Add(fHistPt); // don't forget to add it to the list! the list will be written to file, so if you want
// your histogram in the output file, add it to the list!
// my mass histogram
Double_t fHistMassEdges[12] = {0.0,0.0005,0.0405,0.08,0.12,0.13,0.17,0.48,0.52,0.92,0.96,1.0}; // 11 bins =>> has 11+1 = 12 edges
fHistMass = new TH1F("fHistMass","Particle Histogram;M_{particle}", 11, fHistMassEdges);
fOutputList->Add(fHistMass);
// Histograms for dimuons
fHistEvents = new TH1F("fHistEvents","fHistEvents;N_{events}",100,0.,10000.);
fOutputList->Add(fHistEvents);
PostData(1, fOutputList); // postdata will notify the analysis manager of changes / updates to the
// fOutputList object. the manager will in the end take care of writing your output to file
// so it needs to know what's in the output
}
//_____________________________________________________________________________
void AliAnalysisTaskMyTask::UserExec(Option_t *)
{
// user exec
// this function is called once for each event
// the manager will take care of reading the events from file, and with the static function InputEvent() you
// have access to the current event.
// once you return from the UserExec function, the manager will retrieve the next event from the chain
Int_t Event=0;
Int_t TrigEvent=0;
ofstream s_detail, m_detail, l_detail;
s_detail.open ("s-esd-detail.dat",std::ofstream::app);
m_detail.open ("m-esd-detail.dat",std::ofstream::app);
l_detail.open ("l-esd-detail.dat",std::ofstream::app);
fESD = dynamic_cast<AliESDEvent*>(InputEvent()); // get an event (called fESD) from the input file
// there's another event format (ESD) which works in a similar way
if(!fESD) return; // if the pointer to the event is empty (getting it failed) skip this event
// example part: i'll show how to loop over the tracks in an event
// and extract some information from them which we'll store in a histogram
Int_t iTracks(fESD->GetNumberOfTracks()); // see how many tracks there are in the event
Double_t Vx = 0.01 * fESD->GetPrimaryVertex()->GetX(); // gets vertexes from individual events, in METERS
Double_t Vy = 0.01 * fESD->GetPrimaryVertex()->GetY();
Double_t Vz = 0.01 * fESD->GetPrimaryVertex()->GetZ();
Double_t MagneticField = 0.1 * fESD->GetMagneticField(); // gets magnetic field, in TESLA
/*
Assumed Units: Mass (GeV/c^2)[CONFIRMED] || Energy (GeV) || Momentum (GeV/c) || Charge (* 1.6*10^-19 C)
*/
if(smallEventID == esd_event_id) {
if(iTracks >= 15 && iTracks <= 30) {smallEventID = -1;}
else {smallEventID++;}
} else {smallEventID = -2;}
if(mediumEventID == esd_event_id) {
if(iTracks >= 100 && iTracks <= 300) {mediumEventID = -1;}
else {mediumEventID++;}
} else {mediumEventID = -2;}
if(largeEventID == esd_event_id) {
if(iTracks >= 5000 && iTracks <= 50000) {largeEventID = -1;}
else {largeEventID++;}
} else {largeEventID = -2;}
for(Int_t i(0); i < iTracks; i++) { // loop over all these tracks
if(smallEventID == -1 || mediumEventID == -1 || largeEventID == -1) { // when we get to the selected event, fill histograms and write data
AliESDtrack* track = static_cast<AliESDtrack*>(fESD->GetTrack(i)); // get a track (type AliESDtrack) from the event
if(!track) continue; // if we failed, skip this track
Double_t Mass = track->M(); // returns the pion mass, if the particle can't be identified properly
Double_t Energy = track->E(); // Returns the energy of the particle given its assumed mass, but assumes the pion mass if the particle can't be identified properly.
Double_t Px = track->Px();
Double_t Py = track->Py();
Double_t Pt = track->Pt(); // transversal momentum, in case we need it
Double_t Pz = track->Pz();
Double_t Charge = track->Charge();
if (smallEventID == -1) {
// Add VERTEX (x, y, z), MASS, CHARGE and MOMENTUM (x, y, z) to esd-detail.dat file
s_detail << Vx << " " << Vy << " " << Vz << " ";
s_detail << Mass << " " << Charge << " ";
s_detail << Px << " " << Py << " " << Pz << endl;
}
if (mediumEventID == -1) {
// Add VERTEX (x, y, z), MASS, CHARGE and MOMENTUM (x, y, z) to esd-detail.dat file
m_detail << Vx << " " << Vy << " " << Vz << " ";
m_detail << Mass << " " << Charge << " ";
m_detail << Px << " " << Py << " " << Pz << endl;
}
if (largeEventID == -1) {
// Add VERTEX (x, y, z), MASS, CHARGE and MOMENTUM (x, y, z) to esd-detail.dat file
l_detail << Vx << " " << Vy << " " << Vz << " ";
l_detail << Mass << " " << Charge << " ";
l_detail << Px << " " << Py << " " << Pz << endl;
fHistPt->Fill(Pt); // plot the pt value of the track in a histogram
fHistMass->Fill(Mass);
}
}
}
Event++;
esd_event_id++; // Increment global esd_event_id
fHistEvents->Fill(Event);
s_detail.close();
m_detail.close();
l_detail.close();
// continue until all the tracks are processed
PostData(1, fOutputList); // stream the results the analysis of this event to
// the output manager which will take care of writing
// it to a file
}
//_____________________________________________________________________________
void AliAnalysisTaskMyTask::Terminate(Option_t *)
{
// terminate
// called at the END of the analysis (when all events are processed)
}
//_____________________________________________________________________________
/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. */
/* See cxx source for full Copyright notice */
/* $Id$ */
#ifndef AliAnalysisTaskMyTask_H
#define AliAnalysisTaskMyTask_H
#include "AliAnalysisTaskSE.h"
class AliAnalysisTaskMyTask : public AliAnalysisTaskSE
{
public:
AliAnalysisTaskMyTask();
AliAnalysisTaskMyTask(const char *name);
virtual ~AliAnalysisTaskMyTask();
virtual void UserCreateOutputObjects();
virtual void UserExec(Option_t* option);
virtual void Terminate(Option_t* option);
private:
AliESDEvent* fESD; //! input event
TList* fOutputList; //! output list
TH1F* fHistPt; //! dummy histogram
TH1F* fHistMass; //! my particle histogram!! :D
TH1F* fHistEvents; // Number of events
AliAnalysisTaskMyTask(const AliAnalysisTaskMyTask&); // not implemented
AliAnalysisTaskMyTask& operator=(const AliAnalysisTaskMyTask&); // not implemented
ClassDef(AliAnalysisTaskMyTask, 1);
};
#endif
# Project Description
This project has the purpose of generating a 3D animation of an ALICE particle collision event, inside the LHC, using data obtained from CERN's Open Data Portal, which makes ESDs - Event Summary Data files, that contain information about such events - open and available for analysis.
ESD files regarding the ALICE experiment can be found on http://opendata.cern.ch/search?page=1&size=20&experiment=ALICE, and they should be processed using the Aliroot software, as indicated by the Instructions section below
The software that makes the animation is Blender, which is free and open source. Blender's 2.79b version should be downloaded for this project, and can be found on https://www.blender.org/download/releases/2-79/
The animation making can be summarized in three basic steps:
1) Downloading of an ESD file (for example, any file on this list: http://opendata.cern.ch/record/1102);
2) Processing of ESD file using Aliroot macros (as indicated further);
3) Run code to generate Blender animation using the ESD processing results.
The code for step 3 can be found in the Blender_animation repository: https://git.cta.if.ufrgs.br/ALICE-open-data/alice-blender-animation/tree/ParticleTypes
# Sample macros for processing AliESDs from CERN Open Data Portal
## Requirements
Execute with aliroot5. Place `AliESDs.root` files in reach of the `chain->Add("AliESDs.root");` line on `runAnalysis.C` and execute.
## Instructions
1) Install aliBuild. Follow instructions on https://alice-doc.github.io/alice-analysis-tutorial/building/custom.html
2) Initialize AliPhysics
```bash
mkdir -p ~/alice
cd ~/alice
aliBuild init AliPhysics@master
```
3) Verify dependencies (Optional)
```bash
$ aliDoctor AliPhysics
```
4) Build AliPhysics with aliroot5 (this may take a long time)
```bash
aliBuild build AliPhysics --defaults user -z aliroot5
```
5) Enter AliPhysics environment
```bash
alienv enter AliPhysics/latest-aliroot5-user
```
6) Run the macro
```bash
aliroot runAnalysis.C
```
Results will be saved on three text files: `s-esd-detail.dat`, for an event with a 'small' number of tracks; `m-esd-detail.dat`, for an event with a medium number of tracks; `l-esd-detail.dat`, for an event with a very large number of tracks.
## Credits
The code used here is based on the ALICE analysis tutorial by Redmer A. Bertens.
// Exemplo obtido de https://stackoverflow.com/questions/28970124/cern-root-exporting-data-to-plain-text
#include <iostream>
#include "TFile.h"
#include "TTree.h"
#include <fstream>
using namespace std;
void dumpTreeTotxt(){
TFile *f=new TFile("AliESDs.root"); // opens the root file
TTree *tr=(TTree*)f->Get("esdTree"); // creates the TTree object
//tr->Scan(); // prints the content on the screen
float a,b,c; // create variables of the same type as the branches you want to access
tr->SetBranchAddress("AliESDRun",&a); // for all the TTree branches you need this
// tr->SetBranchAddress("AliESDHeader",&b);
//tr->SetBranchAddress("nserr",&c);
ofstream myfile;
myfile.open ("example.txt");
//myfile << "TS ns nserr\n";
for (int i=0;i<tr->GetEntries();i++){
// loop over the tree
cout << "Event: " << i << endl; //print to the screen
myfile << "Event: " << i << endl; //write to file
tr->GetEntry(i);
}
myfile.close();
}
void runAnalysis()
{
// Erase output txt files
ofstream s_detail, m_detail, l_detail;
s_detail.open ("s-esd-detail.dat");
s_detail << " " << endl;
s_detail.close();
m_detail.open ("m-esd-detail.dat");
m_detail << " " << endl;
m_detail.close();
l_detail.open ("l-esd-detail.dat");
l_detail << " " << endl;
l_detail.close();
// since we will compile a class, tell root where to look for headers
gROOT->ProcessLine(".include $ROOTSYS/include");
gROOT->ProcessLine(".include $ALICE_ROOT/include");
// create the analysis manager
AliAnalysisManager *mgr = new AliAnalysisManager("testAnalysis");
AliESDInputHandler *esdH = new AliESDInputHandler();
mgr->SetInputEventHandler(esdH);
// compile the class (locally)
gROOT->LoadMacro("AliAnalysisTaskMyTask.cxx++g");
// load the addtask macro
gROOT->LoadMacro("AddMyTask.C");
// create an instance of your analysis task
AliAnalysisTaskMyTask *task = AddMyTask();
if(!mgr->InitAnalysis()) return;
mgr->SetDebugLevel(2);
mgr->PrintStatus();
mgr->SetUseProgressBar(1, 25);
// if you want to run locally, we need to define some input
TChain* chain = new TChain("esdTree");
// add a few files to the chain (change this so that your local files are added)
chain->Add("AliESDs.root"); // Breno put it on the same directory that was cloned from Pezzi's // repository: AliESD_Example
chain->Add("AliESDs2.root");
//chain->Add("../root_files/AliAOD.Muons2.root");
//chain->Add("../root_files/AliAOD.Muons3.root");
//chain->Add("../root_files/AliAOD.Muons4.root");
// start the analysis locally, reading the events from the tchain
mgr->StartAnalysis("local", chain);
exit();
}
# ALICE Open Data Blender animation
## Project Description
This project has the purpose of generating a 3D animation of an ALICE particle collision event, inside the LHC, using data obtained from CERN's Open Data Portal, which makes ESDs - Event Summary Data files, that contain information about such events - open and available for analysis.
ESD files regarding the ALICE experiment can be found on http://opendata.cern.ch/search?page=1&size=20&experiment=ALICE, and they should be processed using the Aliroot software, as indicated in the 'Aliroot' section below.
// AliESD_Example git repository: https://git.cta.if.ufrgs.br/ALICE-open-data/AliESD_Example/tree/Blender_animation
The software that makes the animation is Blender, which is free and open source. Blender's 2.79b version should be downloaded for this project, and can be found on https://www.blender.org/download/releases/2-79/
Before starting, you must also clone this repository:
```bash
mkdir -p ~/alice
cd ~/alice
git init
git clone https://git.cta.if.ufrgs.br/ALICE-open-data/alice-blender-animation.git
```
The animation making can be summarized in three basic steps:
1) Downloading an ESD file;
2) Installing aliRoot and running macros;
3) Run bash to generate Blender animation using the ESD processing results.
## Step 1 - Downloading ESD files
ESD files regarding the ALICE experiment can be found on http://opendata.cern.ch/search?page=1&size=20&experiment=ALICE. If you have doubts on which file to pick for a test, you can select any file on this list: http://opendata.cern.ch/record/1102.
You must save your ESD file inside the 'aliRoot' directory, which is obtained by cloning this repository as mentioned above.
## Step 2 - Installing aliRoot
1) Install aliBuild. Follow instructions on https://alice-doc.github.io/alice-analysis-tutorial/building/custom.html
2) Initialize AliPhysics
```bash
cd ~/alice
aliBuild init AliPhysics@master
```
3) Verify dependencies (Optional)
```bash
$ aliDoctor AliPhysics
```
4) Build AliPhysics with aliroot5 (this may take a long time)
```bash
aliBuild build AliPhysics --defaults user -z aliroot5
```
5) Enter AliPhysics environment
```bash
alienv enter AliPhysics/latest-aliroot5-user
```
6) Run the macro
```bash
cd ~/alice/alice-blender-animation/aliRoot
aliroot runAnalysis.C
```
Results will be saved on three text files: `s-esd-detail.dat`, for an event with a 'small' number of tracks; `m-esd-detail.dat`, for an event with a 'medium' number of tracks; `l-esd-detail.dat`, for an event with a 'very large' number of tracks. You must then move those three files to the 'animate' folder, where the Blender scripts are.
## Step 3 - Generating animation
Run the script animate_particles.py as in the example below:
blender -noaudio --background -P animate_particles.py -- -radius=0.05 -duration=1 -camera="BarrelCamera" -datafile="esd-detail.dat" -simulated_t=0.02 -fps=24 -resolution=100
In the example above, argument 'radius' has value 0.05, 'duration' has value 10 and so on.
-radius:
particle radius; must be a number; type float
-duration:
animation duration; must be a number; type int
-camera:
defines animation view; must be a string; available options: OverviewCamera, BarrelCamera, ForwardCamera
-datafile:
filename for event data file; must be a string; must be one of your text files: `s-esd-detail.dat`, `m-esd-detail.dat`, `l-esd-detail.dat`
-simulated_t:
simulated time of event; must be a number; type float
-fps:
frames per second; must be a number; type int
-resolution:
animation resolution percent; must be a number; type int
Animation will be saved in format .mp4 on the address `/tmp/blender`
# -*- coding: utf-8 -*-
# animate_particles.py - Animate HEP events
#
# For console only rendering (example):
# $ blender -noaudio --background -P animate_particles.py -- -radius=0.05 -duration=1 -camera="BarrelCamera" -datafile="esd-detail.dat" -simulated_t=0.02 -fps=24 -resolution=100 -stamp_note="Texto no canto"
#
import os
import bpy
import argparse
import sys
# Pass on command line arguments to script:
class ArgumentParserForBlender(argparse.ArgumentParser):
def _get_argv_after_doubledash(self):
try:
idx = sys.argv.index("--")
return sys.argv[idx+1:] # the list after '--'
except ValueError as e: # '--' not in the list:
return []
# overrides superclass
def parse_args(self):
return super().parse_args(args=self._get_argv_after_doubledash())
parser = ArgumentParserForBlender()
parser.add_argument('-radius','--r_part')
parser.add_argument('-duration','--duration')
parser.add_argument('-camera','--render_camera')
parser.add_argument('-datafile','--datafile')
parser.add_argument('-simulated_t','--simulated_t')
parser.add_argument('-fps','--fps')
parser.add_argument('-resolution','--resolution_percent')
parser.add_argument('-stamp_note','--stamp_note')
args = parser.parse_args()
bpy.context.user_preferences.view.show_splash = False
# Import Drivers, partiles and scence functions:
filename = os.path.join(os.path.basename(bpy.data.filepath), "drivers.py")
exec(compile(open(filename).read(), filename, 'exec'))
# Set animation parameters
r_part = float(args.r_part) # Particle radius
simulated_t = float(args.simulated_t) # in microsseconds
duration = int(args.duration) # in seconds
fps = int(args.fps)
resolution_percent = int(args.resolution_percent)
#configure output
outputPath = "/tmp/blender/"
fileIdentifier = "PhysicalTrajectories_"
## RenderCameras: ["ForwardCamera", "OverviewCamera", "BarrelCamera"]
renderCamera= args.render_camera
renderAnimation = True # True
saveBlenderFile = False # False
"""
# Create and configure animation driver
n_particles = 100 # Event Multiplicity
driver = genDriver("GaussianGenerator",n_particles,3.0) # Simple genDriver takes two parameters: number of particles and Gaussian width
driver.configure(renderCamera, duration, fps, simulated_t, outputPath, fileIdentifier, resolution_percent)
"""
# Create and configure animation driver
driver = dataD