From b76a2ab25546d9e6a785788e544fd36c3501af2f Mon Sep 17 00:00:00 2001
From: Cao Guangjie <gjcao@lxslc614.ihep.ac.cn>
Date: Tue, 17 Sep 2019 20:48:50 +0800
Subject: [PATCH] Convertor from LCIO to Plcio & LCIO Data Service

---
 Examples/CMakeLists.txt                 |   9 +-
 Examples/options/LCIO_read.py           |  43 +++++
 Examples/src/PlcioTest/PlcioReadAlg.cpp |  20 +-
 Examples/src/PlcioTest/PlcioReadAlg.h   |   4 +-
 FWCore/CMakeLists.txt                   |   6 +-
 FWCore/FWCore/LCIODataSvc.h             | 102 ++++++++++
 FWCore/src/components/LCIO2Plcio.cpp    | 238 ++++++++++++++++++++++++
 FWCore/src/components/LCIO2Plcio.h      |  76 ++++++++
 FWCore/src/components/LCIODataSvc.cpp   | 180 ++++++++++++++++++
 FWCore/src/components/LCIOInput.cpp     |  52 ++++++
 FWCore/src/components/LCIOInput.h       |  43 +++++
 11 files changed, 754 insertions(+), 19 deletions(-)
 create mode 100644 Examples/options/LCIO_read.py
 create mode 100644 FWCore/FWCore/LCIODataSvc.h
 create mode 100644 FWCore/src/components/LCIO2Plcio.cpp
 create mode 100644 FWCore/src/components/LCIO2Plcio.h
 create mode 100644 FWCore/src/components/LCIODataSvc.cpp
 create mode 100644 FWCore/src/components/LCIOInput.cpp
 create mode 100644 FWCore/src/components/LCIOInput.h

diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt
index 7db41df7..f9f4c9d9 100644
--- a/Examples/CMakeLists.txt
+++ b/Examples/CMakeLists.txt
@@ -3,6 +3,7 @@ gaudi_subdir(Examples v0r0)
 
 find_package(podio REQUIRED)
 find_package(plcio REQUIRED)
