PeterParfenov лет назад: 2
Сommit
ac871b10de

+ 6 - 0
.vscode/settings.json

@@ -0,0 +1,6 @@
+{
+  "files.associations": {
+    "*.C": "cpp",
+    "iostream": "cpp"
+  }
+}

+ 161 - 0
CMakeLists.txt

@@ -0,0 +1,161 @@
+# CMakeLists.txt for FAS package. It creates a library with dictionary and a main program
+cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
+project(ModelConverter)
+
+# You need to tell CMake where to find the ROOT installation. This can be done
+# in a number of ways:
+#   - ROOT built with classic configure/make use the provided
+#   $ROOTSYS/etc/cmake/FindROOT.cmake
+#   - ROOT built with CMake. Add in CMAKE_PREFIX_PATH the installation prefix
+#   for ROOT
+
+find_package(Git)
+
+list(APPEND CMAKE_PREFIX_PATH $ENV{ROOTSYS})
+
+#---Locate the ROOT package and defines a number of variables (e.g. ROOT_INCLUDE_DIRS)
+find_package(ROOT REQUIRED COMPONENTS MathCore RIO Hist Tree Net EG)
+
+#---Define useful ROOT functions and macros (e.g. ROOT_GENERATE_DICTIONARY)
+include(${ROOT_USE_FILE})
+
+add_definitions(${ROOT_CXX_FLAGS})
+
+#---Locate MCINI package
+find_library(MCINI NAMES McIniData PATHS $ENV{MCINI}/build)
+IF(MCINI)
+  message(STATUS "mcini is found: ${MCINI}")
+  add_definitions("-D_MCINI_")
+endif()
+IF(NOT MCINI)
+  message(STATUS "mcini is not found. Building without it.")
+endif()
+
+#---Locate PHQMDEvent library
+find_library(PHQMD NAMES PHQMDEvent PATHS $ENV{PHQMD_PATH}/phqmd2root/lib/)
+if(PHQMD)
+  message(STATUS "libPHQMDEvent is found: ${PHQMD}")
+  add_definitions("-D_PHQMD_")
+  add_definitions("-D_HSD_ROOT_")
+endif()
+if(NOT PHQMD)
+  message(STATUS "libPHQMDEvent is not found. Building without it.")
+endif()
+
+set(CMAKE_BUILD_TYPE Debug)
+#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -Wall -pthread")
+# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall -ffast-math")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall")
+
+set(MCONVERTER_INCLUDE_DIRECTORIES
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  ${CMAKE_CURRENT_SOURCE_DIR}/bin
+  ${CMAKE_CURRENT_SOURCE_DIR}/format
+  ${CMAKE_CURRENT_SOURCE_DIR}/readers
+  ${CMAKE_CURRENT_SOURCE_DIR}/writers
+  ${CMAKE_CURRENT_SOURCE_DIR}/utility
+  ${ROOT_INLCUDE_DIRS}
+)
+
+set(MCONVERTER_INCLUDE_LIBRARIES
+  ${ROOT_LIBRARIES}
+)
+
+set(MCONVERTER_LIBRARY_h_files
+  ${CMAKE_CURRENT_SOURCE_DIR}/format/mciParticle.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/format/mciEvent.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_smash_root.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_mcpico.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_manager.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/writers/mciWriter_mcpico.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/writers/mciWriter_manager.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/utility/Utility.h
+)
+
+set(MCONVERTER_LIBRARY_cxx_files
+  ${CMAKE_CURRENT_SOURCE_DIR}/format/mciParticle.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/format/mciEvent.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_smash_root.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_mcpico.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_manager.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/writers/mciWriter_mcpico.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/writers/mciWriter_manager.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/utility/Utility.cxx
+)
+
+if(MCINI)
+  list(APPEND MCONVERTER_INCLUDE_DIRECTORIES $ENV{MCINI}/include)
+  list(APPEND MCONVERTER_INCLUDE_LIBRARIES ${MCINI})
+  list(APPEND MCONVERTER_LIBRARY_h_files ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_mcini.h)
+  list(APPEND MCONVERTER_LIBRARY_cxx_files ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_mcini.cxx)
+endif()
+
+if(PHQMD)
+  list(APPEND MCONVERTER_INCLUDE_DIRECTORIES $ENV{PHQMD_PATH})
+  list(APPEND MCONVERTER_INCLUDE_LIBRARIES ${PHQMD})
+  list(APPEND MCONVERTER_LIBRARY_h_files ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_phqmd.h)
+  list(APPEND MCONVERTER_LIBRARY_cxx_files ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_phqmd.cxx)
+  list(APPEND MCONVERTER_LIBRARY_h_files ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_hsd_root.h)
+  list(APPEND MCONVERTER_LIBRARY_cxx_files ${CMAKE_CURRENT_SOURCE_DIR}/readers/mciReader_hsd_root.cxx)
+endif()
+
+include_directories(${MCONVERTER_INCLUDE_DIRECTORIES})
+
+set(MCONVERTER_LinkDef
+  ${CMAKE_CURRENT_SOURCE_DIR}/mConverter.LinkDef.h
+)
+
+#---Generate dictionary
+ROOT_GENERATE_DICTIONARY(G__mConverter
+  ${MCONVERTER_LIBRARY_h_files}
+  LINKDEF ${MCONVERTER_LinkDef}
+)
+
+#---Compile library
+add_library(mConverter SHARED ${MCONVERTER_LIBRARY_cxx_files} G__mConverter.cxx)
+target_link_libraries(mConverter ${MCONVERTER_INCLUDE_LIBRARIES})
+
+# Get the current working branch
+execute_process(
+  COMMAND git rev-parse --abbrev-ref HEAD
+  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+  OUTPUT_VARIABLE GIT_BRANCH
+  RESULT_VARIABLE GIT_BRANCH_ERROR_CODE
+  OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+if( GIT_BRANCH_ERROR_CODE )
+  set(GIT_BRANCH 0)
+endif()
+
+# Get the latest abbreviated commit hash of the working branch
+execute_process(
+  COMMAND git rev-parse --short HEAD
+  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+  OUTPUT_VARIABLE GIT_COMMIT_HASH
+  RESULT_VARIABLE GIT_COMMIT_HASH_ERROR_CODE
+  OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+if( GIT_COMMIT_HASH_ERROR_CODE )
+  set(GIT_COMMIT_HASH 0)
+endif()
+
+# Get the current version
+execute_process(
+  COMMAND git describe --tags --match "*"
+  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+  OUTPUT_VARIABLE GIT_TAG_VERSION
+  RESULT_VARIABLE GIT_TAG_VERSION_ERROR_CODE
+  OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+if( GIT_TAG_VERSION_ERROR_CODE )
+  set(GIT_TAG_VERSION 0.0)
+endif()
+
+set_target_properties (mConverter 
+  PROPERTIES 
+  VERSION ${GIT_TAG_VERSION} SOVERSION ${GIT_BRANCH}-${GIT_COMMIT_HASH}
+)
+
+#---Compile main executable
+add_executable(ModelConverter "${CMAKE_CURRENT_SOURCE_DIR}/bin/main.cpp")
+target_link_libraries(ModelConverter mConverter)

+ 211 - 0
bin/main.cpp

@@ -0,0 +1,211 @@
+#include <iostream>
+#include <vector>
+
+#include <TString.h>
+#include <TFile.h>
+#include <TStopwatch.h>
+
+#include <mciParticle.h>
+#include <mciEvent.h>
+#include <mciReader_manager.h>
+#include <mciReader_smash_root.h>
+#include <mciReader_mcpico.h>
+#include <mciWriter_manager.h>
+#include <mciWriter_mcpico.h>
+#include <Utility.h>
+
+#ifdef _MCINI_
+#include <mciReader_mcini.h>
+#endif
+#ifdef _PHQMD_
+#include <mciReader_phqmd.h>
+#endif
+#ifdef _HSD_ROOT_
+#include <mciReader_hsd_root.h>
+#endif
+
+int main(int argc, char **argv)
+{
+  TString iFileName, oFileName;
+  
+  if (argc < 9)
+  {
+    std::cerr << "./ModelConverter -i input.list -o output.root -input-format [FORMAT] -output-format [FORMAT] [OPTIONAL: -debug]" << std::endl;
+    std::cerr << "Available input formats:" << std::endl;
+    std::cerr << "\tmcpico   - simple custom ROOT format to store model data." << std::endl;
+    std::cerr << "\tparticle - ROOT format that is used by the SMASH model." << std::endl;
+  #ifdef _MCINI_
+    std::cerr << "\tmcini    - custom ROOT format to store both initial state and final state (UniGen data format) model data. Fully compatible with UniGen format." << std::endl;
+  #endif
+  #ifdef _PHQMD_
+    std::cerr << "\tphqmd    - custom ROOT format to store PHQMD (with MST) model data." << std::endl;
+  #endif
+  #ifdef _HSD_ROOT_
+    std::cerr << "\thsd      - custom ROOT format to store HSD model data." << std::endl;
+  #endif
+  std::cerr << "Available output formats:" << std::endl;
+    std::cerr << "\tmcpico   - simple custom ROOT format to store model data." << std::endl;
+    return 1;
+  }
+  for (int i = 1; i < argc; i++)
+  {
+    if (std::string(argv[i]) != "-i" &&
+        std::string(argv[i]) != "-o" &&
+        std::string(argv[i]) != "-input-format" &&
+        std::string(argv[i]) != "-output-format" &&
+        std::string(argv[i]) != "-debug")
+    {
+      std::cerr << "\n[ERROR]: Unknown parameter " << i << ": " << argv[i] << std::endl;
+      return 2;
+    }
+    else
+    {
+      if (std::string(argv[i]) == "-i" && i != argc - 1)
+      {
+        iFileName = argv[++i];
+        continue;
+      }
+      if (std::string(argv[i]) == "-i" && i == argc - 1)
+      {
+        std::cerr << "\n[ERROR]: Input file name was not specified " << std::endl;
+        return 1;
+      }
+      if (std::string(argv[i]) == "-o" && i != argc - 1)
+      {
+        oFileName = argv[++i];
+        continue;
+      }
+      if (std::string(argv[i]) == "-o" && i == argc - 1)
+      {
+        std::cerr << "\n[ERROR]: Output file name was not specified " << std::endl;
+        return 1;
+      }
+      if (std::string(argv[i]) == "-input-format" && i != argc - 1)
+      {
+        mciUtility::GetInstance()->input_format = argv[++i];
+        continue;
+      }
+      if (std::string(argv[i]) == "-input-format" && i == argc - 1)
+      {
+        std::cerr << "\n[ERROR]: Output file name was not specified " << std::endl;
+        return 1;
+      }
+      if (std::string(argv[i]) == "-output-format" && i != argc - 1)
+      {
+        mciUtility::GetInstance()->output_format = argv[++i];
+        continue;
+      }
+      if (std::string(argv[i]) == "-output-format" && i == argc - 1)
+      {
+        std::cerr << "\n[ERROR]: Output file name was not specified " << std::endl;
+        return 1;
+      }
+      if (std::string(argv[i]) == "-debug" && i != argc - 1)
+      {
+        mciUtility::GetInstance()->debug = 1;
+        continue;
+      }
+    }
+  }
+
+  TStopwatch timer;
+  timer.Start();
+  
+  if (mciUtility::GetInstance()->debug)
+  {
+    std::cout << "Input format = " << mciUtility::GetInstance()->input_format << std::endl;
+    std::cout << "Output format = " << mciUtility::GetInstance()->output_format << std::endl;
+    std::cout << "debug = " << mciUtility::GetInstance()->debug << std::endl;
+    std::cout << "Nevents = " << mciUtility::GetInstance()->Nevents << std::endl;
+    std::cout << std::endl;
+  }
+
+  mciReader_manager *readerManager = nullptr;
+  if (mciUtility::GetInstance()->input_format == "mcpico")
+  {
+    readerManager = new mciReader_mcpico();
+  }
+#ifdef _MCINI_
+  if (mciUtility::GetInstance()->input_format == "mcini")
+  {
+    readerManager = new mciReader_mcini();
+  }
+#endif
+#ifdef _PHQMD_
+  if (mciUtility::GetInstance()->input_format == "phqmd")
+  {
+    readerManager = new mciReader_phqmd();
+  }
+#endif
+#ifdef _HSD_ROOT_
+  if (mciUtility::GetInstance()->input_format == "hsd")
+  {
+    readerManager = new mciReader_hsd_root();
+  }
+#endif
+  if (mciUtility::GetInstance()->input_format == "particles")
+  {
+    readerManager = new mciReader_smash_root();
+  }
+
+  if (!readerManager)
+  {
+    std::cerr << "This input format is not found!" << std::endl;
+    return 20;
+  }
+
+  readerManager->SetChain(iFileName.Data());
+
+  Long64_t Nentries_chain = readerManager->GetEntries();
+  Long64_t Nentries = (mciUtility::GetInstance()->Nevents > Nentries_chain) ? Nentries_chain : mciUtility::GetInstance()->Nevents;
+  if (mciUtility::GetInstance()->Nevents == -1)
+    Nentries = Nentries_chain;
+  Int_t Nparticles;
+
+  mciWriter_manager *writerManager = nullptr;
+  if (mciUtility::GetInstance()->output_format == "mcpico")
+  {
+    writerManager = new mciWriter_mcpico();
+  }
+  if (!writerManager)
+  {
+    std::cerr << "This output format is not found!" << std::endl;
+    return 30;
+  }
+
+  writerManager->SetFile(oFileName.Data());
+
+  mciEvent *event = nullptr;
+  mciParticle *particle = nullptr;
+
+  for (Long64_t ievent=0; ievent<Nentries; ievent++)
+  {
+    if (ievent % 1000 == 0)
+      std::cout << "Event [" << ievent << "/" << Nentries << "]" << std::endl;
+    
+    event = (mciEvent *)readerManager->ReadEvent(ievent);
+    if (!event) continue;
+
+    writerManager->SetEvent(event);
+
+    Nparticles = event->GetNparticles();
+    for (int iparticle = 0; iparticle < Nparticles; iparticle++)
+    {
+      particle = readerManager->ReadParticle(iparticle);
+      if (!particle) continue;
+
+      writerManager->SetParticle(particle, iparticle);
+    }
+
+    writerManager->Fill();
+  }
+
+  writerManager->Write();
+  writerManager->Close();
+
+  timer.Stop();
+  timer.Print();
+
+  return 0;
+
+}

+ 11 - 0
format/mciEvent.cxx

@@ -0,0 +1,11 @@
+#include <mciEvent.h>
+
+ClassImp(mciEvent);
+
+mciEvent::mciEvent(/* args */)
+{
+}
+
+mciEvent::~mciEvent()
+{
+}

+ 33 - 0
format/mciEvent.h

@@ -0,0 +1,33 @@
+#ifndef MODELCONVERTER_FORMAT_EVENT_H
+#define MODELCONVERTER_FORMAT_EVENT_H
+
+#include <iostream>
+#include <vector>
+
+#include <Rtypes.h>
+
+class mciEvent
+{
+private:
+  Float_t fB;
+  Float_t fPhiRP;
+  Int_t fNparticles;
+
+public:
+  mciEvent(/* args */);
+  virtual ~mciEvent();
+
+  // Setters
+  virtual void SetB(Float_t _a) { fB = _a; }
+  virtual void SetPhiRP(Float_t _a) { fPhiRP = _a; }
+  virtual void SetNparticles(Float_t _a) { fNparticles = _a; }
+
+  // Getters
+  virtual Float_t GetB() const { return fB; }
+  virtual Float_t GetPhiRP() const { return fPhiRP; }
+  virtual Int_t GetNparticles() const { return fNparticles; }
+
+  ClassDef(mciEvent, 0);
+};
+
+#endif

+ 11 - 0
format/mciParticle.cxx

@@ -0,0 +1,11 @@
+#include <mciParticle.h>
+
+ClassImp(mciParticle);
+
+mciParticle::mciParticle(/* args */)
+{
+}
+
+mciParticle::~mciParticle()
+{
+}

+ 58 - 0
format/mciParticle.h

@@ -0,0 +1,58 @@
+#ifndef MODELCONVERTER_FORMAT_PARTICLE_H
+#define MODELCONVERTER_FORMAT_PARTICLE_H
+
+#include <iostream>
+
+#include <Rtypes.h>
+#include <TVector3.h>
+
+class mciParticle
+{
+private:
+  TVector3 fMom;
+  TVector3 fR;
+  Float_t fEn;
+  Float_t fT;
+  Int_t fPdg;
+  Int_t fCharge;
+
+public:
+  mciParticle(/* args */);
+  virtual ~mciParticle();
+
+  // Setters
+  virtual void SetPxPyPz(Float_t _px, Float_t _py, Float_t _pz) { fMom.SetXYZ(_px, _py, _pz); }
+  virtual void SetXYZ(Float_t _x, Float_t _y, Float_t _z) { fR.SetXYZ(_x, _y, _z); }
+  virtual void SetPx(Float_t _a) { fMom.SetX(_a); }
+  virtual void SetPy(Float_t _a) { fMom.SetY(_a); }
+  virtual void SetPz(Float_t _a) { fMom.SetZ(_a); }
+  virtual void SetX(Float_t _a) { fR.SetX(_a); }
+  virtual void SetY(Float_t _a) { fR.SetY(_a); }
+  virtual void SetZ(Float_t _a) { fR.SetZ(_a); }
+  virtual void SetPdg(Int_t _a) { fPdg = _a; }
+  virtual void SetEnergy(Float_t _a) { fEn = _a; }
+  virtual void SetTime(Float_t _a) { fT = _a; }
+  virtual void SetCharge(Int_t _a) { fCharge = _a; }
+
+  // Getters
+  virtual TVector3 GetMom() { return fMom; }
+  virtual TVector3 GetR() { return fR; }
+  virtual Float_t GetPx() { return fMom.X(); }
+  virtual Float_t GetPy() { return fMom.Y(); }
+  virtual Float_t GetPz() { return fMom.Z(); }
+  virtual Float_t GetPt() { return fMom.Perp(); }
+  virtual Float_t GetP() { return fMom.Mag(); }
+  virtual Float_t GetEta() { return fMom.Eta(); }
+  virtual Float_t GetPhi() { return fMom.Phi(); }
+  virtual Float_t GetT() { return fT; }
+  virtual Float_t GetX() { return fR.X(); }
+  virtual Float_t GetY() { return fR.Y(); }
+  virtual Float_t GetZ() { return fR.Z(); }
+  virtual Int_t GetPdg() const { return fPdg; }
+  virtual Float_t GetEnergy() const { return fEn; }
+  virtual Int_t GetCharge() const { return fCharge; }
+
+  ClassDef(mciParticle, 0);
+};
+
+#endif

+ 29 - 0
mConverter.LinkDef.h

@@ -0,0 +1,29 @@
+#ifdef __CINT__
+
+#pragma link off all global;
+#pragma link off all classes;
+#pragma link off all functions;
+//#pragma link off all extern;
+
+#pragma link C++ nestedclass;
+#pragma link C++ nestedtypedef;
+
+#pragma link C++ class mciParticle+;
+#pragma link C++ class mciEvent+;
+#pragma link C++ class mciReader_smash_root+;
+#pragma link C++ class mciReader_mcpico+;
+#pragma link C++ class mciWriter_mcpico+;
+#ifdef _MCINI_
+#pragma link C++ class mciReader_mcini+;
+#endif
+#ifdef _PHQMD_
+#pragma link C++ class mciReader_phqmd+;
+#endif
+#ifdef _HSD_ROOT_
+#pragma link C++ class mciReader_hsd_root+;
+#endif
+#pragma link C++ class mciReader_manager+;
+#pragma link C++ class mciWriter_manager+;
+#pragma link C++ class mciUtility+;
+
+#endif

+ 136 - 0
readers/mciReader_hsd_root.cxx

@@ -0,0 +1,136 @@
+#include <mciReader_hsd_root.h>
+
+ClassImp(mciReader_hsd_root);
+
+mciReader_hsd_root::mciReader_hsd_root(/* args */) : is_init(false), fCurrentEvent(-1), fEvent(nullptr), fParticle(nullptr)
+{
+}
+
+mciReader_hsd_root::~mciReader_hsd_root()
+{
+}
+
+Bool_t mciReader_hsd_root::ChainCheck()
+{
+  if (!is_init)
+  {
+    return false;
+  }
+
+  if (fCurrentEvent == -1)
+  {
+    return false;
+  }
+
+  if (!fChainPHSD->GetEntry(fCurrentEvent))
+  {
+    return false;
+  }
+  if (!fChainFrag->GetEntry(fCurrentEvent))
+  {
+    return false;
+  }
+
+  return true;
+}
+
+void mciReader_hsd_root::SetChain(const TString &inputFileName)
+{
+  fChainPHSD = (TChain *)mciUtility::GetInstance()->initChain(inputFileName, fChainPHSDName);
+
+  fChainPHSD->SetBranchAddress("event", &fEvent);
+
+  fChainFrag = (TChain *)mciUtility::GetInstance()->initChain(inputFileName, fChainFragName);
+
+  fChainFrag->SetBranchAddress("eventFrag", &fEventFrag);
+
+  is_init = kTRUE;
+}
+
+mciEvent *mciReader_hsd_root::ReadEvent(Long64_t iev)
+{
+  fCurrentEvent = iev;
+
+  if (!ChainCheck())
+  {
+    return nullptr;
+  }
+
+  mciEvent *event = new mciEvent();
+
+  event->SetB(fEvent->GetB());
+  event->SetPhiRP(0.); // in PHQMD axis orientation is rotated by 180 deg. In HSD/PHSD it's ok.
+  //event->SetPhiRP(TMath::Pi()); // in PHQMD axis orientation is rotated by 180 deg. In HSD/PHSD it's ok.
+  event->SetNparticles(fEvent->GetNpart() + fEventFrag->GetNfragMST()); // number of particles from PHSD and number of MST fragments
+
+  return event;
+}
+
+mciParticle *mciReader_hsd_root::ReadParticle(Int_t ipart)
+{
+  if (!ChainCheck())
+  {
+    return nullptr;
+  }
+
+  if (ipart >= fEvent->GetNpart() + fEventFrag->GetNfragMST())
+  {
+    return nullptr;
+  }
+
+  if (ipart < 0)
+  {
+    return nullptr;
+  }
+
+  bool is_particle = false;
+  bool is_fragment = false;
+
+  if (ipart < fEvent->GetNpart())
+  {
+    is_particle = true;
+  }
+  if (ipart >= fEvent->GetNpart())
+  {
+    is_fragment = true;
+  }
+
+  if (!is_particle && !is_fragment)
+  {
+    return nullptr;
+  }
+
+  if (is_particle && is_fragment)
+  {
+    return nullptr;
+  }
+
+  mciParticle *particle = new mciParticle();
+
+  if (is_particle)
+  {
+    fParticle = fEvent->GetParticle(ipart);
+    if (fParticle->IsInMST()) // Check whether the particle from PHSD was used to create MST fragment
+    {
+      return nullptr;
+    }
+    particle->SetEnergy(fParticle->E());
+    particle->SetPdg(fParticle->GetPdg());
+    particle->SetPxPyPz(fParticle->Px(), fParticle->Py(), fParticle->Pz());
+    particle->SetTime(0.);
+    particle->SetXYZ(0., 0., 0.);
+    particle->SetCharge(fParticle->GetCharge());
+  }
+  if (is_fragment)
+  {
+    fFragmentMST = fEventFrag->GetFragmentMST(ipart - fEvent->GetNpart());
+    particle->SetEnergy(fFragmentMST->E());
+    particle->SetPdg(fFragmentMST->GetPdg());
+    particle->SetPxPyPz(fFragmentMST->Px(), fFragmentMST->Py(), fFragmentMST->Pz());
+    particle->SetTime(0.);
+    particle->SetXYZ(0., 0., 0.);
+    particle->SetCharge(fFragmentMST->GetZ());
+  }
+
+  return particle;
+}

+ 48 - 0
readers/mciReader_hsd_root.h

@@ -0,0 +1,48 @@
+#ifndef MODELCONVERTER_READERS_HSD_ROOT_H
+#define MODELCONVERTER_READERS_HSD_ROOT_H
+
+#include <Rtypes.h>
+#include <TChain.h>
+#include <TLorentzVector.h>
+
+#include <qaEvent.h>
+#include <qaParticle.h>
+#include <Utility.h>
+
+#include <mciReader_manager.h>
+
+#include <phqmd2root/src/libPHQMDEvent.h>
+
+class mciReader_hsd_root : virtual public mciReader_manager
+{
+private:
+  TChain *fChainPHSD, *fChainFrag;
+
+  const char *fChainPHSDName = "PHQMDtree";
+  const char *fChainFragName = "FRAGtree";
+
+  bool is_init;
+  Long64_t fCurrentEvent;
+
+  Event *fEvent;
+  EventClust *fEventFrag;
+  Particle *fParticle;
+  Baryon *fBaryonMST;
+  Fragment *fFragmentMST;
+  TLorentzVector fMomentum;
+
+  Bool_t ChainCheck();
+
+public:
+  mciReader_hsd_root(/* args */);
+  virtual ~mciReader_hsd_root();
+
+  virtual void SetChain(const TString &inputFileName);
+  virtual Long64_t GetEntries() { return fChainFrag->GetEntries(); }
+  virtual mciEvent *ReadEvent(Long64_t iev);
+  virtual mciParticle* ReadParticle(Int_t ipart);
+
+  ClassDef(mciReader_hsd_root, 0);
+};
+
+#endif

+ 7 - 0
readers/mciReader_manager.cxx

@@ -0,0 +1,7 @@
+#include <mciReader_manager.h>
+
+ClassImp(mciReader_manager);
+
+mciReader_manager::~mciReader_manager()
+{
+}

+ 26 - 0
readers/mciReader_manager.h

@@ -0,0 +1,26 @@
+#ifndef MODELCONVERTER_READERS_MANAGER_H
+#define MODELCONVERTER_READERS_MANAGER_H
+
+#include <Rtypes.h>
+#include <TString.h>
+
+#include <mciEvent.h>
+#include <mciParticle.h>
+#include <Utility.h>
+
+class mciReader_manager
+{
+private:
+  /* data */
+public:
+  virtual ~mciReader_manager();
+
+  virtual void SetChain(const TString &inputFileName) = 0;
+  virtual Long64_t GetEntries() = 0;
+  virtual mciEvent *ReadEvent(Long64_t iev) = 0;
+  virtual mciParticle* ReadParticle(Int_t ipart) = 0;
+
+  ClassDef(mciReader_manager,0);
+};
+
+#endif

+ 85 - 0
readers/mciReader_mcini.cxx

@@ -0,0 +1,85 @@
+#include <mciReader_mcini.h>
+
+ClassImp(mciReader_mcini);
+
+mciReader_mcini::mciReader_mcini(/* args */) : is_init(false), fCurrentEvent(-1), fEvent(nullptr), fParticle(nullptr)
+{
+}
+
+mciReader_mcini::~mciReader_mcini()
+{
+}
+
+Bool_t mciReader_mcini::ChainCheck()
+{
+  if (!is_init)
+  {
+    return false;
+  }
+
+  if (fCurrentEvent == -1)
+  {
+    return false;
+  }
+
+  if (!fChain->GetEntry(fCurrentEvent))
+  {
+    return false;
+  }
+
+  return true;
+}
+
+void mciReader_mcini::SetChain(const TString &inputFileName)
+{
+  fChain = (TChain *)mciUtility::GetInstance()->initChain(inputFileName, fChainName);
+
+  fChain->SetBranchAddress("event", &fEvent);
+
+  is_init = kTRUE;
+}
+
+mciEvent *mciReader_mcini::ReadEvent(Long64_t iev)
+{
+  fCurrentEvent = iev;
+
+  if (!ChainCheck())
+  {
+    return nullptr;
+  }
+
+  mciEvent *event = new mciEvent();
+
+  event->SetB(fEvent->GetB());
+  event->SetPhiRP(fEvent->GetPhi());
+  event->SetNparticles(fEvent->GetNpa());
+
+  return event;
+}
+
+mciParticle *mciReader_mcini::ReadParticle(Int_t ipart)
+{
+  if (!ChainCheck())
+  {
+    return nullptr;
+  }
+
+  if (ipart >= fEvent->GetNpa())
+  {
+    return nullptr;
+  }
+
+  fParticle = fEvent->GetParticle(ipart);
+  fMomentum = fParticle->GetMomentum();
+
+  mciParticle *particle = new mciParticle();
+
+  particle->SetEnergy(fMomentum.E());
+  particle->SetPdg(fParticle->GetPdg());
+  particle->SetPxPyPz(fMomentum.Px(), fMomentum.Py(), fMomentum.Pz());
+  particle->SetTime(0.);
+  particle->SetXYZ(0., 0., 0.);
+  particle->SetCharge(mciUtility::GetInstance()->GetCharge(fParticle->GetPdg()));
+
+  return particle;
+}

+ 47 - 0
readers/mciReader_mcini.h

@@ -0,0 +1,47 @@
+#ifndef MODELCONVERTER_READERS_MCINI_H
+#define MODELCONVERTER_READERS_MCINI_H
+
+#include <Rtypes.h>
+#include <TChain.h>
+#include <TLorentzVector.h>
+
+#include <mciEvent.h>
+#include <mciParticle.h>
+#include <Utility.h>
+
+#include <mciReader_manager.h>
+
+#include <URun.h>
+#include <UEvent.h>
+#include <UParticle.h>
+#include <EventInitialState.h>
+
+class mciReader_mcini : virtual public mciReader_manager
+{
+private:
+  TChain *fChain;
+
+  const char *fChainName = "events";
+
+  bool is_init;
+  Long64_t fCurrentEvent;
+
+  UEvent *fEvent;
+  UParticle *fParticle;
+  TLorentzVector fMomentum;
+
+  Bool_t ChainCheck();
+
+public:
+  mciReader_mcini(/* args */);
+  virtual ~mciReader_mcini();
+
+  virtual void SetChain(const TString &inputFileName);
+  virtual Long64_t GetEntries() { return fChain->GetEntries(); }
+  virtual mciEvent *ReadEvent(Long64_t iev);
+  virtual mciParticle* ReadParticle(Int_t ipart);
+
+  ClassDef(mciReader_mcini, 0);
+};
+
+#endif

+ 95 - 0
readers/mciReader_mcpico.cxx

@@ -0,0 +1,95 @@
+#include <mciReader_mcpico.h>
+
+ClassImp(mciReader_mcpico);
+
+mciReader_mcpico::mciReader_mcpico(/* args */) : is_init(false), fCurrentEvent(-1)
+{
+}
+
+mciReader_mcpico::~mciReader_mcpico()
+{
+}
+
+Bool_t mciReader_mcpico::ChainCheck()
+{
+  if (!is_init)
+  {
+    return false;
+  }
+
+  if (fCurrentEvent == -1)
+  {
+    return false;
+  }
+
+  if (!fChain->GetEntry(fCurrentEvent))
+  {
+    return false;
+  }
+
+  return true;
+}
+
+void mciReader_mcpico::SetChain(const TString &inputFileName)
+{
+  fChain = (TChain *)mciUtility::GetInstance()->initChain(inputFileName, fChainName);
+
+  fChain->SetBranchAddress("bimp", &bimp);
+  fChain->SetBranchAddress("phi2", &phi2);
+  fChain->SetBranchAddress("phi3", &phi3);
+  fChain->SetBranchAddress("ecc2", &ecc2);
+  fChain->SetBranchAddress("ecc3", &ecc3);
+  fChain->SetBranchAddress("npart", &npart);
+  fChain->SetBranchAddress("nh", &nh);
+  fChain->SetBranchAddress("momx", momx);
+  fChain->SetBranchAddress("momy", momy);
+  fChain->SetBranchAddress("momz", momz);
+  fChain->SetBranchAddress("ene", ene);
+  fChain->SetBranchAddress("hid", hid);
+  fChain->SetBranchAddress("pdg", pdg);
+  fChain->SetBranchAddress("charge", charge);
+
+  is_init = kTRUE;
+}
+
+mciEvent *mciReader_mcpico::ReadEvent(Long64_t iev)
+{
+  fCurrentEvent = iev;
+
+  if (!ChainCheck())
+  {
+    return nullptr;
+  }
+
+  mciEvent *event = new mciEvent();
+
+  event->SetB(bimp);
+  event->SetPhiRP(phi2);
+  event->SetNparticles(nh);
+
+  return event;
+}
+
+mciParticle *mciReader_mcpico::ReadParticle(Int_t ipart)
+{
+  if (!ChainCheck())
+  {
+    return nullptr;
+  }
+
+  if (ipart >= nh)
+  {
+    return nullptr;
+  }
+
+  mciParticle *particle = new mciParticle();
+
+  particle->SetEnergy(ene[ipart]);
+  particle->SetPdg(pdg[ipart]);
+  particle->SetPxPyPz(momx[ipart], momy[ipart], momz[ipart]);
+  particle->SetTime(0.);
+  particle->SetXYZ(0., 0., 0.);
+  particle->SetCharge(mciUtility::GetInstance()->GetCharge(pdg[ipart]));
+
+  return particle;
+}

+ 54 - 0
readers/mciReader_mcpico.h

@@ -0,0 +1,54 @@
+#ifndef MODELCONVERTER_READERS_MCPICO_H
+#define MODELCONVERTER_READERS_MCPICO_H
+
+#include <Rtypes.h>
+#include <TChain.h>
+
+#include <mciEvent.h>
+#include <mciParticle.h>
+#include <Utility.h>
+
+#include <mciReader_manager.h>
+
+#define MAX_TRACKS 15000
+
+class mciReader_mcpico : virtual public mciReader_manager
+{
+private:
+  TChain *fChain;
+
+  const char *fChainName = "mctree";
+
+  bool is_init;
+  Long64_t fCurrentEvent;
+
+  Float_t         bimp;
+  Float_t         phi2;
+  Float_t         phi3;
+  Float_t         ecc2;
+  Float_t         ecc3;
+  Int_t           npart;
+  Int_t           nh;
+  Float_t         momx[MAX_TRACKS];   //[nh]
+  Float_t         momy[MAX_TRACKS];   //[nh]
+  Float_t         momz[MAX_TRACKS];   //[nh]
+  Float_t         ene[MAX_TRACKS];   //[nh]
+  Int_t           hid[MAX_TRACKS];   //[nh]
+  Int_t           pdg[MAX_TRACKS];   //[nh]
+  Short_t         charge[MAX_TRACKS];   //[nh]
+
+  Bool_t ChainCheck();
+
+public:
+  mciReader_mcpico(/* args */);
+  virtual ~mciReader_mcpico();
+
+  virtual void SetChain(const TString &inputFileName);
+  virtual Long64_t GetEntries() { return fChain->GetEntries(); }
+  virtual mciEvent *ReadEvent(Long64_t iev);
+  virtual mciParticle* ReadParticle(Int_t ipart);
+
+  ClassDef(mciReader_mcpico, 0);
+};
+
+#endif

+ 136 - 0
readers/mciReader_phqmd.cxx

@@ -0,0 +1,136 @@
+#include <mciReader_phqmd.h>
+
+ClassImp(mciReader_phqmd);
+
+mciReader_phqmd::mciReader_phqmd(/* args */) : is_init(false), fCurrentEvent(-1), fEvent(nullptr), fParticle(nullptr)
+{
+}
+
+mciReader_phqmd::~mciReader_phqmd()
+{
+}
+
+Bool_t mciReader_phqmd::ChainCheck()
+{
+  if (!is_init)
+  {
+    return false;
+  }
+
+  if (fCurrentEvent == -1)
+  {
+    return false;
+  }
+
+  if (!fChainPHSD->GetEntry(fCurrentEvent))
+  {
+    return false;
+  }
+  if (!fChainFrag->GetEntry(fCurrentEvent))
+  {
+    return false;
+  }
+
+  return true;
+}
+
+void mciReader_phqmd::SetChain(const TString &inputFileName)
+{
+  fChainPHSD = (TChain *)mciUtility::GetInstance()->initChain(inputFileName, fChainPHSDName);
+
+  fChainPHSD->SetBranchAddress("event", &fEvent);
+
+  fChainFrag = (TChain *)mciUtility::GetInstance()->initChain(inputFileName, fChainFragName);
+
+  fChainFrag->SetBranchAddress("eventFrag", &fEventFrag);
+
+  is_init = kTRUE;
+}
+
+mciEvent *mciReader_phqmd::ReadEvent(Long64_t iev)
+{
+  fCurrentEvent = iev;
+
+  if (!ChainCheck())
+  {
+    return nullptr;
+  }
+
+  mciEvent *event = new mciEvent();
+
+  event->SetB(fEvent->GetB());
+  // event->SetPhiRP(0.); // in PHQMD axis orientation is rotated by 180 deg. In HSD/PHSD it's ok.
+  event->SetPhiRP(TMath::Pi()); // in PHQMD axis orientation is rotated by 180 deg. In HSD/PHSD it's ok.
+  event->SetNparticles(fEvent->GetNpart() + fEventFrag->GetNfragMST()); // number of particles from PHSD and number of MST fragments
+
+  return event;
+}
+
+mciParticle *mciReader_phqmd::ReadParticle(Int_t ipart)
+{
+  if (!ChainCheck())
+  {
+    return nullptr;
+  }
+
+  if (ipart >= fEvent->GetNpart() + fEventFrag->GetNfragMST())
+  {
+    return nullptr;
+  }
+
+  if (ipart < 0)
+  {
+    return nullptr;
+  }
+
+  bool is_particle = false;
+  bool is_fragment = false;
+
+  if (ipart < fEvent->GetNpart())
+  {
+    is_particle = true;
+  }
+  if (ipart >= fEvent->GetNpart())
+  {
+    is_fragment = true;
+  }
+
+  if (!is_particle && !is_fragment)
+  {
+    return nullptr;
+  }
+
+  if (is_particle && is_fragment)
+  {
+    return nullptr;
+  }
+
+  mciParticle *particle = new mciParticle();
+
+  if (is_particle)
+  {
+    fParticle = fEvent->GetParticle(ipart);
+    if (fParticle->IsInMST()) // Check whether the particle from PHSD was used to create MST fragment
+    {
+      return nullptr;
+    }
+    particle->SetEnergy(fParticle->E());
+    particle->SetPdg(fParticle->GetPdg());
+    particle->SetPxPyPz(fParticle->Px(), fParticle->Py(), fParticle->Pz());
+    particle->SetTime(0.);
+    particle->SetXYZ(0., 0., 0.);
+    particle->SetCharge(fParticle->GetCharge());
+  }
+  if (is_fragment)
+  {
+    fFragmentMST = fEventFrag->GetFragmentMST(ipart - fEvent->GetNpart());
+    particle->SetEnergy(fFragmentMST->E());
+    particle->SetPdg(fFragmentMST->GetPdg());
+    particle->SetPxPyPz(fFragmentMST->Px(), fFragmentMST->Py(), fFragmentMST->Pz());
+    particle->SetTime(0.);
+    particle->SetXYZ(0., 0., 0.);
+    particle->SetCharge(fFragmentMST->GetZ());
+  }
+
+  return particle;
+}

+ 48 - 0
readers/mciReader_phqmd.h

@@ -0,0 +1,48 @@
+#ifndef MODELCONVERTER_READERS_PHQMD_H
+#define MODELCONVERTER_READERS_PHQMD_H
+
+#include <Rtypes.h>
+#include <TChain.h>
+#include <TLorentzVector.h>
+
+#include <mciEvent.h>
+#include <mciParticle.h>
+#include <Utility.h>
+
+#include <mciReader_manager.h>
+
+#include <phqmd2root/src/libPHQMDEvent.h>
+
+class mciReader_phqmd : virtual public mciReader_manager
+{
+private:
+  TChain *fChainPHSD, *fChainFrag;
+
+  const char *fChainPHSDName = "PHQMDtree";
+  const char *fChainFragName = "FRAGtree";
+
+  bool is_init;
+  Long64_t fCurrentEvent;
+
+  Event *fEvent;
+  EventClust *fEventFrag;
+  Particle *fParticle;
+  Baryon *fBaryonMST;
+  Fragment *fFragmentMST;
+  TLorentzVector fMomentum;
+
+  Bool_t ChainCheck();
+
+public:
+  mciReader_phqmd(/* args */);
+  virtual ~mciReader_phqmd();
+
+  virtual void SetChain(const TString &inputFileName);
+  virtual Long64_t GetEntries() { return fChainFrag->GetEntries(); }
+  virtual mciEvent *ReadEvent(Long64_t iev);
+  virtual mciParticle* ReadParticle(Int_t ipart);
+
+  ClassDef(mciReader_phqmd, 0);
+};
+
+#endif

+ 92 - 0
readers/mciReader_smash_root.cxx

@@ -0,0 +1,92 @@
+#include <mciReader_smash_root.h>
+
+ClassImp(mciReader_smash_root);
+
+mciReader_smash_root::mciReader_smash_root(/* args */) : is_init(false), fCurrentEvent(-1)
+{
+}
+
+mciReader_smash_root::~mciReader_smash_root()
+{
+}
+
+Bool_t mciReader_smash_root::ChainCheck()
+{
+  if (!is_init)
+  {
+    return false;
+  }
+
+  if (fCurrentEvent == -1)
+  {
+    return false;
+  }
+
+  if (!fChain->GetEntry(fCurrentEvent))
+  {
+    return false;
+  }
+
+  return true;
+}
+
+void mciReader_smash_root::SetChain(const TString &inputFileName)
+{
+  fChain = (TChain *)mciUtility::GetInstance()->initChain(inputFileName, fChainName);
+
+  fChain->SetBranchAddress("npart", &npart);
+  fChain->SetBranchAddress("impact_b", &impact_b);
+  fChain->SetBranchAddress("pdgcode", pdgcode);
+  fChain->SetBranchAddress("p0", p0);
+  fChain->SetBranchAddress("px", px);
+  fChain->SetBranchAddress("py", py);
+  fChain->SetBranchAddress("pz", pz);
+  fChain->SetBranchAddress("t", t);
+  fChain->SetBranchAddress("x", x);
+  fChain->SetBranchAddress("y", y);
+  fChain->SetBranchAddress("z", z);
+
+  is_init = kTRUE;
+}
+
+mciEvent *mciReader_smash_root::ReadEvent(Long64_t iev)
+{
+  fCurrentEvent = iev;
+
+  if (!ChainCheck())
+  {
+    return nullptr;
+  }
+
+  mciEvent *event = new mciEvent();
+
+  event->SetB(impact_b);
+  event->SetPhiRP(0.);
+  event->SetNparticles(npart);
+
+  return event;
+}
+
+mciParticle *mciReader_smash_root::ReadParticle(Int_t ipart)
+{
+  if (!ChainCheck())
+  {
+    return nullptr;
+  }
+
+  if (ipart >= npart)
+  {
+    return nullptr;
+  }
+
+  mciParticle *particle = new mciParticle();
+
+  particle->SetEnergy(p0[ipart]);
+  particle->SetPdg(pdgcode[ipart]);
+  particle->SetPxPyPz(px[ipart], py[ipart], pz[ipart]);
+  particle->SetTime(t[ipart]);
+  particle->SetXYZ(x[ipart], y[ipart], z[ipart]);
+  particle->SetCharge(mciUtility::GetInstance()->GetCharge(pdgcode[ipart]));
+
+  return particle;
+}

+ 53 - 0
readers/mciReader_smash_root.h

@@ -0,0 +1,53 @@
+#ifndef MODELCONVERTER_READERS_SMASH_ROOT_H
+#define MODELCONVERTER_READERS_SMASH_ROOT_H
+
+#include <Rtypes.h>
+#include <TChain.h>
+
+#include <mciEvent.h>
+#include <mciParticle.h>
+#include <Utility.h>
+
+#include <mciReader_manager.h>
+
+#define MAX_TRACKS 15000
+
+class mciReader_smash_root : virtual public mciReader_manager
+{
+private:
+  TChain *fChain;
+
+  const char *fChainName = "particles";
+
+  bool is_init;
+  Long64_t fCurrentEvent;
+
+  Int_t npart;
+  Double_t impact_b;
+  Int_t ev;
+  Int_t tcounter;
+  Int_t pdgcode[MAX_TRACKS]; //[npart]
+  Double_t p0[MAX_TRACKS];   //[npart]
+  Double_t px[MAX_TRACKS];   //[npart]
+  Double_t py[MAX_TRACKS];   //[npart]
+  Double_t pz[MAX_TRACKS];   //[npart]
+  Double_t t[MAX_TRACKS];    //[npart]
+  Double_t x[MAX_TRACKS];    //[npart]
+  Double_t y[MAX_TRACKS];    //[npart]
+  Double_t z[MAX_TRACKS];    //[npart]
+
+  Bool_t ChainCheck();
+
+public:
+  mciReader_smash_root(/* args */);
+  virtual ~mciReader_smash_root();
+
+  virtual void SetChain(const TString &inputFileName);
+  virtual Long64_t GetEntries() { return fChain->GetEntries(); }
+  virtual mciEvent *ReadEvent(Long64_t iev);
+  virtual mciParticle* ReadParticle(Int_t ipart);
+
+  ClassDef(mciReader_smash_root, 0);
+};
+
+#endif

+ 77 - 0
utility/Utility.cxx

@@ -0,0 +1,77 @@
+#include <Utility.h>
+#include <TDatabasePDG.h>
+#include <TParticlePDG.h>
+
+ClassImp(mciUtility);
+
+mciUtility *mciUtility::fUtility = nullptr;
+;
+
+mciUtility::mciUtility() : Nevents(-1),
+                         debug(0),
+                         input_format("mcpico"),
+                         output_format("mcpico")
+{
+}
+
+mciUtility::~mciUtility()
+{
+}
+
+mciUtility *mciUtility::GetInstance()
+{
+  if (fUtility == nullptr)
+  {
+    fUtility = new mciUtility();
+  }
+  return fUtility;
+}
+
+Bool_t mciUtility::ReadConfig(const TString &configFileName)
+{
+  if (configFileName.Length() == 0)
+  {
+    return false;
+  }
+
+  TEnv env(configFileName);
+
+  Nevents = env.GetValue("Nevents", 0);
+  debug = env.GetValue("debug", 0);
+
+  return true;
+}
+
+TChain *mciUtility::initChain(const TString &inputFileName, const char *chainName)
+{
+  TChain *chain = new TChain(chainName);
+  std::ifstream file(inputFileName.Data());
+  std::string line;
+  while (std::getline(file, line))
+  {
+    chain->Add(line.c_str());
+  }
+
+  return chain;
+}
+
+std::vector<Float_t> mciUtility::ParseVector(std::string _input)
+{
+  std::vector<Float_t> vB;
+
+  std::istringstream iss(_input);
+
+  std::copy(std::istream_iterator<Float_t>(iss),
+            std::istream_iterator<Float_t>(),
+            std::back_inserter(vB));
+
+  return vB;
+}
+
+Double_t mciUtility::GetCharge(Int_t pdg)
+{
+  auto particle = (TParticlePDG *)TDatabasePDG::Instance()->GetParticle(pdg);
+  if (!particle)
+    return error_code;
+  return particle->Charge() / 3.;
+}

+ 52 - 0
utility/Utility.h

@@ -0,0 +1,52 @@
+#ifndef MODELCONVERTER_UTILITY_H
+#define MODELCONVERTER_UTILITY_H
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <algorithm>
+#include <iterator>
+#include <cassert>
+#include <sstream>
+#include <string>
+
+#include <Rtypes.h>
+#include <TString.h>
+#include <TChain.h>
+#include <TEnv.h>
+
+#include <mciEvent.h>
+#include <mciParticle.h>
+
+class mciUtility
+{
+protected:
+  mciUtility();
+  virtual ~mciUtility();
+  static mciUtility *fUtility;
+
+public:
+  mciUtility(mciUtility &other) = delete;
+  void operator=(const mciUtility &) = delete;
+
+  static mciUtility *GetInstance();
+
+  const Double_t error_code = -999.;
+
+  Int_t Nevents;
+  Int_t debug;
+  std::string input_format;
+  std::string output_format;
+
+  Bool_t ReadConfig(const TString &configFileName);
+  TChain *initChain(const TString &inputFileName, const char *chainName);
+
+  std::vector<Float_t> ParseVector(std::string _input);
+  Bool_t initCentrality();
+
+  Double_t GetCharge(Int_t pdg);
+
+  ClassDef(mciUtility, 0);
+}; // class mciUtility
+
+#endif

+ 7 - 0
writers/mciWriter_manager.cxx

@@ -0,0 +1,7 @@
+#include <mciWriter_manager.h>
+
+ClassImp(mciWriter_manager);
+
+mciWriter_manager::~mciWriter_manager()
+{
+}

+ 28 - 0
writers/mciWriter_manager.h

@@ -0,0 +1,28 @@
+#ifndef MODELCONVERTER_WRITER_MANAGER_H
+#define MODELCONVERTER_WRITER_MANAGER_H
+
+#include <Rtypes.h>
+#include <TString.h>
+
+#include <mciEvent.h>
+#include <mciParticle.h>
+#include <Utility.h>
+
+class mciWriter_manager
+{
+private:
+  /* data */
+public:
+  virtual ~mciWriter_manager();
+
+  virtual void SetFile(const TString &outputFileName) = 0;
+  virtual void SetEvent(mciEvent *const& _ievent) = 0;
+  virtual void SetParticle(mciParticle *const& _iparticle, Int_t id) = 0;
+  virtual void Fill() = 0;
+  virtual void Write() = 0;
+  virtual void Close() = 0;
+
+  ClassDef(mciWriter_manager,0);
+};
+
+#endif

+ 71 - 0
writers/mciWriter_mcpico.cxx

@@ -0,0 +1,71 @@
+#include <mciWriter_mcpico.h>
+
+ClassImp(mciWriter_mcpico);
+
+mciWriter_mcpico::mciWriter_mcpico(/* args */) : fOutFile(nullptr)
+{
+  fTree = new TTree(fTreeName, "Hadrons tree from MC RHIC models");
+  fTree->Branch("bimp",&bimp,"bimp/F"); // impact parametr
+  fTree->Branch("phi2",&phi2,"phi2/F"); // phiRP2
+  fTree->Branch("phi3",&phi3,"phi3/F"); // phiRP3
+  fTree->Branch("ecc2",&ecc2,"ecc2/F"); // eccentricity2
+  fTree->Branch("ecc3",&ecc3,"ecc3/F"); // eccentricity3
+  fTree->Branch("npart",&npart,"npart/I"); // number of participants
+  fTree->Branch("nh",&nh,"nh/I");  // number of particles
+  fTree->Branch("momx",&momx,"momx[nh]/F");
+  fTree->Branch("momy",&momy,"momy[nh]/F");
+  fTree->Branch("momz",&momz,"momz[nh]/F");
+  fTree->Branch("ene",&ene,"ene[nh]/F");//[energy]
+  fTree->Branch("hid",&hid,"hid[nh]/I");//[histrory id]
+  fTree->Branch("pdg",&pdg,"pdg[nh]/I");//[particle data group code]
+  fTree->Branch("charge",&charge,"charge[nh]/S");//[electric charge]
+}
+
+mciWriter_mcpico::~mciWriter_mcpico()
+{
+  delete fTree;
+  delete fOutFile;
+}
+
+void mciWriter_mcpico::SetFile(const TString &outputFileName)
+{
+  if (!fOutFile) fOutFile = new TFile(outputFileName.Data(), "recreate");
+}
+
+void mciWriter_mcpico::SetEvent(mciEvent *const& _ievent)
+{
+  bimp  = _ievent->GetB();
+  phi2  = _ievent->GetPhiRP();
+  phi3  = 0.;
+  ecc2  = 0.;
+  ecc3  = 0.;
+  npart = 0;
+  nh    = _ievent->GetNparticles();
+}
+
+void mciWriter_mcpico::SetParticle(mciParticle *const& _iparticle, Int_t id)
+{
+  momx[id]   = _iparticle->GetPx();
+  momy[id]   = _iparticle->GetPy();
+  momz[id]   = _iparticle->GetPz();
+  ene[id]    = _iparticle->GetEnergy();
+  pdg[id]    = _iparticle->GetPdg();
+  hid[id]    = 0.;
+  charge[id] = _iparticle->GetCharge();
+}
+
+void mciWriter_mcpico::Fill()
+{
+  fTree->Fill();
+}
+
+void mciWriter_mcpico::Write()
+{
+  fOutFile->cd();
+  fTree->Write();
+}
+
+void mciWriter_mcpico::Close()
+{
+  fOutFile->Close();
+}

+ 55 - 0
writers/mciWriter_mcpico.h

@@ -0,0 +1,55 @@
+#ifndef MODELCONVERTER_WRITERS_MCPICO_H
+#define MODELCONVERTER_WRITERS_MCPICO_H
+
+#include <Rtypes.h>
+#include <TFile.h>
+#include <TTree.h>
+
+#include <mciEvent.h>
+#include <mciParticle.h>
+#include <Utility.h>
+
+#include <mciWriter_manager.h>
+
+#define MAX_TRACKS 15000
+
+class mciWriter_mcpico : virtual public mciWriter_manager
+{
+private:
+  
+  TFile *fOutFile;
+  TTree *fTree;
+
+  const char *fTreeName = "mctree";
+
+  Float_t         bimp;
+  Float_t         phi2;
+  Float_t         phi3;
+  Float_t         ecc2;
+  Float_t         ecc3;
+  Int_t           npart;
+  Int_t           nh;
+  Float_t         momx[MAX_TRACKS];   //[nh]
+  Float_t         momy[MAX_TRACKS];   //[nh]
+  Float_t         momz[MAX_TRACKS];   //[nh]
+  Float_t         ene[MAX_TRACKS];   //[nh]
+  Int_t           hid[MAX_TRACKS];   //[nh]
+  Int_t           pdg[MAX_TRACKS];   //[nh]
+  Short_t         charge[MAX_TRACKS];   //[nh]
+
+public:
+  mciWriter_mcpico(/* args */);
+  virtual ~mciWriter_mcpico();
+
+  virtual void SetFile(const TString &outputFileName);
+  virtual void SetEvent(mciEvent *const& _ievent);
+  virtual void SetParticle(mciParticle *const& _iparticle, Int_t id);
+  virtual void Fill();
+  virtual void Write();
+  virtual void Close();
+
+  ClassDef(mciWriter_mcpico, 0);
+};
+
+
+#endif