Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pwg-c2f/analysis/centrality
  • o.lubynets/centrality
2 results
Show changes
Commits on Source (31)
Showing
with 815 additions and 603 deletions
# Generated from CLion C/C++ Code Style settings
BasedOnStyle: LLVM
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignOperands: false
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 0
CompactNamespaces: false
ContinuationIndentWidth: 4
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 2
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PointerAlignment: Left
ReflowComments: false
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 0
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: Never
build/*
install/*
Doxygen/*
# Created by .ignore support plugin (hsz.mobi)
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
### C++ template
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
### CMake template
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
### C template
# Prerequisites
# Object files
*.ko
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
# Libraries
# Shared objects (inc. Windows DLLs)
*.so.*
# Executables
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
### Autotools template
# http://www.gnu.org/software/automake
Makefile.in
/ar-lib
/mdate-sh
/py-compile
/test-driver
/ylwrap
# http://www.gnu.org/software/autoconf
autom4te.cache
/autoscan.log
/autoscan-*.log
/aclocal.m4
/compile
/config.guess
/config.h.in
/config.log
/config.status
/config.sub
/configure
/configure.scan
/depcomp
/install-sh
/missing
/stamp-h1
# https://www.gnu.org/software/libtool/
/ltmain.sh
# http://www.gnu.org/software/texinfo
/texinfo.tex
# http://www.gnu.org/software/m4/
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
......@@ -2,7 +2,7 @@
build:
stage: build
script:
- source /home/vklochkov/Soft/root/root6/root-6.10.08/build/bin/thisroot.sh
- source /sft/ROOT/root_v6.14.06.Linux-ubuntu18-x86_64-gcc7.3/build/bin/thisroot.sh
- mkdir build && cd ./build
- cmake ../
- make
......@@ -12,7 +12,7 @@ build:
test:
stage: test
script:
- source /home/vklochkov/Soft/root/root6/root-6.10.08/build/bin/thisroot.sh
- source /sft/ROOT/root_v6.14.06.Linux-ubuntu18-x86_64-gcc7.3/build/bin/thisroot.sh
- mkdir build && cd ./build
- cmake ../
- make
......
Centrality
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />
\ No newline at end of file
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
\ No newline at end of file
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.5)
project(Centrality)
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_cpp_STANDARD 11)
set(CMAKE_BUILD_TYPE debug)
set(PROJECT_VERSION 1.0)
set(SOURCES
src/BordersFinder.cpp
src/BordersFinderHelper.cpp
src/Getter.cpp
src/BordersFinder2D.cpp
src/Container.cpp
glauber/Fitter.cpp
glauber/FitterHelper.cpp
)
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON)
message(STATUS "Using C++${CMAKE_CXX_STANDARD}")
# by default build optimized code with debug symbols
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release)
endif ()
string(REPLACE ".cpp" ".h" HEADERS "${SOURCES}")
# in DEBUG mode make verbose Makefile
if (CMAKE_BUILD_TYPE MATCHES DEBUG OR CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_VERBOSE_MAKEFILE ON)
endif ()
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -ggdb -DDEBUG -D__DEBUG -Wall -Wextra -fopenmp")
set(CMAKE_CXX_FLAGS_Debug "-O0 -ggdb -DDEBUG -D__DEBUG -Wall -Wextra -fopenmp")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -ftree-vectorize -ffast-math -DNODEBUG -fopenmp")
set(CMAKE_CXX_FLAGS_Release "-O3 -march=native -ftree-vectorize -ffast-math -DNODEBUG -fopenmp")
message(STATUS "Using CXX flags for ${CMAKE_BUILD_TYPE}: ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}")
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
# Telling CMake where to find the ROOT installation.
list(APPEND CMAKE_PREFIX_PATH $ENV{ROOTSYS})
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/lib")
list(APPEND CMAKE_PREFIX_PATH ${ROOTSYS})
#---Locate the ROOT package and defines a number of variables (e.g. ROOT_INCLUDE_DIRS)
find_package(ROOT REQUIRED COMPONENTS Core MathCore RIO Hist Tree)
find_package(AnalysisTree QUIET)
# Define useful ROOT functions and macros (e.g. ROOT_GENERATE_DICTIONARY)
message(STATUS "Using ROOT: ${ROOT_VERSION} <${ROOT_CONFIG}>")
include_directories(${CMAKE_SOURCE_DIR} ${ROOT_INCLUDE_DIR} ${ROOT_INCLUDE_DIRS})
include(${ROOT_USE_FILE})
add_definitions(${ROOT_CXX_FLAGS})
include_directories(${CMAKE_SOURCE_DIR} ${ROOT_INCLUDE_DIRS})
set(DICT_FILE_NAME G__${PROJECT_NAME})
set(PCM_FILE_NAME lib${PROJECT_NAME})
ROOT_GENERATE_DICTIONARY(${DICT_FILE_NAME} ${HEADERS} LINKDEF src/CentralityLinkDef.h)
add_library(Centrality SHARED ${SOURCES} ${DICT_FILE_NAME})
target_link_libraries(Centrality ${ROOT_LIBRARIES})
# Create a main program using the library
add_executable(main main.cpp)
target_link_libraries(main Centrality ${ROOT_LIBRARIES})
target_include_directories(main PUBLIC src)
add_executable(glauber glauber/main.cpp)
target_link_libraries(glauber ${ROOT_LIBRARIES} Centrality)
# install(FILES ${HEADERS} DESTINATION include)
# install(TARGETS Centrality DESTINATION lib)
# Packaging routine
# For complete explanation
# @see https://cmake.org/cmake/help/git-master/manual/cmake-packages.7.html#creating-packages
include(GenerateExportHeader)
if (NOT AnalysisTree_FOUND)
message(STATUS "AnalysisTree is not found")
else ()
add_subdirectory(at_interface)
endif ()
generate_export_header(Centrality)
set_property(TARGET Centrality PROPERTY VERSION ${PROJECT_VERSION})
set_property(TARGET Centrality PROPERTY SOVERSION ${PROJECT_VERSION})
set_property(TARGET Centrality PROPERTY INTERFACE_Centrality_MAJOR_VERSION 1)
set_property(TARGET Centrality APPEND PROPERTY COMPATIBLE_INTERFACE_STRING INTERFACE_Centrality_MAJOR_VERSION)
install(TARGETS Centrality EXPORT CentralityTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
add_subdirectory(src)
add_subdirectory(tasks)
install(
FILES
${HEADERS}
"${CMAKE_CURRENT_BINARY_DIR}/centrality_export.h"
DESTINATION
include/centrality
COMPONENT
Devel
)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/${PCM_FILE_NAME}_rdict.pcm"
"${CMAKE_CURRENT_BINARY_DIR}/${PCM_FILE_NAME}.rootmap"
DESTINATION
lib
OPTIONAL
......@@ -100,6 +67,8 @@ write_basic_package_version_file(
export(EXPORT CentralityTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/Centrality/CentralityTargets.cmake")
message(STATUS "CentralityTargets: ${CentralityTargets}")
set(ConfigPackageLocation lib/cmake/Centrality)
set(Centrality_INCLUDE_DIR "include")
......@@ -109,9 +78,6 @@ configure_package_config_file(
CentralityConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/Centrality/CentralityConfig.cmake
INSTALL_DESTINATION ${ConfigPackageLocation}
PATH_VARS Centrality_INCLUDE_DIR Centrality_LIBRARY_DIR
# [NO_SET_AND_CHECK_MACRO]
# [NO_CHECK_REQUIRED_COMPONENTS_MACRO]
# [INSTALL_PREFIX <path>]
)
install(EXPORT CentralityTargets
......
# !!! NEW REPOSITORY
https://github.com/HeavyIonAnalysis/Centrality
# Centrality Framework
## Installation
......
......@@ -4,7 +4,4 @@
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class Glauber::Fitter+;
#pragma link C++ class Centrality::Getter+;
#endif
set(SOURCES
CentralityFiller.cpp
# CentralityTask.cpp
# CentralityTaskTracks.cpp
# CentralityTaskPsd.cpp
)
string(REPLACE ".cpp" ".hpp" HEADERS "${SOURCES}")
set(DICT_FILE_NAME G__ATCentrality)
set(PCM_FILE_NAME libATCentrality)
include_directories(${CMAKE_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR} ${AnalysisTree_INCLUDE_DIR})
add_library(ATCentrality SHARED ${SOURCES} ${DICT_FILE_NAME})
ROOT_GENERATE_DICTIONARY(${DICT_FILE_NAME} ${HEADERS} LINKDEF ATCentralityLinkDef.hpp)
target_link_libraries(ATCentrality Centrality AnalysisTreeBase AnalysisTreeInfra ${ROOT_LIBRARIES})
#install(TARGETS Centrality EXPORT CentralityTargets
# LIBRARY DESTINATION lib
# ARCHIVE DESTINATION lib
# RUNTIME DESTINATION bin
# INCLUDES DESTINATION include
# )
#
#install(
# FILES
# ${HEADERS}
# DESTINATION
# include/Centrality
# COMPONENT
# Devel
#)
#
#install(
# FILES
# "${CMAKE_CURRENT_BINARY_DIR}/${PCM_FILE_NAME}_rdict.pcm"
# DESTINATION
# lib
# OPTIONAL
#)
#
#install(
# FILES
# "${CMAKE_CURRENT_BINARY_DIR}/${PCM_FILE_NAME}.rootmap"
# DESTINATION
# lib
# OPTIONAL
#)
#include "CentralityFiller.hpp"
#include <memory>
#include "TFile.h"
namespace AnalysisTree{
CentralityFiller::CentralityFiller(const std::string& file, const std::string& getter) {
auto centr_file = std::unique_ptr<TFile>(TFile::Open(file.c_str(), "read"));
if((!centr_file) || (centr_file->IsZombie())) {
throw std::runtime_error("No file or file is zombie");
}
getter_ = centr_file->Get<Centrality::Getter>(getter.c_str());
if(getter_ == nullptr) {
throw std::runtime_error("Centrality Getter is nullptr");
}
}
void CentralityFiller::Init() {
auto man = TaskManager::GetInstance();
auto chain = man->GetChain();
input_ = chain->GetBranch(input_name_);
is_event_header_ = input_.GetBranchType() == DetType::kEventHeader;
in_field_ = input_.GetField(input_field_name_);
in_branches_.emplace(input_name_);
auto conf = input_.GetConfig().Clone(output_name_, AnalysisTree::DetType::kEventHeader);
conf.AddField<float>(output_field_name_, "centrality, %");
output_ = Branch(conf);
out_field_ = output_.GetField(output_field_name_);
output_.SetMutable();
output_.Freeze();
input_.Freeze();
man->AddBranch(&output_);
}
void CentralityFiller::Exec() {
if(is_event_header_) {
FillFromEventHeader();
} else {
FillFromChannels();
}
}
void CentralityFiller::FillFromEventHeader() {
const auto value = input_[0][in_field_];
output_[0].CopyContent(input_[0]);
const auto centrality = getter_->GetCentrality(value);
output_[0].SetValue(out_field_, centrality);
}
void CentralityFiller::FillFromChannels() {
const auto n = input_.size();
int m{0};
for(size_t i = 0; i < n; ++i) {
if(!event_cuts_ || event_cuts_->Apply(input_[i])) {
m++;
}
}
const auto centrality = getter_->GetCentrality(m);
output_[0].SetValue(out_field_, centrality);
}
}
\ No newline at end of file
#ifndef CENTRALITY_AT_INTERFACE_CENTRALITYFILLER_HPP_
#define CENTRALITY_AT_INTERFACE_CENTRALITYFILLER_HPP_
#include <utility>
#include "AnalysisTree/Task.hpp"
#include "AnalysisTree/TaskManager.hpp"
#include "Getter.hpp"
namespace AnalysisTree{
class CentralityFiller : public AnalysisTree::Task{
public:
CentralityFiller() = delete;
CentralityFiller(const std::string& file, const std::string& getter);
void Init() override;
void Exec() override;
void Finish() override {
delete getter_;
}
void SetInput(std::string branch, std::string field = "") {
input_name_ = std::move(branch);
input_field_name_ = std::move(field);
}
void SetOutput(std::string branch, std::string field) {
output_name_ = std::move(branch);
output_field_name_ = std::move(field);
}
~CentralityFiller() override = default;
protected:
void FillFromEventHeader();
void FillFromChannels();
std::string input_name_;
std::string input_field_name_;
std::string output_name_;
std::string output_field_name_;
Centrality::Getter* getter_{nullptr};
AnalysisTree::Branch input_;
AnalysisTree::Branch output_;
AnalysisTree::Field in_field_;
AnalysisTree::Field out_field_;
bool is_event_header_{true};
// AnalysisTree::Cuts* cuts_{nullptr};
};
}
#endif //CENTRALITY_AT_INTERFACE_CENTRALITYFILLER_HPP_
# Contribution Guide
# Contribution Guide
https://google.github.io/styleguide/cppguide.html
## Doxygen documentation
Always document your code, e. g. put at least a brief class description
/** @file MyClass.h
......@@ -37,9 +38,11 @@ The selection of name spaces is reflected also in the directory structure for th
## Include Files
In header files only use include which MUST be there. Unnecessary includes increase the compilation time. Most of the time all necessary includes can be moved to the implementation.
In header files only use include which MUST be there. Unnecessary includes increase the compilation time. Most of the
time all necessary includes can be moved to the implementation.
To avoid including header files more than once, use the preprocessor macro _nsp_ClassName_h_ to mark a header as already included. Usage of these inclusion guards is nonnegotiable.
To avoid including header files more than once, use the preprocessor macro _nsp_ClassName_h_ to mark a header as already
included. Usage of these inclusion guards is nonnegotiable.
// file: .../include/nsp/ClassName.h
......@@ -51,34 +54,40 @@ To avoid including header files more than once, use the preprocessor macro _nsp_
#endif
Since with the introduction of namespaces, a class can exist in more than one namespace, we can have header files with the same name to define the same class. We have to add the namespace both to the path for locating the file and to the preprocessor macro preventing multiple inclusion of a header.
Since with the introduction of namespaces, a class can exist in more than one namespace, we can have header files with
the same name to define the same class. We have to add the namespace both to the path for locating the file and to the
preprocessor macro preventing multiple inclusion of a header.
## Pass by const reference
* Complex objects should be passed by reference.
* Complex objects should be passed by reference.
* Don’t use it for simple types (int, float, . . . ), it can be an overhead
* Prefer over pointer: This makes sure you get a valid object
void func(const myClass& c); // good
void func(const myClass* c); // ok, if you know why (needed only in rare cases)
void func(myClass c); // not so good, unless you know why
void func(const myClass& c); // good void func(const myClass* c); // ok, if you know why (needed only in rare cases)
void func(myClass c); // not so good, unless you know why
## Pointers
* Only use pointer if you have a strong reason!
* If you use objects on the stack you don’t have to care about deletion
* If you need pointers, prefer smart pointers over plain pointers
* Only use pointer if you have a strong reason!
* If you use objects on the stack you don’t have to care about deletion
* If you need pointers, prefer smart pointers over plain pointers
## Using namespace statement
Due to the global effect on all code that includes the particular header, using and using namespace statement should never be given in header files. NEVER do that in header:
Due to the global effect on all code that includes the particular header, using and using namespace statement should
never be given in header files. NEVER do that in header:
using namespace std;
This means all files including your header will have the std namespace. You could do it in the implementation, not considered nice style. Prefer importing only single function, only do it in your implementation
This means all files including your header will have the std namespace. You could do it in the implementation, not
considered nice style. Prefer importing only single function, only do it in your implementation
using std::cout;
Furthermore, since using namespace statement has an immediate effect also outside of the file scope, in .cpp files all such statements should come after all includes.
You could also define an alias, this can even be done locally in a function body
Furthermore, since using namespace statement has an immediate effect also outside of the file scope, in .cpp files all
such statements should come after all includes. You could also define an alias, this can even be done locally in a
function body
using cout = std::cout;
......@@ -89,71 +98,92 @@ consider using modern ‘typedef’
## Abbreviations
In general, avoid abbreviations in variable and class names. Here is a list of accepted abbreviations which should not be expanded explicitly:
In general, avoid abbreviations in variable and class names. Here is a list of accepted abbreviations which should not
be expanded explicitly:
* MC: Monte-Carlo
* NBD: Negative Binomial Distribution
* ...
* MC: Monte-Carlo
* NBD: Negative Binomial Distribution
* ...
## Const correctness and constness issues
It is of utmost importance that all classes, functions and methods respect the correct and logical use of const modifier. Methods that do not change class data members should be declared const. Function and method parameters should be declared const if they are not intended to be changed inside of the function body. This is even more true when references are passed through the parameters.
It is of utmost importance that all classes, functions and methods respect the correct and logical use of const
modifier. Methods that do not change class data members should be declared const. Function and method parameters should
be declared const if they are not intended to be changed inside of the function body. This is even more true when
references are passed through the parameters.
In this respect the use of const_cast is strongly discouraged since it can unravel weird compiler bugs.
The rule of a thumb for each programmer should be that first of all a new variable (if possible) is declared not before the value for it is available (i.e. no C-style declarations of variables at the beginning of the code block) and that every new local variable is declared const by default. A forward declaration of a local variable should be used only in special cases when its value will be known only after complex processing (possibly taking place inside of a nested scope).
The rule of a thumb for each programmer should be that first of all a new variable (if possible) is declared not before
the value for it is available (i.e. no C-style declarations of variables at the beginning of the code block) and that
every new local variable is declared const by default. A forward declaration of a local variable should be used only in
special cases when its value will be known only after complex processing (possibly taking place inside of a nested
scope).
## NULL vs. nullptr
Note that NULL is a (macro) remainder from C and should be avoided. nullptr is meant as a replacement to NULL. nullptr provides a typesafe pointer value representing an empty (null) pointer. The general rule of thumb that I recommend is that you should start using nullptr whenever you would have used NULL in the past. Even better: avoid usage of pointers completely. Almost everything can be done with references instead and is more bug-resistant.
Note that NULL is a (macro) remainder from C and should be avoided. nullptr is meant as a replacement to NULL. nullptr
provides a typesafe pointer value representing an empty (null) pointer. The general rule of thumb that I recommend is
that you should start using nullptr whenever you would have used NULL in the past. Even better: avoid usage of pointers
completely. Almost everything can be done with references instead and is more bug-resistant.
## Pointer * and reference & placement
The * and & modifiers are part of the type and there thus they belong:
Core::Track& foo;
## Constructor initializer list
If possible put it directly after member declaration in the header
Double32_t energy_{0}; // track energy in GeV
## Increment, decrement
As default, only pre-increment (++i) and pre-decrement (--i) operators should be used, unless the post-increment/-decrement (i++) feature is explicitly required. The reason is that the post- versions require temporary storage of the previous value of a variable. The compiler will (most probably) optimize such waste away for the built-in types (int etc) but this does not happen for custom code of the various iterators (STL, Offline). The bad habit of placing ++ after the variables can be avoided by forcing yourself to use pre- versions of operators everywhere.
As default, only pre-increment (++i) and pre-decrement (--i) operators should be used, unless the
post-increment/-decrement (i++) feature is explicitly required. The reason is that the post- versions require temporary
storage of the previous value of a variable. The compiler will (most probably) optimize such waste away for the built-in
types (int etc) but this does not happen for custom code of the various iterators (STL, Offline). The bad habit of
placing ++ after the variables can be avoided by forcing yourself to use pre- versions of operators everywhere.
## Forbidden practices
Generally, the C/FORTRAN-hackish style should be avoided. In particular, the following practices are absolutely forbidden.
Generally, the C/FORTRAN-hackish style should be avoided. In particular, the following practices are absolutely
forbidden.
Do not use fixed size C arrays when variable size arrays are needed, such as
// A "probably big enough" fixed size array in a place where variable size array would be needed:
double a[20];
Use STL vector instead, such as
std::vector<double> a(20);
Do not use dynamical C arrays, such as
// Allocate:
double* a = (double*)calloc(30, sizeof(double));
// De-allocate:
free(a);
Use STL vector instead, see previous point.
Do not pass large data to function arguments via pointers, such as
Use STL vector instead, see previous point. Do not pass large data to function arguments via pointers, such as
int function(int a, double* array);
or
int function(int a, double[] array);
Use instead C++ reference:
int function(int a, std::vector<double>& array);
Do not use unnamed constants, such as
std::vector<double> array(23);
Use instead enums so that we know what 23 is:
// Declared somewhere at the beginning:
......
File moved
#include "Fitter.h"
#include "TTree.h"
#include "TCanvas.h"
#include "TF1.h"
#include "TFile.h"
#include "TGraph.h"
#include "TLegend.h"
#include "TMath.h"
#include "TRandom.h"
ClassImp(Glauber::Fitter)
// ----- Default constructor -------------------------------------------
Glauber::Fitter::Fitter(std::unique_ptr<TTree> tree)
{
fSimTree = std::move(tree);
std::cout << fSimTree->GetEntries() << std::endl;
if (!fSimTree) {
std::cout << "SetSimHistos: *** Error - " << std::endl;
exit(EXIT_FAILURE);
}
fSimTree->SetBranchAddress("Npart", &fNpart);
fSimTree->SetBranchAddress("Ncoll", &fNcoll);
}
void Glauber::Fitter::Init(int nEntries)
{
if ( nEntries < 0 || nEntries > fSimTree->GetEntries() ){
std::cout << "Init: *** ERROR - number of entries < 0 or less that number of entries in input tree" << std::endl;
std::cout << "Init: *** number of entries in input tree = " << fSimTree->GetEntries() << std::endl;
exit(EXIT_FAILURE);
}
const int NpartMax = int (fSimTree->GetMaximum("Npart") );
const int NcollMax = int (fSimTree->GetMaximum("Ncoll") );
fNpartHisto = TH1F ("fNpartHisto", "Npart", NpartMax/fBinSize, 0, NpartMax );
fNcollHisto = TH1F ("fNcollHisto", "Ncoll", NcollMax/fBinSize, 0, NcollMax );
for (int i=0; i<nEntries; i++)
{
fSimTree->GetEntry(i);
fNcollHisto.Fill(fNcoll);
fNpartHisto.Fill(fNpart);
}
std::cout << fSimTree->GetEntries() << std::endl;
fNbins = fDataHisto.GetNbinsX();
while ( fDataHisto.GetBinContent(fNbins-1) == 0)
fNbins--;
fNbins++;
const float min = fDataHisto.GetXaxis()->GetXmin();
const float max = fDataHisto.GetXaxis()->GetXmax();
fMaxValue = min + (max - min)*fNbins/fDataHisto.GetNbinsX() ;
std::cout << "fNbins = " << fNbins << std::endl;
std::cout << "fMaxValue = " << fMaxValue << std::endl;
}
float Glauber::Fitter::Nancestors(float f) const
{
if (fMode == "Default") return f*fNpart + (1-f)*fNcoll;
else if (fMode == "PSD") return f - fNpart;
else if (fMode == "Npart") return TMath::Power(fNpart, f);
else if (fMode == "Ncoll") return TMath::Power(fNcoll, f);
return -1.;
}
float Glauber::Fitter::NancestorsMax(float f) const
{
const int NpartMax = fNpartHisto.GetXaxis()->GetXmax() ; // some magic
const int NcollMax = fNcollHisto.GetXaxis()->GetXmax() ; //TODO
if (fMode == "Default") return f*NpartMax + (1-f)*NcollMax;
else if (fMode == "PSD") return NpartMax;
else if (fMode == "Npart") return TMath::Power(NpartMax, f);
else if (fMode == "Ncoll") return TMath::Power(NcollMax, f);
return -1.;
}
/*
* take Glauber MC data from fSimTree
* Populate fGlauberFitHisto with NBD x Na
*/
void Glauber::Fitter::SetGlauberFitHisto (float f, float mu, float k, int n, Bool_t Norm2Data)
{
fGlauberFitHisto = TH1F("glaub", "", fNbins*1.3, 0, 1.3*fMaxValue);
fGlauberFitHisto.SetName(Form("glaub_%4.2f_%6.4f_%4.2f_%d", f, mu, k, n ));
SetNBDhist(mu, k);
std::unique_ptr<TH1F> htemp {(TH1F*)fNbdHisto.Clone("htemp")}; // WTF??? Not working without pointer
for (int i=0; i<n; i++)
{
fSimTree->GetEntry(i);
const int Na = int(Nancestors(f));
float nHits {0.};
for (int j=0; j<Na; j++){
nHits += int(htemp->GetRandom());
}
fGlauberFitHisto.Fill(nHits);
}
if (Norm2Data)
NormalizeGlauberFit();
}
void Glauber::Fitter::NormalizeGlauberFit ()
{
int fGlauberFitHistoInt {0};
int fDataHistoInt {0};
const int lowchibin = fFitMinBin;
const int highchibin = fFitMaxBin<fNbins ? fFitMaxBin : fNbins;
for (int i=lowchibin; i<highchibin; i++)
{
fGlauberFitHistoInt += fGlauberFitHisto.GetBinContent(i+1);
fDataHistoInt += fDataHisto.GetBinContent(i+1);
}
const float ScaleFactor = (float)fDataHistoInt/fGlauberFitHistoInt;
// std::cout << "Scale = " << Scale << std::endl;
fGlauberFitHisto.Scale(ScaleFactor);
}
/**
*
* @param mu mean value of negative binominal distribution (we are looking for it)
* @param chi2 return value (indicates good match)
* @param mu_min lower search edge for mean value NBD
* @param mu_max upper search edge for mean value NBD
* @param f parameter of Na
* @param k NBD parameter
* @param nEvents
* @param nIter
*/
void Glauber::Fitter::FindMuGoldenSection (float *mu, float *chi2, float mu_min, float mu_max, float f, float k, int nEvents, int nIter)
{
const float phi {(1+TMath::Sqrt(5))/2};
/* left */
float mu_1 = mu_max - (mu_max-mu_min)/phi;
/* right */
float mu_2 = mu_min + (mu_max-mu_min)/phi;
SetGlauberFitHisto (f, mu_1, k, nEvents);
float chi2_mu1 = GetChi2 ();
SetGlauberFitHisto (f, mu_2, k, nEvents);
float chi2_mu2 = GetChi2 ();
for (int j=0; j<nIter; j++)
{
if (chi2_mu1 > chi2_mu2)
{
mu_min = mu_1;
mu_1 = mu_2;
mu_2 = mu_min + (mu_max-mu_min)/phi;
chi2_mu1 = chi2_mu2;
SetGlauberFitHisto (f, mu_2, k, nEvents);
chi2_mu2 = GetChi2 ();
}
else
{
mu_max = mu_2;
mu_2 = mu_1;
mu_1 = mu_max - (mu_max-mu_min)/phi;
chi2_mu2 = chi2_mu1;
SetGlauberFitHisto (f, mu_1, k, nEvents);
chi2_mu1 = GetChi2 ();
}
std::cout << "mu1 = " << mu_1 << " mu2 = " << mu_2 << " chi2_mu1 = " << chi2_mu1 << " chi2_mu2 = " << chi2_mu2 << std::endl;
}
/* take min(mu) */
*mu = (chi2_mu1 < chi2_mu2) ? mu_1 : mu_2;
/* take min(chi2) */
*chi2 = (chi2_mu1 < chi2_mu2) ? chi2_mu1 : chi2_mu2;
}
/**
* Find the best match
*
* @param return value of best fit parameters
* @param f0 parameter of Na, for which chi2 will be calculated
* @param k0 lower search edge for NBD parameter
* @param k1 upper search edge for NBD parameter
* @param nEvents
*/
float Glauber::Fitter::FitGlauber (float *par, Float_t f0, Int_t k0, Int_t k1, Int_t nEvents)
{
float f_fit{-1};
float mu_fit{-1};
float k_fit{-1};
float Chi2Min {1e10};
const TString filename = Form ( "%s/fit_%4.2f_%d_%d_%d.root", fOutDirName.Data(), f0, k0, k1, fFitMinBin );
// std::unique_ptr<TFile> file {TFile::Open(filename, "recreate")};
// std::unique_ptr<TTree> tree {new TTree("test_tree", "tree" )};
TFile* file {TFile::Open(filename, "recreate")};
TTree* tree {new TTree("test_tree", "tree" )};
TH1F h1("h1", "", fNbins, 0, fMaxValue);
float f, mu, k, chi2, sigma;
tree->Branch("histo", "TH1F", &h1);
tree->Branch("f", &f, "f/F");
tree->Branch("mu", &mu, "mu/F");
tree->Branch("k", &k, "k/F");
tree->Branch("chi2", &chi2, "chi2/F");
tree->Branch("sigma",&sigma,"sigma/F");
f = f0;
for (int j=k0; j<=k1; j++)
{
mu = fMaxValue / NancestorsMax(f) ;
k = j;
const float mu_min = 0.7*mu;
const float mu_max = 1.0*mu;
FindMuGoldenSection (&mu, &chi2, mu_min, mu_max, f, k, nEvents, 10);
sigma = ( mu/k + 1 ) * mu;
h1 = fGlauberFitHisto;
tree->Fill();
if (chi2 < Chi2Min)
{
f_fit = f;
mu_fit = mu;
k_fit = k;
Chi2Min = chi2;
fBestFitHisto = fGlauberFitHisto;
}
}
tree->Write();
file->Write();
file->Close();
par[0] = f_fit;
par[1] = mu_fit;
par[2] = k_fit;
return Chi2Min;
}
/**
* Compare fGlauberFitHisto with fDataHisto
* @return chi2 value
*/
float Glauber::Fitter::GetChi2 () const
{
float chi2 {0.0};
const int lowchibin = fFitMinBin;
const int highchibin = fFitMaxBin<fNbins ? fFitMaxBin : fNbins;
for (int i=lowchibin; i<=highchibin; ++i)
{
if (fDataHisto.GetBinContent(i) < 1.0) continue;
const float error2 = TMath::Power(fDataHisto.GetBinError(i), 2) + TMath::Power(fGlauberFitHisto.GetBinError(i), 2);
const float diff2 = TMath::Power((fGlauberFitHisto.GetBinContent(i) - fDataHisto.GetBinContent(i)), 2) / error2;
chi2 += diff2;
}
chi2 = chi2 / (highchibin - lowchibin + 1);
return chi2;
}
/**
* Popuates histogram nbd_<mean>_<k> with values of NBD
* @param mu
* @param k
*/
void Glauber::Fitter::SetNBDhist(float mu, float k)
{
// Interface for TH1F.
const int nBins = (mu+1.)*3 < 10 ? 10 : (mu+1.)*3;
fNbdHisto = TH1F ("fNbdHisto", "", nBins, 0, nBins);
fNbdHisto.SetName(Form("nbd_%f_%f",mu,k));
for (int i=0; i<nBins; ++i)
{
const float val = NBD(i, mu, k);
if (val>1e-10) fNbdHisto.SetBinContent(i+1, val);
// std::cout << "val " << val << std::endl;
}
}
/**
* Negative Binomial Distribution (by definition)
* @param n argument
* @param mu mean
* @param k argument
* @return NBD for a given parameters
*/
float Glauber::Fitter::NBD(float n, float mu, float k) const
{
// Compute NBD.
float F;
float f;
if (n+k > 100.0)
{
// log method for handling large numbers
F = TMath::LnGamma(n + k)- TMath::LnGamma(n + 1.)- TMath::LnGamma(k);
f = n * TMath::Log(mu/k) - (n + k) * TMath::Log(1.0 + mu/k);
F += f;
F = TMath::Exp(F);
}
else
{
F = TMath::Gamma(n + k) / ( TMath::Gamma(n + 1.) * TMath::Gamma(k) );
f = n * TMath::Log(mu/k) - (n + k) * TMath::Log(1.0 + mu/k);
f = TMath::Exp(f);
F *= f;
}
return F;
}
/**
* Creates histo with a given model parameter distribution
* @param range observable range
* @param name name of the MC-Glauber model parameter
* @param par array with fit parameters
* @param Nevents
* @return pointer to the histogram
*/
std::unique_ptr<TH1F> Glauber::Fitter::GetModelHisto (const float range[2], TString name, const float par[3], int nEvents)
{
const float f = par[0];
const float mu = par[1];
const float k = par[2];
float modelpar{-999.};
fSimTree->SetBranchAddress(name, &modelpar);
SetNBDhist(mu, k);
// TRandom random;
// random.SetSeed(mu*k);
std::unique_ptr<TH1F> hModel(new TH1F ("hModel", "name", 100, fSimTree->GetMinimum(name), fSimTree->GetMaximum(name)) );
for (int i=0; i<nEvents; i++)
{
fSimTree->GetEntry(i);
const int Na = int(Nancestors(f));
float nHits{0.};
for (int j=0; j<Na; ++j){
nHits += (int)fNbdHisto.GetRandom();
}
if ( nHits > range[0] && nHits < range[1] ){
hModel->Fill(modelpar);
}
}
return std::move(hModel);
}
/** @file Fitter.h
@class Glauber::Fitter
@author Viktor Klochkov (klochkov44@gmail.com)
@author Ilya Selyuzhenkov (ilya.selyuzhenkov@gmail.com)
@brief Class to fit histo with Glauber based function
*/
#ifndef GlauberFitter_H
#define GlauberFitter_H 1
#include <vector>
#include "TString.h"
#include "TNamed.h"
#include "TH1F.h"
#include "TTree.h"
// #include "TMinuit.h"
namespace Glauber
{
class Fitter
{
public:
/** Default constructor **/
Fitter() {};
Fitter(std::unique_ptr<TTree> tree) ;
/** Destructor **/
virtual ~Fitter(){};
void Init(int nEntries);
void SetGlauberFitHisto (Float_t f, Float_t mu, Float_t k, Int_t n = 10000, Bool_t Norm2Data = true);
void NormalizeGlauberFit ();
void DrawHistos (Bool_t isSim = true, Bool_t isData = true, Bool_t isGlauber = false, Bool_t isNBD = false);
float FitGlauber (float *par, Float_t f0, Int_t k0, Int_t k1, Int_t nEvents);
void FindMuGoldenSection (Float_t *mu, Float_t *chi2, Float_t mu_min, Float_t mu_max, Float_t f, Float_t k, Int_t nEvents = 10000, Int_t nIter = 5);
Float_t GetChi2 (void) const;
Float_t NBD(Float_t n, Float_t mu, Float_t k) const;
void SetNBDhist(Float_t mu, Float_t k);
float Nancestors(float f) const;
float NancestorsMax(float f) const;
std::unique_ptr<TH1F> GetModelHisto (const Float_t range[2], TString name, const Float_t par[3], Int_t nEvents);
//
// Setters
//
void SetInputHisto (const TH1F &h) { fDataHisto = h; }
void SetFitMinBin (Int_t min) { fFitMinBin = min; }
void SetFitMaxBin (Int_t min) { fFitMaxBin = min; }
void SetNormMinBin (Int_t min) { fNormMinBin = min; }
void SetBinSize (Int_t size) { fBinSize = size; }
void SetOutDirName (TString name) { fOutDirName = name; }
void SetMode (const TString mode) { fMode = mode; }
//
// Getters
//
TH1F GetGlauberFitHisto () const { return fGlauberFitHisto; }
TH1F GetDataHisto () const { return fDataHisto; }
TH1F GetNBDHisto () const { return fNbdHisto; }
TH1F GetNpartHisto () const { return fNpartHisto; }
TH1F GetNcollHisto () const { return fNcollHisto; }
TH1F GetBestFiHisto () const { return fBestFitHisto; }
private:
/** Data members **/
TH1F fNpartHisto;
TH1F fNcollHisto;
TH1F fDataHisto;
TH1F fNbdHisto;
TH1F fGlauberFitHisto;
TH1F fBestFitHisto;
/* MC data */
std::unique_ptr<TTree> fSimTree{nullptr};
Float_t fNpart{-1.};
Float_t fNcoll{-1.};
Float_t fMaxValue{-1.};
Int_t fNbins{-1};
Int_t fBinSize{-1};
Int_t fFitMinBin{-1};
Int_t fFitMaxBin{-1};
Int_t fNormMinBin{-1};
TString fMode{"Default"};
TString fOutDirName{""};
ClassDef(Fitter, 2);
};
}
#endif
#include "FitterHelper.h"