+find_package(LCIO REQUIRED)
 
 set(Examples_srcs
     src/HelloWorld/*.cpp
@@ -17,8 +18,8 @@ gaudi_install_headers(Examples)
 
 # Modules
 gaudi_add_module(Examples ${Examples_srcs}
-    INCLUDE_DIRS GaudiKernel FWCore ${plcio_INCLUDE_DIRS} ${podio_INCLUDE_DIRS}
-    LINK_LIBRARIES GaudiKernel FWCore ${podio_LIBRARIES} $ENV{PLCIO}/lib/libplcio.so
+    INCLUDE_DIRS GaudiKernel FWCore ${plcio_INCLUDE_DIRS} ${podio_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS}
+    LINK_LIBRARIES GaudiKernel FWCore ${podio_LIBRARIES} ${LCIO_LIBRARIES} $ENV{PLCIO}/lib/libplcio.so
 )
 
 # Unit tests
@@ -33,3 +34,7 @@ gaudi_add_test(PlcioWriteAlg
 
 gaudi_add_test(PlcioReadAlg
                FRAMEWORK options/plcio_read.py)
+
+gaudi_add_test(LCIOReadAlg
+               FRAMEWORK options/LCIO_read.py)
+
diff --git a/Examples/options/LCIO_read.py b/Examples/options/LCIO_read.py
new file mode 100644
index 00000000..0a3a9428
--- /dev/null
+++ b/Examples/options/LCIO_read.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+from Gaudi.Configuration import *
+
+from Configurables import LCIODataSvc
+dsvc = LCIODataSvc("EventDataSvc", input="/cefs/data/FullSim/CEPC240/CEPC_v4/higgs/E240.Pe2e2h_bb.e0.p0.whizard195/e2e2h_bb.e0.p0.00001_000000_sim.slcio")
+
+from Configurables import PlcioReadAlg
+alg = PlcioReadAlg("PlcioReadAlg")
+
+from Configurables import LCIOInput
+lcioinput = LCIOInput("LCIOReader", collections=[
+    "MCParticle",
+    "COILCollection",
+    "EcalBarrelSiliconCollection",
+    "EcalBarrelSiliconPreShowerCollection",
+    "EcalEndcapRingCollection",
+    "EcalEndcapRingPreShowerCollection",
+    "EcalEndcapSiliconCollection",
+    "EcalEndcapSiliconPreShowerCollection",
+    "FTD_PIXELCollection",
+    "FTD_STRIPCollection",
+    "HcalBarrelCollection",
+    "HcalEndCapRingsCollection",
+    "HcalEndCapsCollection",
+    "LumiCalCollection",
+    "MuonBarrelCollection",
+    "MuonEndCapCollection",
+    "SETCollection",
+    "SITCollection",
+    "TPCCollection",
+    "TPCSpacePointCollection",
+    "VXDCollection"
+    ])
+
+# ApplicationMgr
+from Configurables import ApplicationMgr
+ApplicationMgr( TopAlg = [lcioinput, alg],
+                EvtSel = 'NONE',
+                EvtMax = 10,
+                ExtSvc = [dsvc],
+                OutputLevel=DEBUG
+)
diff --git a/Examples/src/PlcioTest/PlcioReadAlg.cpp b/Examples/src/PlcioTest/PlcioReadAlg.cpp
index 5921731c..59d420dd 100644
--- a/Examples/src/PlcioTest/PlcioReadAlg.cpp
+++ b/Examples/src/PlcioTest/PlcioReadAlg.cpp
@@ -1,5 +1,4 @@
 #include "PlcioReadAlg.h"
-#include "plcio/EventHeaderCollection.h"
 #include "plcio/MCParticleCollection.h"
 
 DECLARE_COMPONENT(PlcioReadAlg)
@@ -7,8 +6,7 @@ DECLARE_COMPONENT(PlcioReadAlg)
 PlcioReadAlg::PlcioReadAlg(const std::string& name, ISvcLocator* svcLoc)
     : GaudiAlgorithm(name, svcLoc)
 {
-    declareProperty("HeaderCol", m_headerCol);
-    declareProperty("InputCol", m_mcParCol, "MCParticle collection (input)");
+    declareProperty("MCParticleCol", m_hdl, "MCParticle collection (input)");
 }
 
 StatusCode PlcioReadAlg::initialize()
@@ -20,21 +18,19 @@ StatusCode PlcioReadAlg::initialize()
 StatusCode PlcioReadAlg::execute()
 {
     debug() << "begin execute PlcioReadAlg" << endmsg;
+    auto mcCol = m_hdl.get();
 
-    auto headers = m_headerCol.get();
-    auto header = headers->at(0);
-    auto mcCol = m_mcParCol.get();
-
-    info() << "Run " << header.getRunNumber() << " Event " << header.getEventNumber() << " { ";
+//    debug() << "testing loop..." <<endmsg;
     for ( auto p : *mcCol ) {
-        info() << p.getObjectID().index << " : [";
+        debug() << p.getObjectID().index << " : [";
         for ( auto it = p.daughters_begin(), end = p.daughters_end(); it != end; ++it ) {
-            info() << " " << it->getObjectID().index;
+            debug() << " " << it->getObjectID().index;
         }
-        info() << " ]; ";
+        debug() << " ]; ";
     }
-    info() << "}" << endmsg;
+    debug() << endmsg;
 
+//    debug() << "end execute PlcioReadAlg" << endmsg;
     return StatusCode::SUCCESS;
 }
 
diff --git a/Examples/src/PlcioTest/PlcioReadAlg.h b/Examples/src/PlcioTest/PlcioReadAlg.h
index 5b9ec815..07d0eae4 100644
--- a/Examples/src/PlcioTest/PlcioReadAlg.h
+++ b/Examples/src/PlcioTest/PlcioReadAlg.h
@@ -5,7 +5,6 @@
 #include "GaudiAlg/GaudiAlgorithm.h"
 
 namespace plcio {
-    class EventHeaderCollection;
     class MCParticleCollection;
 }
 
@@ -23,8 +22,7 @@ class PlcioReadAlg : public GaudiAlgorithm
 
     private :
 
-        DataHandle<plcio::EventHeaderCollection> m_headerCol{"EventHeaderCol", Gaudi::DataHandle::Reader, this};
-        DataHandle<plcio::MCParticleCollection> m_mcParCol{"MCParticleCol", Gaudi::DataHandle::Reader, this};
+        DataHandle<plcio::MCParticleCollection> m_hdl{"MCParticle", Gaudi::DataHandle::Reader, this};
 
 };
 
diff --git a/FWCore/CMakeLists.txt b/FWCore/CMakeLists.txt
index 0540c5e3..3cc5478b 100644
--- a/FWCore/CMakeLists.txt
+++ b/FWCore/CMakeLists.txt
@@ -4,6 +4,8 @@
 gaudi_subdir(FWCore v0r1)
 
 find_package(podio REQUIRED)
+find_package(plcio REQUIRED)
+find_package(LCIO REQUIRED)
 find_package(ROOT COMPONENTS RIO Tree)
 
 # this declaration will not be needed in the future
@@ -13,8 +15,8 @@ gaudi_install_python_modules()
 
 gaudi_add_library(FWCore
 		  src/*.cpp
-                  INCLUDE_DIRS ${podio_INCLUDE_DIRS} ROOT
-                  LINK_LIBRARIES GaudiAlgLib GaudiKernel ${podio_LIBRARIES} ROOT
+                  INCLUDE_DIRS ${podio_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS} ${plcio_INCLUDE_DIRS} ROOT
+                  LINK_LIBRARIES GaudiAlgLib GaudiKernel ${podio_LIBRARIES} ${LCIO_LIBRARIES} ${plcio_LIBRARIES} ROOT
                   PUBLIC_HEADERS FWCore)
 
 gaudi_add_module(FWCorePlugins
diff --git a/FWCore/FWCore/LCIODataSvc.h b/FWCore/FWCore/LCIODataSvc.h
new file mode 100644
index 00000000..9627a8b7
--- /dev/null
+++ b/FWCore/FWCore/LCIODataSvc.h
@@ -0,0 +1,102 @@
+#ifndef FWCORE_LCIODATASVC_H
+#define FWCORE_LCIODATASVC_H
+
+#include "GaudiKernel/DataSvc.h"
+#include "GaudiKernel/IConversionSvc.h"
+// LCIO
+#include "podio/CollectionBase.h"
+#include "podio/CollectionIDTable.h"
+#include "podio/EventStore.h"
+#include "podio/ROOTReader.h"
+
+#include "IO/LCReader.h"
+#include "EVENT/LCCollection.h"
+#include "EVENT/MCParticle.h"
+#include "plcio/MCParticleCollection.h"
+#include "plcio/MCParticle.h"
+#include "plcio/EventHeaderCollection.h"
+
+#include "src/components/LCIO2Plcio.h"
+#include <utility>
+// Forward declarations
+
+/** @class LCIOEvtSvc EvtDataSvc.h
+ *
+ *   An EvtDataSvc for LCIO classes
+ *
+ *  @author B. Hegner
+ */
+class LCIODataSvc : public DataSvc {
+public:
+
+  friend class SvcFactory<LCIODataSvc>;
+
+  typedef std::vector<std::pair<std::string, podio::CollectionBase*>> CollRegistry;
+
+  virtual StatusCode initialize();
+  virtual StatusCode reinitialize();
+  virtual StatusCode finalize();
+  virtual StatusCode clearStore();
+
+  /// Standard Constructor
+  LCIODataSvc(const std::string& name, ISvcLocator* svc);
+
+  /// Standard Destructor
+  virtual ~LCIODataSvc();
+
+  // Use DataSvc functionality except where we override
+  using DataSvc::registerObject;
+  /// Overriding standard behaviour of evt service
+  /// Register object with the data store.
+  virtual StatusCode registerObject(const std::string& fullPath, DataObject* pObject) final;
+
+  StatusCode readCollection(const std::string& collectionName, int collectionID);
+
+  virtual const CollRegistry& getCollections() const { return m_collections; }
+  virtual const CollRegistry& getReadCollections() const { return m_readCollections; }
+  virtual podio::CollectionIDTable* getCollectionIDs() { return m_collectionIDs; }
+
+  /// Set the collection IDs (if reading a file)
+  void setCollectionIDs(podio::CollectionIDTable* collectionIds);
+  /// Resets caches of reader and event store, increases event counter
+  void endOfRead();
+
+
+  TTree* eventDataTree() {return m_eventDataTree;}
+
+private:
+
+  EVENT::LCEvent* evt = nullptr;
+  // eventDataTree
+  TTree* m_eventDataTree;
+  /// LCIO reader for ROOT files
+  IO::LCReader* m_reader;
+  /// LCIO reader for ROOT files
+  plcio::EventHeaderCollection* pl_evtcol;
+  /// podio::ROOTReader m_reader;
+  /// LCIO EventStore, used to initialise collections
+  /// podio::EventStore m_provider;
+  /// Counter of the event number
+  int m_eventNum{0};
+  /// Number of events in the file / to process
+  int m_eventMax{-1};
+
+
+  SmartIF<IConversionSvc> m_cnvSvc;
+
+  // special members for podio handling
+  std::vector<std::pair<std::string, podio::CollectionBase*>> m_collections;
+  std::vector<std::pair<std::string, podio::CollectionBase*>> m_readCollections;
+  podio::CollectionIDTable* m_collectionIDs;
+
+protected:
+//  bool exist_MCP = false;
+  LCIO2Plcio cvtor;
+//  EVENT::LCCollection* mcpcol_lc;
+//  plcio::MCParticleCollection* mcpcol_pl;
+
+  /// ROOT file name the input is read from. Set by option filename
+  std::vector<std::string> m_filenames;
+  std::string m_filename;
+};
+#endif  // CORE_LCIODATASVC_H
diff --git a/FWCore/src/components/LCIO2Plcio.cpp b/FWCore/src/components/LCIO2Plcio.cpp
new file mode 100644
index 00000000..ac853eaa
--- /dev/null
+++ b/FWCore/src/components/LCIO2Plcio.cpp
@@ -0,0 +1,238 @@
+#include "LCIO2Plcio.h"
+
+#include "lcio.h"
+#include "EVENT/LCCollection.h" 
+#include "plcio/MCParticle.h"
+#include "plcio/MCParticleConst.h"
+#include "plcio/MCParticleCollection.h"
+#include "plcio/LCRunHeader.h"
+#include "plcio/LCRunHeaderCollection.h"
+#include "EVENT/MCParticle.h"
+
+typedef std::vector<EVENT::MCParticle*> MCParticleVec ;
+
+//std::map<std::string, fptr> LCIO2Plcio::map_cvt;
+CollectionsMap LCIO2Plcio::map_cols;
+
+void lp_info(std::string s){
+  printf("[LCIO2Plcio]:\t\t%s.\n", &s[0]);
+}
+
+LCIO2Plcio::LCIO2Plcio(){
+  map_cvt.insert(std::make_pair<std::string, fptr>("MCParticle", Convertor_MCParticle));
+  map_cvt.insert(std::make_pair<std::string, fptr>("LCRunHeader", Convertor_LCRunHeader));
+  map_cvt.insert(std::make_pair<std::string, fptr>("SimTrackerHit", Convertor_SimTrackerHit));
+  map_cvt.insert(std::make_pair<std::string, fptr>("SimCalorimeterHit", Convertor_SimCalorimeterHit));
+}
+LCIO2Plcio::LCIO2Plcio(EVENT::LCCollection* collection){
+  LCIO2Plcio();
+}
+
+podio::CollectionBase* LCIO2Plcio::Convertor_LCRunHeader(EVENT::LCCollection* lc_col){
+  plcio::LCRunHeaderCollection* pl_col = new plcio::LCRunHeaderCollection();
+//  plcio::LCRunHeader pl_rh = (plcio::LCRunHeader) pl_col->create();
+  return pl_col;
+}
+
+void LCIO2Plcio::void_Core_MCParticle(EVENT::MCParticle* lc_mcp, plcio::MCParticle& pl_mcp){
+
+  pl_mcp.setPDG( lc_mcp->getPDG() );
+  pl_mcp.setGeneratorStatus( lc_mcp->getGeneratorStatus() );
+  pl_mcp.setSimulatorStatus( lc_mcp->getSimulatorStatus() );
+  pl_mcp.setCharge( lc_mcp->getCharge() );
+  pl_mcp.setTime( lc_mcp->getTime() );
+  pl_mcp.setMass( lc_mcp->getMass() );
+  pl_mcp.setStopped( lc_mcp->isStopped() );
+  pl_mcp.setOverlay( lc_mcp->isOverlay() );
+  pl_mcp.setBackscatter( lc_mcp->isBackscatter() );
+  pl_mcp.setDecayedInTracker( lc_mcp->isDecayedInTracker() );
+  pl_mcp.setDecayedInCalorimeter( lc_mcp->isDecayedInCalorimeter() );
+  pl_mcp.setCreatedInSimulation( lc_mcp->isCreatedInSimulation() );
+  pl_mcp.setVertexIsNotEndpointOfParent( lc_mcp->vertexIsNotEndpointOfParent() );
+  pl_mcp.setHasLeftDetector( lc_mcp->hasLeftDetector() );
+
+  pl_mcp.setSpin( plcio::FloatThree( lc_mcp->getSpin() ) );
+  pl_mcp.setColorFlow( plcio::IntTwo( lc_mcp->getColorFlow() ) );
+  pl_mcp.setVertex( plcio::DoubleThree( lc_mcp->getVertex()));
+  pl_mcp.setEndpoint( plcio::DoubleThree( lc_mcp->getEndpoint() ) );
+
+  // send float ptr as parameter to FloatThree.
+  float plcio_m[3];
+  const double* lcio_m = lc_mcp->getMomentum();
+  plcio_m[0] = lcio_m[0];
+  plcio_m[1] = lcio_m[1];
+  plcio_m[2] = lcio_m[2];
+  pl_mcp.setMomentum( plcio::FloatThree( plcio_m ) );
+
+  lcio_m = lc_mcp->getMomentumAtEndpoint();
+  plcio_m[0] = lcio_m[0];
+  plcio_m[1] = lcio_m[1];
+  plcio_m[2] = lcio_m[2];
+  pl_mcp.setMomentumAtEndpoint( plcio::FloatThree( plcio_m ) );
+}
+
+podio::CollectionBase* LCIO2Plcio::Convertor_MCParticle(EVENT::LCCollection* lc_col){
+  return Core_MCParticle(lc_col);
+}
+
+plcio::MCParticleCollection* LCIO2Plcio::Core_MCParticle(EVENT::LCCollection* lc_col){
+  plcio::MCParticleCollection* pl_col = new plcio::MCParticleCollection();
+
+  // Convert basic info from LCIO to plcio;
+  for( unsigned i=0,N=lc_col->getNumberOfElements() ; i< N ; ++i){
+      EVENT::MCParticle* lc_mcp = (EVENT::MCParticle*) lc_col->getElementAt(i) ;
+      plcio::MCParticle pl_mcp = (plcio::MCParticle) pl_col->create();
+
+      void_Core_MCParticle(lc_mcp, pl_mcp);
+      // dealing each of 'Parents' of lcio::MCParticle ;
+      const MCParticleVec& veclc = lc_mcp->getParents();
+      for(unsigned j=0; j<veclc.size(); j++){
+        EVENT::MCParticle* vlcreg = veclc[j];
+        for(unsigned k=0; k<i; ++k){
+          if(((EVENT::MCParticle*) lc_col->getElementAt(k)) == vlcreg){
+            // A loop for plcio's MCParticleCollection to recover plcio's relationship;
+            plcio::MCParticle plprt = pl_col->at(k);
+            pl_mcp.addParent(plprt);
+            plprt.addDaughter(pl_mcp);        
+	  }
+	}
+      }
+  }
+  return pl_col;
+}
+
+//void LCIO2Plcio::setPlcioMCParticleCollection(plcio::MCParticleCollection* pl_col){
+//  hitcol_pl = pl_col;
+//}
+
+//void LCIO2Plcio::setLCIOMCParticleCollection(EVENT::LCCollection* lc_col){
+//  hitcol_lc = lc_col;
+//}
+
+
+podio::CollectionBase* LCIO2Plcio::Convertor_SimTrackerHit(EVENT::LCCollection* lc_col){
+  plcio::SimTrackerHitCollection* pl_col = new plcio::SimTrackerHitCollection();
+
+  for( unsigned i=0,N=lc_col->getNumberOfElements() ; i< N ; ++i){
+    EVENT::SimTrackerHit* lc_sth = (EVENT::SimTrackerHit*) lc_col->getElementAt(i) ;
+    plcio::SimTrackerHit pl_sth = (plcio::SimTrackerHit) pl_col->create();
+
+    pl_sth.setCellID0( lc_sth->getCellID0() );
+    pl_sth.setCellID1( lc_sth->getCellID1() );
+    pl_sth.setEDep( lc_sth->getEDep() );
+    pl_sth.setTime( lc_sth->getTime() );
+    pl_sth.setPathLength( lc_sth->getPathLength() );
+    pl_sth.setQuality( lc_sth->getQuality() );
+    pl_sth.setPosition( lc_sth->getPosition() );
+    pl_sth.setMomentum( lc_sth->getMomentum() );
+    pl_sth.setOverlay( lc_sth->isOverlay() );
+    pl_sth.setProducedBySecondary( lc_sth->isProducedBySecondary() );
+
+    // Looping the LCIO::MCParticleCollection to pick Particle for Hits;
+    CollectionsVec vec_mcp;
+    vec_mcp = map_cols["MCParticle"];
+    EVENT::LCCollection* hitcol_lc = (EVENT::LCCollection*) vec_mcp[0].first;
+    plcio::MCParticleCollection* hitcol_pl = (plcio::MCParticleCollection*) vec_mcp[0].second;
+
+    int index = -1;
+    // search corresponding MCParticleCollection*;
+    EVENT::MCParticle* mcptr_reg = lc_sth->getMCParticle();
+    for( unsigned j=0, M=hitcol_lc->getNumberOfElements(); j<M; ++j){
+      EVENT::MCParticle* mcpin_lc = (EVENT::MCParticle*) hitcol_lc->getElementAt(j);
+      if( mcpin_lc == mcptr_reg ){
+	index = j;
+      }
+    }
+//    if( index != -1) lp_info("Cedar: Convertor SimTrackerHit Success.");
+    bool is_empty = false;
+    if( index == -1){
+      if(mcptr_reg == nullptr) is_empty = true;
+//      lp_info("Convertor SimTrackerHit Problem.");
+//      printf("LCCollection size: %d\n", hitcol_lc->getNumberOfElements());
+//      printf("MCParticleCollection size: %d\n", hitcol_pl->size());
+//      printf("Index: %d\n", index);
+    }
+    if( is_empty == false )
+      pl_sth.setMCParticle( hitcol_pl->at(index) );
+
+  }
+  return pl_col;
+}
+
+podio::CollectionBase* LCIO2Plcio::Convertor_SimCalorimeterHit(EVENT::LCCollection* lc_col){
+  plcio::SimCalorimeterHitCollection* pl_col = new plcio::SimCalorimeterHitCollection();
+
+  for( unsigned i=0,N=lc_col->getNumberOfElements() ; i< N ; ++i){
+    EVENT::SimCalorimeterHit* lc_sch = (EVENT::SimCalorimeterHit*) lc_col->getElementAt(i);
+    plcio::SimCalorimeterHit pl_sch = (plcio::SimCalorimeterHit) pl_col->create();
+
+    pl_sch.setCellID0( lc_sch->getCellID0() );
+    pl_sch.setCellID1( lc_sch->getCellID1() );
+    pl_sch.setEnergy( lc_sch->getEnergy() );
+
+    float plcio_p[3];
+    const float* lcio_p = lc_sch->getPosition();
+    plcio_p[0] = lcio_p[0];
+    plcio_p[1] = lcio_p[1];
+    plcio_p[2] = lcio_p[2];
+    pl_sch.setPosition( plcio::FloatThree( plcio_p ) );
+
+    // converting from lc_sch to pl_sch on the contribution variables;
+    for( unsigned j=0, N=lc_sch->getNMCContributions(); j<N; j++){
+      plcio_p[0] = lc_sch->getStepPosition(j)[0];
+      plcio_p[1] = lc_sch->getStepPosition(j)[1];
+      plcio_p[2] = lc_sch->getStepPosition(j)[2];
+
+      plcio::ConstCaloHitContribution tmp(
+	lc_sch->getPDGCont(j), lc_sch->getEnergyCont(j),
+	lc_sch->getTimeCont(j), plcio::FloatThree(plcio_p) 
+      );
+      pl_sch.addContribution( tmp );
+    }
+  }
+
+  return pl_col;
+}
+
+bool LCIO2Plcio::isReady(const std::string& TypeName){
+  if( TypeName == "SimTrackerHit" ){
+    std::vector<std::string>::iterator it = find(
+                  vec_Types.begin(), vec_Types.end(), "MCParticle"
+    );
+    if( it != vec_Types.end() )
+      return true;
+  }
+  return false;
+}
+
+podio::CollectionBase* LCIO2Plcio::Convertor_getPlcio(EVENT::LCCollection* lc_col){
+
+  podio::CollectionBase* collection(nullptr);
+  TypeName = lc_col->getTypeName();
+
+//  lp_info("Converting "+TypeName);
+  bool ready = true; 
+  if( !ready ){
+    lp_info("Not ready yet.");
+    lp_info("Please put MCParticle firstly in the python file, Please");
+    return nullptr;
+  }
+
+  fptr fp;
+  if( map_cvt.find(TypeName) == map_cvt.end()){
+    lp_info("unrecognized "+TypeName);
+  }else{
+    fp = *map_cvt[TypeName];
+  }
+
+  fp = *map_cvt[TypeName];
+  collection = fp(lc_col);
+
+// maintain map<TypeName, CollVec>;
+    map_cols[TypeName].push_back(
+      std::pair<EVENT::LCCollection*, podio::CollectionBase*>(lc_col, collection)
+    );
+
+//  lp_info("done.");
+  return collection;
+}
diff --git a/FWCore/src/components/LCIO2Plcio.h b/FWCore/src/components/LCIO2Plcio.h
new file mode 100644
index 00000000..799f864e
--- /dev/null
+++ b/FWCore/src/components/LCIO2Plcio.h
@@ -0,0 +1,76 @@
+#ifndef FWCORE_CONVERTOR_H
+#define FWCORE_CONVERTOR_H
+
+// LCIO
+
+#include <map>
+#include <iostream>
+#include <string>
+#include "lcio.h"
+// #include "IO/LCReader.h"
+// #include "EVENT/LCCollection.h"
+#include "EVENT/MCParticle.h"
+#include "EVENT/SimTrackerHit.h"
+#include "EVENT/SimCalorimeterHit.h"
+#include "plcio/SimTrackerHit.h"
+#include "plcio/SimTrackerHitCollection.h"
+#include "plcio/SimCalorimeterHit.h"
+#include "plcio/SimCalorimeterHitCollection.h"
+#include "plcio/MCParticle.h"
+#include "plcio/MCParticleCollection.h"
+
+#include <utility>
+// Forward declarations
+
+/** @class LCIO2Plcio LCIO2Plcio.h
+ *
+ *   An LCIO2Plcio for Converting from LCCollection to plcio collection;
+ *
+ *  @author jhZou, gjCao 
+ */
+
+// typedef plcio::MCParticleCollection* (*fptr) (EVENT::LCCollection*);
+typedef podio::CollectionBase* (*fptr) (EVENT::LCCollection*);
+typedef std::vector<std::pair<EVENT::LCCollection*, podio::CollectionBase*>> CollectionsVec;
+typedef std::map<std::string, CollectionsVec> CollectionsMap;
+
+class LCIO2Plcio{
+public:
+
+  /// Standard Constructor
+  LCIO2Plcio();
+  LCIO2Plcio(EVENT::LCCollection*);
+
+  /// Standard Destructor
+  virtual ~LCIO2Plcio(){}
+
+  void test(){ printf("MYTESTFUC\n"); }
+  void clear(){ map_cols.clear(); };
+
+//  plcio::MCParticleCollection* Convertor_getPlcio(EVENT::LCCollection*);
+  podio::CollectionBase* Convertor_getPlcio(EVENT::LCCollection*);
+  static podio::CollectionBase* Convertor_MCParticle(EVENT::LCCollection*);
+  static podio::CollectionBase* Convertor_LCRunHeader(EVENT::LCCollection*);
+  static podio::CollectionBase* Convertor_SimTrackerHit(EVENT::LCCollection*);
+  static podio::CollectionBase* Convertor_SimCalorimeterHit(EVENT::LCCollection*);
+
+  static void void_Core_MCParticle(EVENT::MCParticle*, plcio::MCParticle&);
+  static plcio::MCParticleCollection* Core_MCParticle(EVENT::LCCollection*);
+
+  bool isReady(const std::string&);
+  void setPlcioMCParticleCollection(plcio::MCParticleCollection*);
+  void setLCIOMCParticleCollection(EVENT::LCCollection*);
+
+private:
+  std::string TypeName;
+  // maintain a log vec about data read;
+  std::vector<std::string> vec_Types;
+
+  // maintain a map from keyword to function pointer.
+  std::map<std::string, fptr> map_cvt;
+  static CollectionsMap map_cols;
+
+//  plcio::MCParticleCollection* hitcol_pl;
+//  EVENT::LCCollection* hitcol_lc;
+};
+#endif  // CORE_CONVERTOR_H
diff --git a/FWCore/src/components/LCIODataSvc.cpp b/FWCore/src/components/LCIODataSvc.cpp
new file mode 100644
index 00000000..b5ed5235
--- /dev/null
+++ b/FWCore/src/components/LCIODataSvc.cpp
@@ -0,0 +1,180 @@
+#include "FWCore/LCIODataSvc.h"
+#include "LCIO2Plcio.h"
+#include "GaudiKernel/IConversionSvc.h"
+#include "GaudiKernel/IEventProcessor.h"
+#include "GaudiKernel/ISvcLocator.h"
+
+#include "IOIMPL/LCFactory.h"
+#include "FWCore/DataWrapper.h"
+#include "lcio.h"
+#include "plcio/MCParticleCollection.h"
+#include "plcio/MCParticle.h"
+#include "plcio/EventHeaderCollection.h"
+#include "EVENT/MCParticle.h"
+
+#include "TTree.h"
+
+typedef std::vector<lcio::MCParticle*> MCParticleVec ;  
+
+DECLARE_SERVICE_FACTORY(LCIODataSvc)
+/// Service initialisation
+StatusCode LCIODataSvc::initialize() {
+  // Nothing to do: just call base class initialisation
+  StatusCode status = DataSvc::initialize();
+  ISvcLocator* svc_loc = serviceLocator();
+
+  // Attach data loader facility
+  m_cnvSvc = svc_loc->service("EventPersistencySvc");
+  status = setDataLoader(m_cnvSvc);
+
+  m_reader = IOIMPL::LCFactory::getInstance()->createLCReader();
+
+  if (m_filename != "") {
+    m_filenames.push_back(m_filename);
+  }
+
+  if (m_filenames.size() > 0) {
+    if (m_filenames[0] != "") {
+      m_reader->open(m_filenames);
+      m_eventMax = m_reader->getNumberOfEvents();
+    }
+  }
+  return status;
+}
+/// Service reinitialisation
+StatusCode LCIODataSvc::reinitialize() {
+  // Do nothing for this service
+  return StatusCode::SUCCESS;
+}
+/// Service finalization
+StatusCode LCIODataSvc::finalize() {
+  m_cnvSvc = 0;  // release
+  DataSvc::finalize().ignore();
+  return StatusCode::SUCCESS;
+}
+
+StatusCode LCIODataSvc::clearStore() {
+  for (auto& collNamePair : m_collections) {
+    if (collNamePair.second != nullptr) {
+      collNamePair.second->clear();
+    }
+  }
+  for (auto& collNamePair : m_readCollections) {
+    if (collNamePair.second != nullptr) {
+      collNamePair.second->clear();
+    }
+  }
+  DataSvc::clearStore().ignore();
+  m_collections.clear();
+  m_readCollections.clear();
+  return StatusCode::SUCCESS;
+}
+
+void LCIODataSvc::endOfRead() {
+  if (m_eventMax != -1) {
+    // m_provider.clearCaches();
+    // m_reader.endOfEvent();
+    if (m_eventNum++ > m_eventMax) {
+      info() << "Reached end of file with event " << m_eventMax << endmsg;
+      IEventProcessor* eventProcessor;
+      service("ApplicationMgr", eventProcessor);
+      eventProcessor->stopRun();
+    }
+  }
+  evt = nullptr;
+}
+
+void LCIODataSvc::setCollectionIDs(podio::CollectionIDTable* collectionIds) {
+  if (m_collectionIDs != nullptr) {
+    delete m_collectionIDs;
+  }
+  m_collectionIDs = collectionIds;
+}
+
+/// Standard Constructor
+LCIODataSvc::LCIODataSvc(const std::string& name, ISvcLocator* svc)
+    : DataSvc(name, svc), m_collectionIDs(new podio::CollectionIDTable()) {
+
+  m_eventDataTree = new TTree("events", "Events tree");
+  declareProperty("inputs", m_filenames = {}, "Names of the files to read");
+  declareProperty("input", m_filename = "", "Name of the file to read");
+
+    }
+
+/// Standard Destructor
+LCIODataSvc::~LCIODataSvc() {}
+
+
+StatusCode LCIODataSvc::readCollection(const std::string& collName, int collectionID) {
+  podio::CollectionBase* collection(nullptr);
+
+  if( evt == nullptr ){
+    evt = m_reader->readNextEvent();
+    cvtor.clear();
+
+    // basicly set EventHeader;
+    pl_evtcol = new plcio::EventHeaderCollection();
+    plcio::EventHeader evt_header;
+    evt_header = (plcio::EventHeader) pl_evtcol->create();
+    evt_header.setEventNumber( evt->getEventNumber() );
+    evt_header.setRunNumber( evt->getRunNumber() );
+    evt_header.setTimeStamp( evt->getTimeStamp() );
+    evt_header.setDetectorName( evt->getDetectorName() );
+
+    // wrap event header collection into Data service;
+    auto wrapper = new DataWrapper<podio::CollectionBase>;
+    int id = m_collectionIDs->add("EventHeader");
+    pl_evtcol->setID(id);
+    wrapper->setData(pl_evtcol);
+    m_readCollections.emplace_back(std::make_pair("EventHeader", pl_evtcol));
+
+    DataSvc::registerObject("EventHeader", wrapper);
+  }
+
+  debug() << "reading collection name: " << collName  << "." << endmsg;
+  EVENT::LCCollection* lc_col;
+  std::vector<std::string> vec_colns = *evt->getCollectionNames();
+  std::vector<std::string>::iterator it = find(vec_colns.begin(), vec_colns.end(), collName);
+  if( it != vec_colns.end() ){
+    lc_col = evt->getCollection(collName); 
+  }
+  else return StatusCode::SUCCESS;
+//  debug() << "Got collection: " << collName  << "." << endmsg;
+
+  std::string TypeName = lc_col->getTypeName();
+//  if( !exist_MCP && (TypeName == "MCParticle") ) exist_MCP = true;
+//  if( TypeName == "MCParticle" ){
+//    if( !exist_MCP ) exist_MCP = true;
+//    mcpcol_pl = LCIO2Plcio::Core_MCParticle(lc_col);
+//    LCIO2Plcio::setLCIOMCParticleCollection(mcpcol_lc);
+//    LCIO2Plcio::setPlcioMCParticleCollection(mcpcol_pl);
+//  }
+  collection = cvtor.Convertor_getPlcio( lc_col );
+  pl_evtcol->at(0)->addCollectionName(collName);
+  pl_evtcol->at(0)->addCollectionType(TypeName);
+
+  auto wrapper = new DataWrapper<podio::CollectionBase>;
+  int id = m_collectionIDs->add(collName);
+  collection->setID(id);
+  wrapper->setData(collection);
+  m_readCollections.emplace_back(std::make_pair(collName, collection));
+
+//  info() << "readCollection completed." << endmsg;
+
+  return DataSvc::registerObject(collName, wrapper);
+}
+
+StatusCode LCIODataSvc::registerObject(const std::string& fullPath, DataObject* pObject) {
+  DataWrapperBase* wrapper = dynamic_cast<DataWrapperBase*>(pObject);
+  if (wrapper != nullptr) {
+    podio::CollectionBase* coll = wrapper->collectionBase();
+    if (coll != nullptr) {
+      size_t pos = fullPath.find_last_of("/");
+      std::string shortPath(fullPath.substr(pos + 1, fullPath.length()));
+      int id = m_collectionIDs->add(shortPath);
+      coll->setID(id);
+      m_collections.emplace_back(std::make_pair(shortPath, coll));
+    }
+  }
+  return DataSvc::registerObject(fullPath, pObject);
+}
diff --git a/FWCore/src/components/LCIOInput.cpp b/FWCore/src/components/LCIOInput.cpp
new file mode 100644
index 00000000..c6a81070
--- /dev/null
+++ b/FWCore/src/components/LCIOInput.cpp
@@ -0,0 +1,52 @@
+#include "LCIOInput.h"
+
+#include "TFile.h"
+#include "TROOT.h"
+
+#include "FWCore/DataWrapper.h"
+#include "FWCore/LCIODataSvc.h"
+
+DECLARE_COMPONENT(LCIOInput)
+
+LCIOInput::LCIOInput(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) {}
+
+StatusCode LCIOInput::initialize() {
+  if (GaudiAlgorithm::initialize().isFailure()) return StatusCode::FAILURE;
+
+  // check whether we have the LCIOEvtSvc active
+  m_LCIODataSvc = dynamic_cast<LCIODataSvc*>(evtSvc().get());
+  if (nullptr == m_LCIODataSvc) return StatusCode::FAILURE;
+
+  auto idTable = m_LCIODataSvc->getCollectionIDs();
+  for (auto& name : m_collectionNames) {
+    debug() << "Finding collection " << name << " in collection registry." << endmsg;
+/*
+    if (!idTable->present(name)) {
+      error() << "Requested product " << name << " not found." << endmsg;
+      return StatusCode::FAILURE;
+    }
+*/
+    m_collectionIDs.push_back(idTable->add(name));
+  }
+  return StatusCode::SUCCESS;
+}
+
+StatusCode LCIOInput::execute() {
+  size_t cntr = 0;
+  // Re-create the collections from ROOT file
+  for (auto& id : m_collectionIDs) {
+    const std::string& collName = m_collectionNames.value().at(cntr++);
+    debug() << "Registering collection to read " << collName << " with id " << id << endmsg;
+    if (m_LCIODataSvc->readCollection(collName, id).isFailure()) {
+      return StatusCode::FAILURE;
+    }
+  }
+  // Tell data service that we are done with requested collections
+  m_LCIODataSvc->endOfRead();
+  return StatusCode::SUCCESS;
+}
+
+StatusCode LCIOInput::finalize() {
+  if (GaudiAlgorithm::finalize().isFailure()) return StatusCode::FAILURE;
+  return StatusCode::SUCCESS;
+}
diff --git a/FWCore/src/components/LCIOInput.h b/FWCore/src/components/LCIOInput.h
new file mode 100644
index 00000000..f8492279
--- /dev/null
+++ b/FWCore/src/components/LCIOInput.h
@@ -0,0 +1,43 @@
+#ifndef FWCORE_LCIOINPUT_H
+#define FWCORE_LCIOINPUT_H
+// Gaaudi
+#include "GaudiAlg/GaudiAlgorithm.h"
+
+// STL
+#include <string>
+#include <vector>
+
+// forward declarations
+// from FWCore:
+class LCIODataSvc;
+
+/** @class LCIOInput FWCore/components/LCIOInput.h LCIOInput.h
+ *
+ *  Class that allows to read ROOT files written with LCIOInput
+ *
+ *  @author J. Lingemann
+ */
+
+class LCIOInput : public GaudiAlgorithm {
+  friend class AlgFactory<LCIOInput>;
+
+public:
+  /// Constructor.
+  LCIOInput(const std::string& name, ISvcLocator* svcLoc);
+  /// Initialization of LCIOInput. Acquires the data service, opens root file and creates trees.
+  virtual StatusCode initialize();
+  /// Execute. Re-creates collections that are specified to be read and sets references.
+  virtual StatusCode execute();
+  /// Finalize. Closes ROOT file.
+  virtual StatusCode finalize();
+
+private:
+  /// Name of collections to read. Set by option collections (this is temporary)
+  Gaudi::Property<std::vector<std::string>> m_collectionNames{this, "collections", {}, "Places of collections to read"};
+  /// Collection IDs (retrieved with CollectionIDTable from ROOT file, using collection names)
+  std::vector<int> m_collectionIDs;
+  /// Data service: needed to register objects and get collection IDs. Just an observing pointer.
+  LCIODataSvc* m_LCIODataSvc;
+};
+
+#endif
-- 
GitLab