Commit 1ab3031e authored by Riccardo Longo's avatar Riccardo Longo
Browse files

Add basic structure. Analysis code developed by Yakov; cmake + doxygen done by Riccardo

parent 39245bb6
message("${BoldYellow}----------------------------")
message("Preparing Analysis libraries...")
message("----------------------------${ColourReset}")
include_directories(${CMAKE_SOURCE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/Analysis/include)
#In the following the list of source files to be linked
set (ANALYSIS_SRC_DIR "${CMAKE_SOURCE_DIR}/Analysis/src")
#### Get all header files
FILE(GLOB_RECURSE PA_INC
"${CMAKE_SOURCE_DIR}/Analysis/include/*.hh"
)
add_executable(AnalysisExample ${ANALYSIS_SRC_DIR}/DataReader.cpp ${ANALYSIS_SRC_DIR}/WFAnalysis.cpp userFunctions/AnalysisExample.cpp)
TARGET_LINK_LIBRARIES(AnalysisExample ${ROOT_LIBRARIES})
install(TARGETS AnalysisExample RUNTIME DESTINATION bin)
# - Find ROOT instalation
# This module tries to find the ROOT installation on your system.
# It tries to find the root-config script which gives you all the needed information.
# If the system variable ROOTSYS is set this is straight forward.
# If not the module uses the pathes given in ROOT_CONFIG_SEARCHPATH.
# If you need an other path you should add this path to this varaible.
# The root-config script is then used to detect basically everything else.
# This module defines a number of key variables and macros.
# F.Uhlig@gsi.de (fairroot.gsi.de)
MESSAGE(STATUS "Looking for Root...")
SET(ROOT_CONFIG_SEARCHPATH
${SIMPATH}/tools/root/bin
/usr/local/Cellar/root/6.14.04_2/bin
)
SET(ROOT_DEFINITIONS "")
SET(ROOT_INSTALLED_VERSION_TOO_OLD FALSE)
SET(ROOT_CONFIG_EXECUTABLE ROOT_CONFIG_EXECUTABLE-NOTFOUND)
FIND_PROGRAM(ROOT_CONFIG_EXECUTABLE NAMES root-config PATHS
${ROOT_CONFIG_SEARCHPATH}
NO_DEFAULT_PATH)
IF (${ROOT_CONFIG_EXECUTABLE} MATCHES "ROOT_CONFIG_EXECUTABLE-NOTFOUND")
MESSAGE( FATAL_ERROR "ROOT not installed in the searchpath and ROOTSYS is not set. Please
set ROOTSYS or add the path to your ROOT installation in the Macro FindROOT.cmake in the
subdirectory cmake/modules.")
ELSE (${ROOT_CONFIG_EXECUTABLE} MATCHES "ROOT_CONFIG_EXECUTABLE-NOTFOUND")
STRING(REGEX REPLACE "(^.*)/bin/root-config" "\\1" test ${ROOT_CONFIG_EXECUTABLE})
SET( ENV{ROOTSYS} ${test})
set( ROOTSYS ${test})
ENDIF (${ROOT_CONFIG_EXECUTABLE} MATCHES "ROOT_CONFIG_EXECUTABLE-NOTFOUND")
IF (ROOT_CONFIG_EXECUTABLE)
SET(ROOT_FOUND FALSE)
EXEC_PROGRAM(${ROOT_CONFIG_EXECUTABLE} ARGS "--version" OUTPUT_VARIABLE ROOTVERSION)
MESSAGE(STATUS "Looking for Root... - found $ENV{ROOTSYS}/bin/root")
MESSAGE(STATUS "Looking for Root... - version ${ROOTVERSION} ")
# we need at least version 5.00/00
IF (NOT ROOT_MIN_VERSION)
SET(ROOT_MIN_VERSION "5.00/00")
ENDIF (NOT ROOT_MIN_VERSION)
# now parse the parts of the user given version string into variables
STRING(REGEX REPLACE "^([0-9]+)\\.[0-9][0-9]+\\/[0-9][0-9]+" "\\1" req_root_major_vers "${ROOT_MIN_VERSION}")
STRING(REGEX REPLACE "^[0-9]+\\.([0-9][0-9])+\\/[0-9][0-9]+.*" "\\1" req_root_minor_vers "${ROOT_MIN_VERSION}")
STRING(REGEX REPLACE "^[0-9]+\\.[0-9][0-9]+\\/([0-9][0-9]+)" "\\1" req_root_patch_vers "${ROOT_MIN_VERSION}")
# and now the version string given by qmake
STRING(REGEX REPLACE "^([0-9]+)\\.[0-9][0-9]+\\/[0-9][0-9]+.*" "\\1" found_root_major_vers "${ROOTVERSION}")
STRING(REGEX REPLACE "^[0-9]+\\.([0-9][0-9])+\\/[0-9][0-9]+.*" "\\1" found_root_minor_vers "${ROOTVERSION}")
STRING(REGEX REPLACE "^[0-9]+\\.[0-9][0-9]+\\/([0-9][0-9]+).*" "\\1" found_root_patch_vers "${ROOTVERSION}")
IF (found_root_major_vers LESS 5)
MESSAGE( FATAL_ERROR "Invalid ROOT version \"${ROOTERSION}\", at least major version 4 is required, e.g. \"5.00/00\"")
ENDIF (found_root_major_vers LESS 5)
# compute an overall version number which can be compared at once
MATH(EXPR req_vers "${req_root_major_vers}*10000 + ${req_root_minor_vers}*100 + ${req_root_patch_vers}")
MATH(EXPR found_vers "${found_root_major_vers}*10000 + ${found_root_minor_vers}*100 + ${found_root_patch_vers}")
IF (found_vers LESS req_vers)
SET(ROOT_FOUND FALSE)
SET(ROOT_INSTALLED_VERSION_TOO_OLD TRUE)
ELSE (found_vers LESS req_vers)
SET(ROOT_FOUND TRUE)
ENDIF (found_vers LESS req_vers)
ENDIF (ROOT_CONFIG_EXECUTABLE)
IF (ROOT_FOUND)
# ask root-config for the library dir
# Set ROOT_LIBRARY_DIR
EXEC_PROGRAM( ${ROOT_CONFIG_EXECUTABLE}
ARGS "--libdir"
OUTPUT_VARIABLE ROOT_LIBRARY_DIR_TMP )
IF(EXISTS "${ROOT_LIBRARY_DIR_TMP}")
SET(ROOT_LIBRARY_DIR ${ROOT_LIBRARY_DIR_TMP} )
ELSE(EXISTS "${ROOT_LIBRARY_DIR_TMP}")
MESSAGE("Warning: ROOT_CONFIG_EXECUTABLE reported ${ROOT_LIBRARY_DIR_TMP} as library path,")
MESSAGE("Warning: but ${ROOT_LIBRARY_DIR_TMP} does NOT exist, ROOT must NOT be installed correctly.")
ENDIF(EXISTS "${ROOT_LIBRARY_DIR_TMP}")
# ask root-config for the binary dir
EXEC_PROGRAM(${ROOT_CONFIG_EXECUTABLE}
ARGS "--bindir"
OUTPUT_VARIABLE root_bins )
SET(ROOT_BINARY_DIR ${root_bins})
# ask root-config for the include dir
EXEC_PROGRAM( ${ROOT_CONFIG_EXECUTABLE}
ARGS "--incdir"
OUTPUT_VARIABLE root_headers )
SET(ROOT_INCLUDE_DIR ${root_headers})
# CACHE INTERNAL "")
# ask root-config for the library varaibles
EXEC_PROGRAM( ${ROOT_CONFIG_EXECUTABLE}
# ARGS "--noldflags --noauxlibs --libs"
ARGS "--glibs"
OUTPUT_VARIABLE root_flags )
# STRING(REGEX MATCHALL "([^ ])+" root_libs_all ${root_flags})
# STRING(REGEX MATCHALL "-L([^ ])+" root_library ${root_flags})
# REMOVE_FROM_LIST(root_flags "${root_libs_all}" "${root_library}")
SET(ROOT_LIBRARIES ${root_flags})
# Make variables changeble to the advanced user
MARK_AS_ADVANCED( ROOT_LIBRARY_DIR ROOT_INCLUDE_DIR ROOT_DEFINITIONS)
# Set ROOT_INCLUDES
SET( ROOT_INCLUDES ${ROOT_INCLUDE_DIR})
SET(LD_LIBRARY_PATH ${LD_LIBRARY_PATH} ${ROOT_LIBRARY_DIR})
#######################################
#
# Check the executables of ROOT
# ( rootcint )
#
#######################################
FIND_PROGRAM(ROOT_CINT_EXECUTABLE
NAMES rootcint
PATHS ${ROOT_BINARY_DIR}
NO_DEFAULT_PATH
)
ENDIF (ROOT_FOUND)
###########################################
#
# Macros for building ROOT dictionary
#
###########################################
MACRO (ROOT_GENERATE_DICTIONARY_OLD )
set(INFILES "")
foreach (_current_FILE ${ARGN})
IF (${_current_FILE} MATCHES "^.*\\.h$")
IF (${_current_FILE} MATCHES "^.*Link.*$")
set(LINKDEF_FILE ${_current_FILE})
ELSE (${_current_FILE} MATCHES "^.*Link.*$")
set(INFILES ${INFILES} ${_current_FILE})
ENDIF (${_current_FILE} MATCHES "^.*Link.*$")
ELSE (${_current_FILE} MATCHES "^.*\\.h$")
IF (${_current_FILE} MATCHES "^.*\\.cxx$")
set(OUTFILE ${_current_FILE})
ELSE (${_current_FILE} MATCHES "^.*\\.cxx$")
set(INCLUDE_DIRS ${INCLUDE_DIRS} -I${_current_FILE})
ENDIF (${_current_FILE} MATCHES "^.*\\.cxx$")
ENDIF (${_current_FILE} MATCHES "^.*\\.h$")
endforeach (_current_FILE ${ARGN})
# MESSAGE("INFILES: ${INFILES}")
# MESSAGE("OutFILE: ${OUTFILE}")
# MESSAGE("LINKDEF_FILE: ${LINKDEF_FILE}")
# MESSAGE("INCLUDE_DIRS: ${INCLUDE_DIRS}")
STRING(REGEX REPLACE "(^.*).cxx" "\\1.h" bla "${OUTFILE}")
# MESSAGE("BLA: ${bla}")
SET (OUTFILES ${OUTFILE} ${bla})
ADD_CUSTOM_COMMAND(OUTPUT ${OUTFILES}
COMMAND ${ROOT_CINT_EXECUTABLE}
ARGS -f ${OUTFILE} -c -DHAVE_CONFIG_H ${INCLUDE_DIRS} ${INFILES} ${LINKDEF_FILE} DEPENDS ${INFILES})
# MESSAGE("ROOT_CINT_EXECUTABLE has created the dictionary ${OUTFILE}")
ENDMACRO (ROOT_GENERATE_DICTIONARY_OLD)
###########################################
#
# Macros for building ROOT dictionary
#
###########################################
MACRO (ROOT_GENERATE_DICTIONARY INFILES LINKDEF_FILE OUTFILE INCLUDE_DIRS_IN)
set(INCLUDE_DIRS)
foreach (_current_FILE ${INCLUDE_DIRS_IN})
set(INCLUDE_DIRS ${INCLUDE_DIRS} -I${_current_FILE})
endforeach (_current_FILE ${INCLUDE_DIRS_IN})
# MESSAGE("INFILES: ${INFILES}")
# MESSAGE("OutFILE: ${OUTFILE}")
# MESSAGE("LINKDEF_FILE: ${LINKDEF_FILE}")
# MESSAGE("INCLUDE_DIRS: ${INCLUDE_DIRS}")
STRING(REGEX REPLACE "^(.*)\\.(.*)$" "\\1.h" bla "${OUTFILE}")
# MESSAGE("BLA: ${bla}")
SET (OUTFILES ${OUTFILE} ${bla})
if (CMAKE_SYSTEM_NAME MATCHES Linux)
ADD_CUSTOM_COMMAND(OUTPUT ${OUTFILES}
COMMAND ROOTSYS=${ROOTSYS} ${ROOT_CINT_EXECUTABLE}
ARGS -f ${OUTFILE} -c -DHAVE_CONFIG_H ${INCLUDE_DIRS} ${INFILES} ${LINKDEF_FILE} DEPENDS ${INFILES} ${LINKDEF_FILE})
else (CMAKE_SYSTEM_NAME MATCHES Linux)
if (CMAKE_SYSTEM_NAME MATCHES Darwin)
ADD_CUSTOM_COMMAND(OUTPUT ${OUTFILES}
COMMAND DYLD_LIBRARY_PATH=${ROOT_LIBRARY_DIR} ROOTSYS=${ROOTSYS} ${ROOT_CINT_EXECUTABLE}
ARGS -f ${OUTFILE} -c -DHAVE_CONFIG_H ${INCLUDE_DIRS} ${INFILES} ${LINKDEF_FILE} DEPENDS ${INFILES} ${LINKDEF_FILE})
endif (CMAKE_SYSTEM_NAME MATCHES Darwin)
endif (CMAKE_SYSTEM_NAME MATCHES Linux)
ENDMACRO (ROOT_GENERATE_DICTIONARY)
MACRO (GENERATE_ROOT_TEST_SCRIPT SCRIPT_FULL_NAME)
get_filename_component(path_name ${SCRIPT_FULL_NAME} PATH)
get_filename_component(file_extension ${SCRIPT_FULL_NAME} EXT)
get_filename_component(file_name ${SCRIPT_FULL_NAME} NAME_WE)
set(shell_script_name "${file_name}.sh")
#MESSAGE("PATH: ${path_name}")
#MESSAGE("Ext: ${file_extension}")
#MESSAGE("Name: ${file_name}")
#MESSAGE("Shell Name: ${shell_script_name}")
string(REPLACE ${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR} new_path ${path_name}
)
#MESSAGE("New PATH: ${new_path}")
file(MAKE_DIRECTORY ${new_path}/data)
CONVERT_LIST_TO_STRING(${LD_LIBRARY_PATH})
set(MY_LD_LIBRARY_PATH ${output})
set(my_script_name ${SCRIPT_FULL_NAME})
if(CMAKE_SYSTEM MATCHES Darwin)
configure_file(${PROJECT_SOURCE_DIR}/cmake/scripts/root_macro_macos.sh.in
${new_path}/${shell_script_name}
)
else(CMAKE_SYSTEM MATCHES Darwin)
configure_file(${PROJECT_SOURCE_DIR}/cmake/scripts/root_macro.sh.in
${new_path}/${shell_script_name}
)
endif(CMAKE_SYSTEM MATCHES Darwin)
EXEC_PROGRAM(/bin/chmod ARGS "u+x ${new_path}/${shell_script_name}")
ENDMACRO (GENERATE_ROOT_TEST_SCRIPT)
/** @file Analysis
* @brief Function prototypes for Analysis
*
* This contains the prototypes and members
* for Analysis
*
* @author Yakov Kulinich
* @bug No known bugs.
*/
#ifndef ANALYSIS_H
#define ANALYSIS_H
#include <string>
#include <vector>
class TFile;
class TH1;
class TH2;
class TH3;
class TTree;
class Analysis{
public:
Analysis( ){};
Analysis( const std::string& ){};
virtual ~Analysis( ){};
virtual void Initialize ( ) = 0;
virtual void SetupHistograms( ) = 0;
virtual void AnalyzeEvent ( const std::vector< TH1* >& ) = 0;
virtual void AnalyzeEvent ( const std::vector< std::vector< float > >& ) = 0;
virtual void Finalize ( ) = 0;
protected:
std::string m_fNameOut;
TFile* m_fOut;
};
#endif
/** @file DataReader
* @brief Function prototypes for DataReader
*
* This contains the prototypes and members
* for DataReader
*
* @author Yakov Kulinich
* @bug No known bugs.
*/
#ifndef DATAREADER_H
#define DATAREADER_H
#include <string>
#include <vector>
class TFile;
class Analysis;
class DataReader{
public:
DataReader( );
DataReader( const unsigned int = 0, const unsigned int = 0 );
DataReader( const unsigned int = 0, const unsigned int = 0, const std::string& = "" );
DataReader( const unsigned int = 0, const unsigned int = 0,
const std::string& = "", const unsigned int = 0 );
virtual ~DataReader();
void Initialize ( );
void ProcessEvents( );
void Finalize ( );
private:
Analysis* m_ana;
//Number of channels to be read
unsigned int m_nCh;
//Number of samples per channel
unsigned int m_nSamp;
//Input file name
std::string m_fNameIn;
//Run number
unsigned int m_runNumber;
//Boolean switch to enable the reading of a list of files
bool m_readListOfFiles;
TFile* m_fIn;
};
#endif
/** @file WFAnalysis
* @brief Function prototypes for WFAnalysis
*
* This contains the prototypes and members
* for WFAnalysis
*
* @author Yakov Kulinich
* @bug No known bugs.
*/
#ifndef WFANALYSIS_H
#define WFANALYSIS_H
#include "Analysis.h"
class WFAnalysis : public Analysis{
public :
WFAnalysis( );
WFAnalysis( const std::string& = "" );
virtual ~WFAnalysis( );
virtual void Initialize ( );
virtual void SetupHistograms( );
virtual void AnalyzeEvent ( const std::vector< TH1* >& );
virtual void AnalyzeEvent ( const std::vector< std::vector< float > >& );
virtual void Finalize ( );
};
#endif
/** @file DataReader.cxx
* @brief Implementation of DataReader.
*
* Function definitions for DataReader are provided.
* This class reads a rootfile with raw waveforms
* that are processed by rcdaqAnalysis running on prdf files.
* Then, in the event loop, analysis classes can be called.
*
* @author Yakov Kulinich, Riccardo Longo
* @bug No known bugs.
*/
#include <TFile.h>
#include <TTree.h>
#include <TH1.h>
#include <TCanvas.h>
#include <iostream>
#include "DataReader.h"
#include "WFAnalysis.h"
/** @brief Default Constructor for DataReader.
*/
DataReader::DataReader() : DataReader( 0, 0, "", 0 ){
}
/** @brief Constructor for DataReader.
*
* @param1 Number of channels being read
* @param2 Number of samples per channel
*/
DataReader::DataReader( const unsigned int nCh, const unsigned int nSamp )
: DataReader( nCh, nSamp, "", 0 ){
// here say we will read in list of files, maybe
// there is better way to do it, just an idea for now.
m_readListOfFiles = true;
}
/** @brief Constructor for DataReader.
*
* @param1 Number of channels being read
* @param2 Number of samples per channel
* @param3 Input filename.
*/
DataReader::DataReader( const uint nCh, const uint nSamp,
const std::string& fNameIn )
: DataReader( nCh, nSamp, fNameIn, 0 ){
}
/** @brief Constructor for DataReader.
*
* @param1 Number of channels being read
* @param2 Number of samples per channel
* @param4 Output file name (custom)
* @param3 Run number being used.
*/
DataReader::DataReader( const uint nCh, const uint nSamp,
const std::string& fNameIn, const uint runNum )
: m_nCh( nCh ), m_nSamp( nSamp ),
m_fNameIn( fNameIn ), m_runNumber( runNum ),
m_ana( NULL ), m_fIn( NULL ){
}
/** @brief Destructor for DataReader.
*/
DataReader::~DataReader(){
delete m_fIn;
}
/** @brief Initialization method for DataReader
*
* Select which file(s) to read. For now just a single
* file, later this can be extended to read many and make
* chain of files for example. Also create and initialize
* the analysis that will be running.
*
* @return none
*/
void DataReader::Initialize(){
// If we are reading a list of files, or have no run number
// make default name output.root, otherwise make it
// outputN.root, where N is a run number of a file.
std::string fNameOut = m_readListOfFiles ?
"output.root" : Form( "output%d.root", m_runNumber );
if( m_readListOfFiles ){
// for now do nothing. Was thinking of having
// a file called inputFiles.txt, from which to
// read a list of files. TBD (I am in Berlin now).
} else {
m_fIn = TFile::Open( m_fNameIn.c_str() );
}
m_ana = new WFAnalysis( fNameOut );
m_ana->Initialize();
m_ana->SetupHistograms();
}
/** @brief Process Events method for DataReader
*
* Connect to files / chain of files.
* Read tree event by event, and fill basic waveforms.
* So far (12.12.18) For each event - Read Raw data for all channels,
* put it into 2D vector size NxM where N = nCh, M = nSamp
* Also, For each event - Fill N 1D histos that have size M.
* Then one can send these to any Analysis function they make.
* Here for example (12.12.18), we send to WFAnalysis::AnalyzeEvent( .. )
* See below - Have fun!
*
* @return none
*/
void DataReader::ProcessEvents(){
std::vector< std::vector< float > > vWF;
std::vector< std::vector< float >* > pvWF;
std::vector< TH1* > vWFH;
vWF .resize( m_nCh );
pvWF.resize( m_nCh );
vWFH.resize( m_nCh );
TTree* tree = static_cast< TTree* >
( m_fIn->Get( "tree" ) );
// Connect raw data to tree
// Also create the histograms to fill
for( uint ch = 0; ch < m_nCh; ch++ ){
pvWF[ ch ] = &vWF[ ch ];
tree->SetBranchAddress( Form( "RawC%d", ch ), &pvWF[ ch ] );
vWFH[ ch ] = new TH1D( Form( "hWF%d", ch ), Form( "hWF%d;samp;amp", ch ), m_nSamp, 0, m_nSamp );
}
std::cout << "File: " << m_fIn->GetName() << " has "
<< tree->GetEntries() << " events." << std::endl;
// !! EVENT LOOP
for( int ev = 0; ev < tree->GetEntries(); ev++ ){
tree->GetEntry( ev );
// Fill the waveforms
for( uint ch = 0; ch < m_nCh; ch++ ){
vWFH[ ch ]->Reset();
// Loop over samples in each channel
for( uint samp = 0; samp < m_nSamp; samp++ ){
vWFH[ ch ]->SetBinContent( samp + 1, vWF[ ch ][ samp ] );
} // End loop over samples in each channel
} // End loop over channels
// Now call analysis. With the provided WFAnalysis,
// Can either send a vector of histos, or a 2D vector
// Of all the data, depending on what you want to do.
m_ana->AnalyzeEvent( vWFH );
m_ana->AnalyzeEvent( vWF );
} // End event loop
for( auto& h : vWFH ){ delete h; }
}
/** @brief Finalize method for DataReader
*
* Close any input files
* Call analysis finalize methods
*
* @return none
*/
void DataReader::Finalize(){
if( m_fIn ){
m_fIn->Close();
}
m_ana->Finalize();
}
/** @file WFAnalysis.cxx
* @brief Implementation of WFAnalysis.
*
* Function definitions for WFAnalysis are provided.
* This class is the main class for the waveform analysis.
* It initializes the histograms used for output of processed events.
* Also includes methods that accept all waveforms in an event.
* This is where the analysis should be done.
*