Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 4021e4b54906b2457a3259a81e42a2ad36007c23)
+++ CMakeLists.txt	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -12,5 +12,5 @@
 
 #if(ET_ONLY)
-  add_subdirectory(earthworm)
+  add_subdirectory(src)
   add_subdirectory(bin)
   add_subdirectory(examples)
Index: n/test_encoding.cc
===================================================================
--- bin/test_encoding.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,102 +1,0 @@
-#include "RedisHelper.hh"
-#include <iostream>
-#include <vector>
-#include <typeinfo>
-
-int main() {
-
-  const char *python_ref[] =
-  {"{\"dtype\": \"int8\", \"shape\": [6], \"__ndarray__\": \"AQIDBDJ/\"}",
-  "{\"dtype\": \"uint8\", \"shape\": [6], \"__ndarray__\": \"AQIDBDJ/\"}",
-  "{\"dtype\": \"int16\", \"shape\": [6], \"__ndarray__\": \"AQACAAMABAAyAH8A\"}",
-  "{\"dtype\": \"uint16\", \"shape\": [6], \"__ndarray__\": \"AQACAAMABAAyAH8A\"}",
-  "{\"dtype\": \"int32\", \"shape\": [6], \"__ndarray__\": \"AQAAAAIAAAADAAAABAAAADIAAAB/AAAA\"}",
-  "{\"dtype\": \"uint32\", \"shape\": [6], \"__ndarray__\": \"AQAAAAIAAAADAAAABAAAADIAAAB/AAAA\"}",
-  "{\"dtype\": \"int64\", \"shape\": [6], \"__ndarray__\": \"AQAAAAAAAAACAAAAAAAAAAMAAAAAAAAABAAAAAAAAAAyAAAAAAAAAH8AAAAAAAAA\"}",
-  "{\"dtype\": \"uint64\", \"shape\": [6], \"__ndarray__\": \"AQAAAAAAAAACAAAAAAAAAAMAAAAAAAAABAAAAAAAAAAyAAAAAAAAAH8AAAAAAAAA\"}",
-  "{\"dtype\": \"float32\", \"shape\": [6], \"__ndarray__\": \"AACAPwAAAEAAAEBAAACAQAAASEIAAP5C\"}",
-  "{\"dtype\": \"float64\", \"shape\": [6], \"__ndarray__\": \"AAAAAAAA8D8AAAAAAAAAQAAAAAAAAAhAAAAAAAAAEEAAAAAAAABJQAAAAAAAwF9A\"}"};
-
-
-  std::vector<std::string> python_ref_vec(python_ref, python_ref+10);
-
-  std::string str;
-
-  c2json_int8(std::vector<int8_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
-  if(str!=python_ref[0]) {
-    std::cout << "failed to pass test " << 0 << std::endl;
-    return 1;
-  }
-  c2json_uint8(std::vector<uint8_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
-  if(str!=python_ref[1]) {
-    std::cout << "failed to pass test " << 1 << std::endl;
-    return 1;
-  }
-  c2json_int16(std::vector<int16_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
-  if(str!=python_ref[2]) {
-    std::cout << "failed to pass test " << 2 << std::endl;
-    return 1;
-  }
-  c2json_uint16(std::vector<uint16_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
-  if(str!=python_ref[3]) {
-    std::cout << "failed to pass test " << 3 << std::endl;
-    return 1;
-  }
-  c2json_int32(std::vector<int32_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
-  if(str!=python_ref[4]) {
-    std::cout << "failed to pass test " << 4 << std::endl;
-    return 1;
-  }
-  c2json_uint32(std::vector<uint32_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
-  if(str!=python_ref[5]) {
-    std::cout << "failed to pass test " << 5 << std::endl;
-    return 1;
-  }
-  c2json_int64(std::vector<int64_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
-  if(str!=python_ref[6]) {
-    std::cout << "failed to pass test " << 6 << std::endl;
-    return 1;
-  }
-  c2json_uint64(std::vector<uint64_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
-  if(str!=python_ref[7]) {
-    std::cout << "failed to pass test " << 7 << std::endl;
-    return 1;
-  }
-  c2json_float(std::vector<float> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
-  if(str!=python_ref[8]) {
-    std::cout << "failed to pass test " << 8 << std::endl;
-    return 1;
-  }
-  c2json_double(std::vector<double> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
-  if(str!=python_ref[9]) {
-    std::cout << "failed to pass test " << 9 << std::endl;
-    return 1;
-  }
-
-
-  std::cout << "passed all python cross comparison. " << std::endl;
-
-
-
-  //reference generated by python as
-  // import base64
-  // bytes_data = range(0,256)
-  // d="".join(map(chr, bytes_data))
-  // base64.b64encode(d)
-
-  std::string ref = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==";
-  unsigned char bytes[256];
-  for(unsigned i=0;i<256;i++)
-    bytes[i]=i;
-
-  std::string encoded;
-  base64_encode(bytes , 256, encoded) ;
-  if(encoded!=ref) {
-    std::cout <<  "error!" << std::endl;
-    return 2;
-  }
-  else
-    std::cout << "passed!" << std::endl;
-  return 0;
-
-}
Index: rthworm/CMakeLists.txt
===================================================================
--- earthworm/CMakeLists.txt	(revision 77fb58de50cf08d859a04c9aba35ed2da4c34785)
+++ 	(revision )
@@ -1,60 +1,0 @@
-project(earthworm)
-
-# add external package
-include(ExternalProject)
-
-set(EXTERNAL_INSTALL_LOCATION ${CMAKE_BINARY_DIR}/extern)
-
-if(WITH_REDIS)
-ExternalProject_Add(expkg_cpp_redis
-    GIT_REPOSITORY https://github.com/cpp-redis/cpp_redis.git
-    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION}
-    BUILD_COMMAND make -j
-    INSTALL_COMMAND make install
-    #UPDATE_COMMAND ""
-)
-endif()
-
-
-#include_directories(${EXTERNAL_INSTALL_LOCATION}/include)
-#link_directories(${EXTERNAL_INSTALL_LOCATION}/lib)
-
-#add source
-file(GLOB PSR_SRC "${PROJECT_SOURCE_DIR}/Parser/libsrc/*.cc")
-file(GLOB HIS_SRC "${PROJECT_SOURCE_DIR}/Hist/libsrc/*.cc")
-file(GLOB UTL_SRC "${PROJECT_SOURCE_DIR}/Utils/libsrc/*.cc")
-file(GLOB DIM_SRC "${PROJECT_SOURCE_DIR}/DimRecv/libsrc/*.cc")
-file(GLOB PRO_SRC "${PROJECT_SOURCE_DIR}/cpythonprototype/libsrc/*.cc")
-
-if(WITH_REDIS)
-file(GLOB RIS_SRC "${PROJECT_SOURCE_DIR}/RedisIO/libsrc/*.cc")
-endif()
-
-
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${PSR_SRC} ${HIS_SRC} ${UTL_SRC}  ${PRO_SRC} ${DIM_SRC} ${RIS_SRC})
-
-if(WITH_REDIS)
-target_link_libraries(${PROJECT_NAME}  pthread  ${CMAKE_SOURCE_DIR}/extern/dim/linux/libdim.a
-                      ${EXTERNAL_INSTALL_LOCATION}/lib/libcpp_redis.a
-                      ${EXTERNAL_INSTALL_LOCATION}/lib/libtacopie.a)
-else()
-target_link_libraries(${PROJECT_NAME} pthread  ${CMAKE_SOURCE_DIR}/extern/dim/linux/libdim.a)
-
-endif()
-
-if(WITH_REDIS)
-add_dependencies(earthworm expkg_cpp_redis)
-endif()
-
-target_include_directories( ${PROJECT_NAME}
-    PUBLIC
-    ${PROJECT_SOURCE_DIR}/Utils/libinc
-    ${PROJECT_SOURCE_DIR}/Hist/libinc
-    ${PROJECT_SOURCE_DIR}/Parser/libinc
-    ${PROJECT_SOURCE_DIR}/cpythonprototype/libinc
-    ${PROJECT_SOURCE_DIR}/RedisIO/libinc
-    ${PROJECT_SOURCE_DIR}/DimRecv/libinc
-    ${CMAKE_SOURCE_DIR}/extern/dim/inc
-    ${CMAKE_SOURCE_DIR}/extern/
-    ${EXTERNAL_INSTALL_LOCATION}/include
-)
Index: rthworm/DimRecv/libinc/DAQInterface.hh
===================================================================
--- earthworm/DimRecv/libinc/DAQInterface.hh	(revision 82e3ac03b2993ee5dd25229a6f2b800faf9cb840)
+++ 	(revision )
@@ -1,86 +1,0 @@
-#ifndef DimRecv_DAQInterface_hh
-#define DimRecv_DAQInterface_hh
-
-// DimClient class
-//Inform the Server that this client would like the Server to execute an ExitHandler when it dies.
-// static setExitHandler ( char * serverName) ;
-// Instruct the Server to execute the virtual method errorHandler whenever the DIM server sees an error.
-// If no errorHandler is declared the DIM server prints an error message.
-// static addErrorHandler (DimErrorHandler *handler ) ;
-
-
-#include <dic.hxx>
-#include "UtilsException.hh"
-
-#include <iostream>
-#include <string>
-#include <future>
-#include <mutex>
-#include <vector>
-#include <chrono>
-#include <utility>      // std::pair
-
-#include "DaqTask.hh"
-
-// using tasktype = std::pair < std::future<unsigned>, std::vector<uint8_t> > ;
-
-class ErrorHandler : public DimErrorHandler
-{
-	void errorHandler(int severity, int code, char *msg)
-	{
-		int index = 0;
-		char **services;
-		if(code)
-    {
-
-    }
-		std::cout << severity << " " << msg << std::endl;
-		services = DimClient::getServerServices();
-		std::cout<< "from "<< DimClient::getServerName() << " services:" << std::endl;
-		while(services[index])
-		{
-			std::cout << services[index] << std::endl;
-			index++;
-		}
-	}
-public:
-	ErrorHandler() {DimClient::addErrorHandler(this);}
-};
-
-
-//This is the base class for decoding detector raw data.
-class DAQInterface: public DimClient {
-public:
-  DAQInterface(std::string daq_name="DAQ");
-  virtual ~DAQInterface();
-  void infoHandler() override;
-	void setActiveStatus(bool act) ;
-
-
-private:
-	//remove finished calculation in m_tasks to release resources,
-	//based on the Erase–remove idiom.
-	void houseKeeping();
-
-	// static std::vector<DAQInterface*> m_instances;
-
-  bool m_active;
-	//dim
-  ErrorHandler m_errhdl;
-  DimStampedInfo m_daq_data;
-
-  // task and info
-  std::vector<DaqTask> m_tasks;
-  int64_t m_num_trigger, m_received_byte, m_processed_byte;
-	int64_t m_processed_event;
-
-	// house keeping
-  std::mutex m_task_mutex, m_hist_mutex;
-  std::chrono::milliseconds m_houskpg_intvl_ms;
-	std::chrono::system_clock::time_point m_start_time;
-
-  std::thread m_hk_thread;
-
-};
-
-#endif
Index: rthworm/DimRecv/libinc/DaqTask.hh
===================================================================
--- earthworm/DimRecv/libinc/DaqTask.hh	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,38 +1,0 @@
-#ifndef DimRecv_DaqTask_hh
-#define DimRecv_DaqTask_hh
-
-#include <future>
-#include <vector>
-#include <mutex>
-
-class DaqTask {
-public:
-  DaqTask(uint8_t* begin, uint8_t* end);
-  virtual ~DaqTask();
-
-  // Move initialization
-  DaqTask(DaqTask&& other) ;
-  // Copy initialization
-  DaqTask(const DaqTask& other) ;
-  // Move assignment
-  DaqTask& operator = (DaqTask&& other) ;
-  // Copy assignment
-  DaqTask& operator = (const DaqTask& other) ;
-
-
-  uint64_t readyAndValid();
-  void start();
-  void setTime(int second, int ms);
-  void getTime(int &second, int &ms) const;
-
-
-private:
-  std::vector<uint8_t> m_data;
-  std::shared_future<uint64_t> m_future;
-  int m_time_s, m_time_ms; //since 1/1/1970, in seconds
-  mutable std::mutex m_run_mutex;
-
-  uint64_t run();
-};
-
-#endif
Index: rthworm/DimRecv/libinc/DimServer.hh
===================================================================
--- earthworm/DimRecv/libinc/DimServer.hh	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,32 +1,0 @@
-#ifndef DimRecv_DimServer_hh
-#define DimRecv_DimServer_hh
-
-#include <stdint.h>
-#include <vector>
-#include <future>
-#include <mutex>
-#include <unordered_map>
-#include "UtilsException.hh"
-
-
-//This is the base class for decoding detector raw data.
-class DimServer {
-
-public:
-  DimServer();
-  virtual ~DimServer();
-
-private:
-  unsigned int m_dimServerID;
-  static std::mutex m_mutex;
-  static unsigned dostuff();
-  static void eventDataArrived(void *tag, void *buf, int *size);
-  static std::vector< std::future<unsigned> > m_tasks;
-  static std::vector< std::vector<uint8_t> > m_data;
-
-};
-
-std::mutex DimServer::m_mutex;
-std::vector< std::future<unsigned> > DimServer::m_tasks;
-std::vector< std::vector<uint8_t> > DimServer::m_data;
-#endif
Index: rthworm/DimRecv/libinc/Retriver.hh
===================================================================
--- earthworm/DimRecv/libinc/Retriver.hh	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,32 +1,0 @@
-#ifndef DimRecv_Retriver_hh
-#define DimRecv_Retriver_hh
-
-#include <stdint.h>
-#include <vector>
-#include <future>
-#include <mutex>
-#include <unordered_map>
-#include "UtilsException.hh"
-
-
-//This is the base class for decoding detector raw data.
-class Retriver {
-
-public:
-  Retriver();
-  virtual ~Retriver();
-
-private:
-  unsigned int m_dimServerID;
-  static std::mutex m_mutex;
-  static unsigned dostuff();
-  static void eventDataArrived(void *tag, void *buf, int *size);
-  static std::vector< std::future<unsigned> > m_tasks;
-  static std::vector< std::vector<uint8_t> > m_data;
-
-};
-
-std::mutex Retriver::m_mutex;
-std::vector< std::future<unsigned> > Retriver::m_tasks;
-std::vector< std::vector<uint8_t> > Retriver::m_data;
-#endif
Index: rthworm/DimRecv/libsrc/DAQInterface.cc
===================================================================
--- earthworm/DimRecv/libsrc/DAQInterface.cc	(revision 82e3ac03b2993ee5dd25229a6f2b800faf9cb840)
+++ 	(revision )
@@ -1,109 +1,0 @@
-#include "DAQInterface.hh"
-#include <iostream>
-#include <algorithm>  // remove_if
-#include <time.h>
-#include <csignal>
-
-DAQInterface::DAQInterface(std::string daq_name)
-: DimClient(), m_active(true), m_errhdl()
-, m_daq_data(daq_name.c_str(),const_cast<char *>("daq"), this)
-, m_num_trigger(0), m_received_byte(0), m_processed_byte(0), m_processed_event(0)
-, m_houskpg_intvl_ms(1000), m_start_time(std::chrono::system_clock::now())
-{
-  addErrorHandler(&m_errhdl);
-  std::cout << "service name is " << daq_name << std::endl;
-  // setExitHandler("RUN_INFO");
-  m_hk_thread = std::thread(&DAQInterface::houseKeeping, this);
-}
-
-DAQInterface::~DAQInterface()
-{
-  if(m_hk_thread.joinable())
-    m_hk_thread.detach();
-}
-
-
-void DAQInterface::setActiveStatus(bool act)
-{
-  std::lock_guard<std::mutex> guard(m_task_mutex);
-  m_active=act;
-}
-
-void DAQInterface::infoHandler()
-{
-  std::lock_guard<std::mutex> guard(m_task_mutex);
-  // auto start = std::chrono::system_clock::now();
-
-  DimInfo *curr = getInfo(); // get current DimInfo address
-  if(curr == &m_daq_data && m_active)
-  {
-    //if(!m_num_trigger) return; //info handler will be triggered by constructor in dim v20
-    unsigned dsize  = curr->getSize();
-    m_received_byte += dsize;
-
-    uint8_t *data = static_cast<uint8_t*>(curr->getData());
-    std::vector<uint8_t> buf(data, data+dsize);
-
-    m_tasks.emplace_back( DaqTask(data, data+dsize));
-    m_tasks.back().setTime(curr->getTimestamp(), curr->getTimestampMillisecs());
-    m_tasks.back().start();
-  }
-  else   {
-    //fixme:log
-  }
-
-  m_num_trigger++;
-
-  // auto end = std::chrono::system_clock::now();
-  // std::chrono::duration<double> elapsed_seconds = end-start;
-  // std::time_t end_time = std::chrono::system_clock::to_time_t(end);
-  // std::cout << "elapsed time: " << elapsed_seconds.count()*1000 << "ms\n";
-
-}
-
-void DAQInterface::houseKeeping()
-{
-  std::cout <<"Starting house kepping ..." << std::endl;
-
-  while (1) {
-    std::this_thread::sleep_for(m_houskpg_intvl_ms);
-    if(m_tasks.empty()) continue;
-
-    std::lock_guard<std::mutex> guard(m_task_mutex);
-
-    unsigned processed =0;
-
-    auto newend = std::remove_if(m_tasks.begin(), m_tasks.end(),
-    [&](DaqTask &atask ) -> bool
-    {
-      uint64_t processed = atask.readyAndValid();
-      if(! processed )
-        return false;
-      else
-      {
-        int bytes = processed & 0xffffffff;
-        int events = (processed >> 32) & 0xffffffff;
-        m_processed_byte += bytes;
-        m_processed_event += events;
-        return true;
-      }
-    });
-
-    if(newend == m_tasks.end() ) continue;
-
-    unsigned deleted = m_tasks.end() - newend;
-    m_tasks.erase(newend, m_tasks.end());
-
-    std::cout <<  '\r' << "processed " << m_processed_byte/1024/1024  << "MB. Received "
-    << m_processed_byte/1024/1024 << "MB. Processed " <<  m_processed_byte*100./m_received_byte <<"%. ";
-
-    std::chrono::duration<double> elapsed_seconds = std::chrono::system_clock::now()-m_start_time;
-		double t = elapsed_seconds.count();
-
-    std::cout << "processed " << m_processed_event  << " events. Event rate "
-    <<  m_processed_event/t <<" /s. ";
-
-    std::cout  << m_tasks.size() << " tasks in queue, " << deleted << " finished tasks"
-    << std::flush << std::flush << std::flush;
-  }
-}
Index: rthworm/DimRecv/libsrc/DaqTask.cc
===================================================================
--- earthworm/DimRecv/libsrc/DaqTask.cc	(revision 82e3ac03b2993ee5dd25229a6f2b800faf9cb840)
+++ 	(revision )
@@ -1,122 +1,0 @@
-#include "DaqTask.hh"
-#include <thread>
-#include <chrono>
-#include <iostream>
-#include "PackageHe3.hh"
-
-DaqTask::DaqTask(uint8_t* begin, uint8_t* end)
-:m_data(begin, end), m_time_s(0), m_time_ms(0)
-{
-
-}
-
-DaqTask::~DaqTask()
-{
-
-}
-
-
-uint64_t DaqTask::readyAndValid()
-{
-  std::lock_guard<std::mutex> guard(m_run_mutex);
-
-  if(!m_future.valid())
-    return 0;
-  auto status = m_future.wait_for(std::chrono::milliseconds(0));
-  return status == std::future_status::ready ? m_future.get() : 0;
-}
-
-void DaqTask::start()
-{
-  std::lock_guard<std::mutex> guard(m_run_mutex);
-  m_future = std::async(std::launch::async, &DaqTask::run, this).share();
-}
-
-uint64_t DaqTask::run()
-{
-  // printf("running. m_data size %zu\n", m_data.size());
-
-  std::lock_guard<std::mutex> guard(m_run_mutex);
-
-  const uint8_t * abuf = m_data.data();
-  int event_cnt=0;
-  std::vector<Parser::HitInfo> hitinfo;
-  Parser::PackageHe3 he3(0.);
-
-  while(he3.readNextPackage(abuf, m_data.data()+m_data.size(), hitinfo))
-  {
-    event_cnt+=hitinfo.size();
-  }
-
-  // if(event_cnt)
-  // {
-  //   char fn[200];
-  //   sprintf(fn,"data/%d_%d.dat",m_time_s, m_time_ms);
-  //   FILE *datafile = fopen(fn, "wb");
-  //   fwrite (m_data.data() , sizeof(char), m_data.size(), datafile);
-  //   fclose(datafile);
-  //   // printf("%s, %d events\n", fn, event_cnt);
-  // }
-
-  uint64_t shiftedEvt = event_cnt*4294967296;  //shifting 32 bits to the higher order
-  return (uint64_t)m_data.size() +  shiftedEvt;
-}
-
-void DaqTask::setTime(int second, int ms)
-{
-  std::lock_guard<std::mutex> guard(m_run_mutex);
-  m_time_s = second;
-  m_time_ms = ms;
-}
-void DaqTask::getTime(int &second, int &ms) const
-{
-  std::lock_guard<std::mutex> guard(m_run_mutex);
-  second = m_time_s;
-  ms = m_time_ms;
-}
-
-// Move initialization
-DaqTask::DaqTask(DaqTask&& other) {
-  std::lock_guard<std::mutex> lock(other.m_run_mutex);
-  m_data = std::move(other.m_data);
-  m_future = std::move(other.m_future);
-  m_time_s = other.m_time_s;
-  m_time_ms = other.m_time_ms;
-  other.m_time_s = 0;
-  other.m_time_ms = 0;
-};
-
-// Copy initialization
-DaqTask::DaqTask(const DaqTask& other) {
-  std::lock_guard<std::mutex> lock(other.m_run_mutex);
-  m_data = other.m_data;
-  m_future = other.m_future;
-  m_time_s = other.m_time_s;
-  m_time_ms = other.m_time_ms;
-};
-
-// Move assignment
-DaqTask& DaqTask::operator = (DaqTask&& other) {
-  std::lock(m_run_mutex, other.m_run_mutex);
-  std::lock_guard<std::mutex> self_lock(m_run_mutex, std::adopt_lock);
-  std::lock_guard<std::mutex> other_lock(other.m_run_mutex, std::adopt_lock);
-  m_data = std::move(other.m_data);
-  m_future = std::move(other.m_future);
-  m_time_s = other.m_time_s;
-  m_time_ms = other.m_time_ms;
-  other.m_time_s = 0;
-  other.m_time_ms = 0;
-  return *this;
-};
-
-// Copy assignment
-DaqTask& DaqTask::operator = (const DaqTask& other) {
-  std::lock(m_run_mutex, other.m_run_mutex);
-  std::lock_guard<std::mutex> self_lock(m_run_mutex, std::adopt_lock);
-  std::lock_guard<std::mutex> other_lock(other.m_run_mutex, std::adopt_lock);
-  m_data = other.m_data;
-  m_future = other.m_future;
-  m_time_s = other.m_time_s;
-  m_time_ms = other.m_time_ms;
-  return *this;
-};
Index: rthworm/DimRecv/libsrc/DimServer.cc
===================================================================
--- earthworm/DimRecv/libsrc/DimServer.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,70 +1,0 @@
-#include "DimServer.hh"
-#ifdef __cplusplus
-extern "C"{
-#include "dic.h"
-}
-#endif
-
-
-DimServer::DimServer()
-:m_dimServerID(0)
-{
-  char* envNode = getenv("DIM_DNS_NODE");
-  char* envPort = getenv("DIM_DNS_PORT");
-  // if(envNode and envPort) {
-  // LogInfo << "DIM_DNS_NODE: " << envNode << std::endl;
-  // LogInfo << "DIM_DNS_PORT: " << envPort << std::endl;
-  static int no_link = -1;
-  //xx. https://dim.web.cern.ch/dimCdic.html#dic_info_service_stamped
-  // unsigned int dic_info_service_stamped (name, type, timeout, address, size, user_routine, tag, fill_address, fill_size)
-  // 1. char *name: service name, same name used by server when declaring the service.
-  // 2. int type;
-  //    Type of service, constants defined are: ONCE_ONLY, TIMED or MONITORED:
-  //    MONITORED: The client will receive the data when the server updates it (by calling dis_update_service()),
-  //  but also at regular intervals if the "timeout" parameter is different from 0. The "timeout" parameter can be set to 0 to receive data only on server update.
-  // 3. int timeout;
-  //   For a TIMED or MONITORED service "timeout" indicates the time interval the server should use to send new data, for ONCE_ONLY  services it indicates the time after
-  //   which the service is considered to have failed.
-  // 4. int *address;
-  //    Address of the buffer where to store the data when the service returns from the server. This parameter can be set to 0 and only the callback routine will be executed.
-  // 5. int size;
-  //    The size in bytes of the previous buffer (if specified).
-  // 6. void *user_routine;
-  //    The address of a routine to be executed when new data is returned from the server, the parameters of this routine will be specified later in this document.
-  //   Can be set to 0 if no callback routine is necessary.
-  // 7. long tag;
-  //    A parameter to be sent to the user_routine in order to identify the service that has completed.
-  // 8. int *fill_address;
-  //    Address of a buffer containing data to be stored in the service buffer or passed to the callback routine in case the service doesn't succeed.
-  // 9. int fill_size;
-  //    The size in bytes of the previous buffer.
-
-  // return unsigned int service_id;
-  // The service identifier, to be used when (if) releasing the service.
-
-  m_dimServerID = dic_info_service_stamped( "what is the name??", MONITORED, 0, 0, 0,
-   &DimServer::eventDataArrived, 1200, &no_link, 4 );
-  // ERROR_THROW("Failed to establish dim connection");
-  // else throw SniperException("DIM_DNS_NODE or DIM_DNS_PORT undefined!");
-}
-
-DimServer::~DimServer()
-{
-
-}
-
-unsigned DimServer::dostuff()
-{
-  return 1;
-}
-
-void DimServer::eventDataArrived(void *tag, void *buf, int *size )
-{
-  if( *static_cast<const int*>(tag) == 1200)
-  {
-    std::unique_lock<std::mutex> mlock(m_mutex);
-    m_data.emplace_back(std::vector<uint8_t> ( (uint8_t*)buf, (uint8_t*)buf+(*size) ) );
-    // std::future<unsigned> task = std::async(std::launch::async, DimServer::dostuff);
-    m_tasks.emplace_back(std::async(std::launch::async, DimServer::dostuff));
-  }
-}
Index: rthworm/DimRecv/libsrc/Retriver.cc
===================================================================
--- earthworm/DimRecv/libsrc/Retriver.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,70 +1,0 @@
-#include "Retriver.hh"
-#ifdef __cplusplus
-extern "C"{
-#include "dic.h"
-}
-#endif
-
-
-Retriver::Retriver()
-:m_dimServerID(0)
-{
-  char* envNode = getenv("DIM_DNS_NODE");
-  char* envPort = getenv("DIM_DNS_PORT");
-  // if(envNode and envPort) {
-  // LogInfo << "DIM_DNS_NODE: " << envNode << std::endl;
-  // LogInfo << "DIM_DNS_PORT: " << envPort << std::endl;
-  static int no_link = -1;
-  //xx. https://dim.web.cern.ch/dimCdic.html#dic_info_service_stamped
-  // unsigned int dic_info_service_stamped (name, type, timeout, address, size, user_routine, tag, fill_address, fill_size)
-  // 1. char *name: service name, same name used by server when declaring the service.
-  // 2. int type;
-  //    Type of service, constants defined are: ONCE_ONLY, TIMED or MONITORED:
-  //    MONITORED: The client will receive the data when the server updates it (by calling dis_update_service()),
-  //  but also at regular intervals if the "timeout" parameter is different from 0. The "timeout" parameter can be set to 0 to receive data only on server update.
-  // 3. int timeout;
-  //   For a TIMED or MONITORED service "timeout" indicates the time interval the server should use to send new data, for ONCE_ONLY  services it indicates the time after
-  //   which the service is considered to have failed.
-  // 4. int *address;
-  //    Address of the buffer where to store the data when the service returns from the server. This parameter can be set to 0 and only the callback routine will be executed.
-  // 5. int size;
-  //    The size in bytes of the previous buffer (if specified).
-  // 6. void *user_routine;
-  //    The address of a routine to be executed when new data is returned from the server, the parameters of this routine will be specified later in this document.
-  //   Can be set to 0 if no callback routine is necessary.
-  // 7. long tag;
-  //    A parameter to be sent to the user_routine in order to identify the service that has completed.
-  // 8. int *fill_address;
-  //    Address of a buffer containing data to be stored in the service buffer or passed to the callback routine in case the service doesn't succeed.
-  // 9. int fill_size;
-  //    The size in bytes of the previous buffer.
-
-  // return unsigned int service_id;
-  // The service identifier, to be used when (if) releasing the service.
-
-  m_dimServerID = dic_info_service_stamped( "what is the name??", MONITORED, 0, 0, 0,
-   &Retriver::eventDataArrived, 1200, &no_link, 4 );
-  // ERROR_THROW("Failed to establish dim connection");
-  // else throw SniperException("DIM_DNS_NODE or DIM_DNS_PORT undefined!");
-}
-
-Retriver::~Retriver()
-{
-
-}
-
-unsigned Retriver::dostuff()
-{
-  return 1;
-}
-
-void Retriver::eventDataArrived(void *tag, void *buf, int *size )
-{
-  if( *static_cast<const int*>(tag) == 1200)
-  {
-    std::unique_lock<std::mutex> mlock(m_mutex);
-    m_data.emplace_back(std::vector<uint8_t> ( (uint8_t*)buf, (uint8_t*)buf+(*size) ) );
-    // std::future<unsigned> task = std::async(std::launch::async, Retriver::dostuff);
-    m_tasks.emplace_back(std::async(std::launch::async, Retriver::dostuff));
-  }
-}
Index: rthworm/Hist/libinc/Hist2DMap.hh
===================================================================
--- earthworm/Hist/libinc/Hist2DMap.hh	(revision 45e614669efff721f23712f6214da63a10cba61a)
+++ 	(revision )
@@ -1,50 +1,0 @@
-#ifndef Histogram_Hist2DMap_hh
-#define Histogram_Hist2DMap_hh
-
-#include <map>
-#include <vector>
-#include <mutex>
-
-#include "NumpyHist2D.hh"
-
-// This class reads information from a full package.
-  class Hist2DMap {
-  public:
-    Hist2DMap(unsigned nbinsx, double xmin, double xmax,
-           unsigned nbinsy, double ymin, double ymax);
-    virtual ~Hist2DMap();
-
-    inline void fill(unsigned key, double x, double y);
-    void reset();
-    std::map<unsigned, NumpyHist2D* >::const_iterator getHistMapBegin() const;
-    std::map<unsigned, NumpyHist2D* >::const_iterator getHistMapEnd() const;
-
-  private:
-    std::mutex m_histmap_mutex;
-    std::map<unsigned, NumpyHist2D* > m_histmap;
-    unsigned m_xbin;
-    double m_xl, m_xu;
-    unsigned m_ybin;
-    double m_yl, m_yu;
-  };
-
-
-
-inline void Hist2DMap::fill(unsigned key, double x, double y)
-{
-  // Lock The Data structure
-  std::lock_guard<std::mutex> guard(m_histmap_mutex);
-
-  auto it_hist = m_histmap.find(key);
-  NumpyHist2D *histpt;
-  //create a new histogram for a new key
-  if(it_hist==m_histmap.end()) {
-    histpt = new NumpyHist2D(m_xbin, m_xl, m_xu, m_ybin, m_yl, m_yu);
-    m_histmap[key] = histpt;
-  }
-  else
-    histpt = it_hist->second;
-
-  histpt->fill(x,y);
-}
-#endif
Index: rthworm/Hist/libinc/NumpyHist1D.hh
===================================================================
--- earthworm/Hist/libinc/NumpyHist1D.hh	(revision c7ecea415c9e046d5a08db405078268967e91305)
+++ 	(revision )
@@ -1,26 +1,0 @@
-#ifndef NumpyHist1D_hh
-#define NumpyHist1D_hh
-
-#include "NumpyHistBase.hh"
-
-
-class NumpyHist1D : public NumpyHistBase {
-public:
-  explicit NumpyHist1D(unsigned nbins, double xmin, double xmax);
-  virtual ~NumpyHist1D();
-
-  unsigned dimension() const override { return 1; }  ;
-  void serialise(std::string &serialised) const override;
-
-  void fill(double val);
-  void fill(double val, double weight);
-
-private:
-  double m_binfactor;
-
-};
-
-
-
-
-#endif
Index: rthworm/Hist/libinc/NumpyHist2D.hh
===================================================================
--- earthworm/Hist/libinc/NumpyHist2D.hh	(revision c7ecea415c9e046d5a08db405078268967e91305)
+++ 	(revision )
@@ -1,32 +1,0 @@
-#ifndef NumpyHist2D_hh
-#define NumpyHist2D_hh
-
-#include "NumpyHistBase.hh"
-
-
-class NumpyHist2D : public NumpyHistBase {
-public:
-
-  explicit NumpyHist2D(unsigned nxbins, double xmin, double xmax,
-              unsigned nybins, double ymin, double ymax);
-  virtual ~NumpyHist2D();
-
-  unsigned dimension() const override { return 2; }  ;
-  void serialise(std::string &serialised) const override;
-
-  void fill(double xval, double yval);
-  void fill(double xval, double yval, double weight);
-
-private:
-  double m_xbinfactor, m_ybinfactor;
-  double m_ymin;
-  double m_ymax;
-  uint32_t m_xnbins, m_ynbins;
-
-
-};
-
-
-
-
-#endif
Index: rthworm/Hist/libinc/NumpyHistBase.hh
===================================================================
--- earthworm/Hist/libinc/NumpyHistBase.hh	(revision 0b8d7c8abff6357f62f38cf26cede6ed240fa588)
+++ 	(revision )
@@ -1,57 +1,0 @@
-#ifndef NumpyHistBase_hh
-#define NumpyHistBase_hh
-
-#include <string>
-#include <cassert>
-#include <vector>
-#include <stdexcept>
-#include <mutex>
-
-class NumpyHistBase {
-public:
-  explicit NumpyHistBase(unsigned nbins);
-  virtual ~NumpyHistBase();
-
-  double getXMin() const {return m_xmin;}
-  double getXMax() const {return m_xmax;}
-  double getIntegral() const {return m_sumW;};
-  double getOverflow() const {return m_overflow;};
-  double getUnderflow() const {return m_underflow;};
-  double getMinFilled() const {return m_minfilled;};
-  double getMaxFilled() const {return m_maxfilled;};
-  double getNBins() const {return m_nbins;};
-
-  void scale(double scalefact);
-  void reset();
-  void save(const std::string &filename) const;
-
-  virtual unsigned dimension() const = 0;
-  virtual void serialise(std::string &serialised) const = 0;
-
-protected:
-  void serialise_numpy(const std::vector<uint64_t> &shape, std::string &serialised) const;
-  mutable std::mutex m_hist_mutex;
-  std::vector<double> m_data;
-  double m_xmin;
-  double m_xmax;
-  double m_sumW;
-  double m_underflow;
-  double m_overflow;
-  double m_minfilled;
-  double m_maxfilled;
-  uint32_t m_nbins;
-
-private:
-  //Copy/assignment are forbidden:
-  // Move initialization
-  NumpyHistBase(NumpyHistBase&& other) = delete;
-  // Copy initialization
-  NumpyHistBase(const NumpyHistBase& other) = delete;
-  // Move assignment
-  NumpyHistBase& operator = (NumpyHistBase&& other) = delete;
-  // Copy assignment
-  NumpyHistBase& operator = (const NumpyHistBase& other) = delete;
-
-};
-
-#endif
Index: rthworm/Hist/libsrc/Hist2DMap.cc
===================================================================
--- earthworm/Hist/libsrc/Hist2DMap.cc	(revision 45e614669efff721f23712f6214da63a10cba61a)
+++ 	(revision )
@@ -1,34 +1,0 @@
-#include "Hist2DMap.hh"
-#include "UtilsException.hh"
-#include "NumpyHist2D.hh"
-
-Hist2DMap::Hist2DMap(unsigned nbinx, double xmin, double xmax,
-       unsigned nbiny, double ymin, double ymax)
-: m_xbin(nbinx), m_xl(xmin), m_xu(xmax), m_ybin(nbiny), m_yl(ymin), m_yu(ymax)
-{
-}
-
-Hist2DMap::~Hist2DMap()
-{
-  auto it = m_histmap.begin();
-  for ( ; it != m_histmap.end(); ++it)
-     delete it->second;
-}
-
-void Hist2DMap::reset()
-{
-  auto it = m_histmap.begin();
-  for ( ; it != m_histmap.end(); ++it)
-     it->second->reset();
-}
-
-
-std::map<unsigned, NumpyHist2D* >::const_iterator Hist2DMap::getHistMapBegin() const
-{
-  return m_histmap.begin();
-}
-
-std::map<unsigned, NumpyHist2D* >::const_iterator Hist2DMap::getHistMapEnd() const
-{
-  return m_histmap.end();
-}
Index: rthworm/Hist/libsrc/NumpyHist1D.cc
===================================================================
--- earthworm/Hist/libsrc/NumpyHist1D.cc	(revision 0b8d7c8abff6357f62f38cf26cede6ed240fa588)
+++ 	(revision )
@@ -1,55 +1,0 @@
-#include "NumpyHist1D.hh"
-#include <cmath>
-#include <vector>
-
-NumpyHist1D::NumpyHist1D(unsigned nbins, double xmin, double xmax)
-:NumpyHistBase(nbins), m_binfactor(nbins/(xmax-xmin))
-{
-  m_xmin=xmin, m_xmax=xmax, m_nbins=nbins;
-}
-
-NumpyHist1D::~NumpyHist1D()
-{
-}
-
-
-void NumpyHist1D::serialise(std::string &serialised) const
-{
-  std::lock_guard<std::mutex> guard(m_hist_mutex);
-  serialise_numpy(std::vector<uint64_t>{m_nbins}, serialised);
-}
-
-//Normal filling:
-void NumpyHist1D::fill(double val)
-{
-  std::lock_guard<std::mutex> guard(m_hist_mutex);
-
-  if(val<m_xmin) {
-    m_underflow++;
-    return;
-  }
-  else if(val>m_xmax) {
-    m_overflow++;
-    return;
-  }
-
-  unsigned i = floor((val-m_xmin)*m_binfactor);
-  ++m_data[i];
-}
-
-void NumpyHist1D::fill(double val, double w)
-{
-  std::lock_guard<std::mutex> guard(m_hist_mutex);
-
-  if(val<m_xmin) {
-    m_underflow += w;
-    return;
-  }
-  else if(val>m_xmax) {
-    m_overflow += w;
-    return;
-  }
-
-  unsigned i = floor((val-m_xmin)*m_binfactor);
-  m_data[i] += w;
-}
Index: rthworm/Hist/libsrc/NumpyHist2D.cc
===================================================================
--- earthworm/Hist/libsrc/NumpyHist2D.cc	(revision 0b8d7c8abff6357f62f38cf26cede6ed240fa588)
+++ 	(revision )
@@ -1,63 +1,0 @@
-#include "NumpyHist2D.hh"
-#include <cmath>
-#include <vector>
-#include <iostream>
-
-NumpyHist2D::NumpyHist2D(unsigned xnbins, double xmin, double xmax,
-                         unsigned ynbins, double ymin, double ymax)
-:NumpyHistBase(xnbins*ynbins), m_xbinfactor(xnbins/(xmax-xmin)),
-m_ybinfactor(ynbins/(ymax-ymin))
-{
-  m_xmin=xmin, m_xmax=xmax, m_xnbins=xnbins;
-  m_ymin=ymin, m_ymax=ymax, m_ynbins=ynbins;
-  m_nbins = m_xnbins * m_ynbins;
-
-  // std::invalid_argument("data can not be shaped by the given shape vector");
-
-}
-
-NumpyHist2D::~NumpyHist2D()
-{
-}
-
-void NumpyHist2D::serialise(std::string &serialised) const
-{
-  std::lock_guard<std::mutex> guard(m_hist_mutex);
-
-  serialise_numpy(std::vector<uint64_t>{m_xnbins, m_ynbins}, serialised);
-}
-
-//Normal filling:
-void NumpyHist2D::fill(double xval, double yval)
-{
-  std::lock_guard<std::mutex> guard(m_hist_mutex);
-
-  if(xval<m_xmin ||  yval<m_ymin) {
-    m_underflow++;
-    return;
-  }
-  else if(xval>m_xmax || yval>m_ymax) {
-    m_overflow++;
-    return;
-  }
-  unsigned ix = floor((xval-m_xmin)*m_xbinfactor);
-  unsigned iy = floor((yval-m_ymin)*m_ybinfactor);
-  ++m_data[ix*m_ynbins + iy];
-}
-
-void NumpyHist2D::fill(double xval, double yval, double w)
-{
-  std::lock_guard<std::mutex> guard(m_hist_mutex);
-
-  if(xval<m_xmin ||  yval<m_ymin) {
-    m_underflow+=w;
-    return;
-  }
-  else if(xval>m_xmax || yval>m_ymax) {
-    m_overflow+=w;
-    return;
-  }
-  unsigned ix = floor((xval-m_xmin)*m_xbinfactor);
-  unsigned iy = floor((yval-m_ymin)*m_ybinfactor);
-  m_data[iy*m_xnbins + ix]+=w;
-}
Index: rthworm/Hist/libsrc/NumpyHistBase.cc
===================================================================
--- earthworm/Hist/libsrc/NumpyHistBase.cc	(revision 0b8d7c8abff6357f62f38cf26cede6ed240fa588)
+++ 	(revision )
@@ -1,63 +1,0 @@
-#include "NumpyHistBase.hh"
-#include "RedisNumpy.hh"
-#include <stdexcept>
-#include <fstream>
-
-NumpyHistBase::NumpyHistBase(unsigned nbin)
-: m_data(nbin,0.), m_xmin(0), m_xmax(0), m_sumW(0), m_underflow(0),
- m_overflow(0),m_minfilled(0), m_maxfilled(0), m_nbins(0)
-{
-
-}
-
-NumpyHistBase::~NumpyHistBase()
-{
-}
-
-void NumpyHistBase::save(const std::string &filename) const
-{
-  std::lock_guard<std::mutex> guard(m_hist_mutex);
-
-  std::string bdata;
-  serialise(bdata);
-  std::ofstream outfile(filename, std::ofstream::binary);
-  outfile << bdata;
-  outfile.close();
-}
-
-
-void NumpyHistBase::serialise_numpy(const std::vector<uint64_t> &shape, std::string &serialise) const
-{
-  std::lock_guard<std::mutex> guard(m_hist_mutex);
-
-  uint64_t elementnum=1;
-  for(auto v:shape)
-    elementnum *= v;
-
-  if(elementnum!=m_nbins)
-    std::invalid_argument("data can not be shaped by the given shape vector");
-
-  RedisNumpy nvt;
-  nvt.makeNumpyArr(m_data, RedisNumpy::data_type::f8,
-                   shape, serialise);
-}
-
-void NumpyHistBase::scale(double scalefact)
-{
-  std::lock_guard<std::mutex> guard(m_hist_mutex);
-
-  for(unsigned i=0;i<m_nbins;i++)
-    m_data[i] *= scalefact;
-}
-
-void NumpyHistBase::reset()
-{
-  std::lock_guard<std::mutex> guard(m_hist_mutex);
-
-  std::fill(m_data.begin(), m_data.begin()+m_nbins, 0.);
-  m_sumW = 0.;
-  m_underflow = 0.;
-  m_overflow = 0.;
-  m_minfilled = 0.;
-  m_maxfilled = 0.;
-}
Index: rthworm/Parser/libinc/PackageHe3.hh
===================================================================
--- earthworm/Parser/libinc/PackageHe3.hh	(revision 37135bf5257bd0aee24a8f389b10bfffabb6e3a3)
+++ 	(revision )
@@ -1,44 +1,0 @@
-#ifndef Parser_PackageHe3_hh
-#define Parser_PackageHe3_hh
-
-#include <map>
-#include <mutex>
-
-#include "ParserHe3.hh"
-
-class Hist2DMap;
-
-//This class reads information from a full package.
-namespace Parser {
-  struct HitInfo {
-    double pos;
-    double t;
-    double chargesum;
-    uint32_t hit_t0;
-    uint8_t tube_id;
-    HitInfo(): pos(0.),t(0.),chargesum(0.),hit_t0(0), tube_id(0) {}
-    HitInfo(double position, double time, double chargesum,uint32_t t0, uint8_t tube)
-      : pos(position),t(time),chargesum(chargesum), hit_t0(t0), tube_id(tube) {}
-  };
-
-  //Reflectormetor uses He3 detector of 300mm length.
-  //time stamp should be divided by 80 to convert to micro-second
-  //fixme :  put m_detector_half_length and m_tof2us elsewhere
-  class EXPORT_SYMBOL PackageHe3: public ParserHe3 {
-  public:
-    PackageHe3(double threshold, double hvlength=150., double tofscale=1./80);
-
-    ~PackageHe3() override;
-    //fixme: hit position is scale by a constant 150
-    //returns false when reach the end of the data stream
-    bool readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end, std::vector<HitInfo>& hitinfo) const;
-    bool readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end, Hist2DMap &hitmap) const;
-
-    double getChargeThreshold() const;
-    void setChargeThreshold(double charge);
-  private:
-    std::mutex m_mutex;
-    double m_charge_threshold, m_detector_half_length, m_tof2us;
-  };
-}
-#endif
Index: rthworm/Parser/libinc/PackageMWPC.hh
===================================================================
--- earthworm/Parser/libinc/PackageMWPC.hh	(revision 82e3ac03b2993ee5dd25229a6f2b800faf9cb840)
+++ 	(revision )
@@ -1,52 +1,0 @@
-#ifndef Parser_PackageMWPC_hh
-#define Parser_PackageMWPC_hh
-
-#include <map>
-#include "ParserMWPC.hh"
-#include <fstream>
-
-class Hist2DMap;
-
-class NumpyHist1D;
-
-
-//This class reads information from a full package.
-namespace Parser {
-  //fixme :  put m_detector_half_length and m_tof2us elsewhere
-  class EXPORT_SYMBOL PackageMWPC: public ParserMWPC {
-  public:
-    PackageMWPC(double threshold, double time_window );
-    ~PackageMWPC() override;
-
-    //returns false when reach the end of the data stream
-    bool readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end,
-                         Hist2DMap &hitmap,
-                         NumpyHist1D &qhist) const;
-    void write(std::ofstream &file, const char *filename);
-    void print() const;
-
-    double getChargeThreshold() const;
-    void setChargeThreshold(double charge);
-
-  private:
-    double m_charge_threshold;
-    uint64_t m_time_window;
-    mutable uint32_t m_last_t0;
-    mutable std::multimap<uint32_t,uint32_t> m_tof_cq_map; //<TOF, chanel+Q>
-    mutable std::vector<uint64_t> m_hit;
-
-    void pushbackRawData(unsigned eventmapnum, const uint8_t *&pt) const;
-
-    inline void getChannelCharge(uint32_t in, uint8_t& channel, uint16_t& charge ) const;
-
-  };
-
-  inline void Parser::PackageMWPC::getChannelCharge(uint32_t in, uint8_t& channel, uint16_t& charge) const
-  {
-    channel = in>>24;
-    uint16_t baseline = ((in>>12)&MASK_12) ; //fixme the document states the baseline value is the combination of 8 samples!?
-    uint16_t chage = (in&MASK_12) ;
-    charge = chage>baseline ? chage-baseline: 0  ; //fixme emit warning if overflowed
-  }
-}
-#endif
Index: rthworm/Parser/libinc/PackageMWPCold.hh
===================================================================
--- earthworm/Parser/libinc/PackageMWPCold.hh	(revision 82e3ac03b2993ee5dd25229a6f2b800faf9cb840)
+++ 	(revision )
@@ -1,50 +1,0 @@
-#ifndef Parser_PackageMWPCold_hh
-#define Parser_PackageMWPCold_hh
-
-#include <map>
-#include "ParserMWPC.hh"
-#include <fstream>
-
-  class Hist2DMap;
-  class NumpyHist1D;
-
-
-//This class reads information from a full package.
-namespace Parser {
-  //fixme :  put m_detector_half_length and m_tof2us elsewhere
-  class EXPORT_SYMBOL PackageMWPCold: public ParserMWPC {
-  public:
-    PackageMWPCold(double threshold, double time_window );
-    ~PackageMWPCold() override;
-
-    //returns false when reach the end of the data stream
-    bool readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end,
-                         Hist2DMap &hitmap,
-                         NumpyHist1D &qhist) const;
-    void write(std::ofstream &file, const char *filename);
-    void print() const;
-
-    double getChargeThreshold() const;
-    void setChargeThreshold(double charge);
-
-  private:
-    double m_charge_threshold;
-    uint64_t m_time_window;
-    mutable uint32_t m_last_t0;
-    mutable std::multimap<uint32_t,uint32_t> m_tof_cq_map; //<TOF, chanel+Q>
-
-    void pushbackRawData(unsigned eventmapnum, const uint8_t *&pt) const;
-
-    inline void getChannelCharge(uint32_t in, uint8_t& channel, uint16_t& charge ) const;
-
-  };
-
-  inline void Parser::PackageMWPCold::getChannelCharge(uint32_t in, uint8_t& channel, uint16_t& charge) const
-  {
-    channel = in>>24;
-    uint16_t baseline = ((in>>12)&MASK_12) ; //fixme the document states the baseline value is the combination of 8 samples!?
-    uint16_t chage = (in&MASK_12) ;
-    charge = chage>baseline ? chage-baseline: 0  ; //fixme emit warning if overflowed
-  }
-}
-#endif
Index: rthworm/Parser/libinc/ParserBase.hh
===================================================================
--- earthworm/Parser/libinc/ParserBase.hh	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,59 +1,0 @@
-#ifndef Parser_ParserBase_hh
-#define Parser_ParserBase_hh
-
-#include <stdint.h>
-#include <vector>
-#include <string>
-#include "ctypes_api.hh"
-
-//This is the base class for decoding detector raw data.
-//fixme change to stream based class
-namespace EXPORT_SYMBOL Parser {
-  class ParserBase {
-  public:
-    ParserBase();
-    virtual ~ParserBase();
-
-    //read unsigned 32-bit integer from buffer
-    void read_uint32(const uint8_t*& pt, uint32_t &u32) const;
-    //slow, use with care
-    inline void read_uint32_many(const uint8_t*& pt, std::vector<uint32_t> &u32_vec, unsigned num=4) const;
-
-    //find the end position of a package
-    //Function returns true if the end position of a valid package is found
-    virtual bool findEnd(const uint8_t* pt, const uint8_t*& end) const = 0 ;
-
-    //sanity check. Slow, use with care. fixme: validation should be more detailed
-    virtual bool is_valid(const uint8_t* pt) const = 0 ;
-
-    //search for next valid package. Slow, use with care.
-    virtual bool findNextPackage(const uint8_t*& start, const uint8_t * const stop, const uint8_t*& pkgend, uint64_t &offset) const ;
-
-  public:
-    enum BIT_MASK: uint32_t {
-      MASK_4  = 0XF,
-      MASK_6  = 0X3F,
-      MASK_8  = 0XFF,
-      MASK_12  = 0XFFF,
-      MASK_14  = 0X3FFF,
-      MASK_16 = 0XFFFF,
-      MASK_20 = 0xFFFFF,
-      MASK_24 = 0XFFFFFF,
-      MASK_28 = 0XFFFFFFF
-    };
-
-  };
-
-  inline void Parser::ParserBase::read_uint32(const uint8_t*& pt, uint32_t &u32) const
-  {
-    //endian free
-    //Fixme: could be optimised after profiling
-    u32 = (*pt)<<24 ;
-    u32 += (*(++pt))<<16 ;
-    u32 += (*(++pt))<<8 ;
-    u32 += *(++pt) ;
-    pt++;
-  }
-
-}
-#endif
Index: rthworm/Parser/libinc/ParserHe3.hh
===================================================================
--- earthworm/Parser/libinc/ParserHe3.hh	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,69 +1,0 @@
-#ifndef Parser_ParserHe3_hh
-#define Parser_ParserHe3_hh
-
-#include <stdint.h>
-#include <vector>
-
-#include "ParserBase.hh"
-
-//This class reads segments of raw package from He3 detector.
-namespace Parser {
-
-  class EXPORT_SYMBOL ParserHe3: public ParserBase {
-  public:
-    struct Header {
-      uint8_t flag; //0xFA
-      uint8_t instrument;
-      uint8_t detector_type;
-      uint8_t module;
-      uint8_t opt_mode;
-      uint8_t fre_div_mode;
-      uint8_t data_ver;
-      uint8_t data_type;
-    };
-
-    struct Info {
-      uint32_t t0_count;
-      uint16_t hit_cnt;
-      uint16_t sample_num_n; //sampled number of points on the waveform
-      uint16_t sample_num_bl; //sampled number of points on the baseline
-      Info() : t0_count(), hit_cnt(), sample_num_n(), sample_num_bl() {}
-    };
-
-    struct Hit {
-      uint32_t time;
-      uint32_t upper_baseline;
-      uint32_t lower_baseline;
-      uint16_t upper_charge;
-      uint16_t lower_charge;
-      uint8_t tube_id;
-    };
-
-
-
-   enum FLAG: uint32_t {
-     DATA_START  = 0XE,
-     PACK_START  = 0xFA,
-     PACK_END  = 0XFB
-   };
-
-
-  public:
-    ParserHe3();
-    virtual ~ParserHe3();
-    void readHeader(const uint8_t*& pt, const Header *header) const;
-    void readInfo(const uint8_t*& pt, Info &info) const;
-    //input pt remain untouched
-    void printInfo(const uint8_t* pt) const;
-
-    //it_payload should point at the data flag 0xE, otherwise time is set to zero.
-    void readHit( const uint8_t*& pt_payload, Hit &hit) const ;
-
-    bool findEnd(const uint8_t* pt, const uint8_t*& end) const override;
-    bool is_valid(const uint8_t* pt) const override;
-
-  private:
-
-  };
-}
-#endif
Index: rthworm/Parser/libinc/ParserMWPC.hh
===================================================================
--- earthworm/Parser/libinc/ParserMWPC.hh	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,42 +1,0 @@
-#ifndef Parser_ParserMWPC_hh
-#define Parser_ParserMWPC_hh
-
-#include <stdint.h>
-#include <vector>
-
-#include "ParserBase.hh"
-
-//This class reads segments of raw package from He3 detector.
-namespace Parser {
-
-  class EXPORT_SYMBOL ParserMWPC: public ParserBase {
-  public:
-    struct MWPCHeader {
-      uint8_t instrment, detector_type, opt_mode, freq_div_mode, data_version, data_type;
-      uint8_t model_status[6];
-      uint32_t model_bycnt[6];
-      uint32_t t0cnt, payload_bycnt,map_num;
-    };
-
-
-
-   enum MWPCFLAG: uint32_t {
-     MWPC_HIT  = 0xAA,
-     MWPC_SIG  = 0XEE1234EE
-   };
-
-
-  public:
-    ParserMWPC();
-    ~ParserMWPC() override;
-    void readHeader(const uint8_t*& pt, MWPCHeader& header) const;
-    void readHit();
-
-    bool findEnd(const uint8_t* pt, const uint8_t*& end) const override;
-    bool is_valid(const uint8_t* pt) const override;
-
-  private:
-
-  };
-}
-#endif
Index: rthworm/Parser/libinc/ParserUtils.hh
===================================================================
--- earthworm/Parser/libinc/ParserUtils.hh	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,8 +1,0 @@
-#ifndef Parser_Utils_hh
-#define Parser_Utils_hh
-
-namespace Parser {
-  int is_little_endian();
-}
-
-#endif
Index: rthworm/Parser/libsrc/PackageHe3.cc
===================================================================
--- earthworm/Parser/libsrc/PackageHe3.cc	(revision 37135bf5257bd0aee24a8f389b10bfffabb6e3a3)
+++ 	(revision )
@@ -1,107 +1,0 @@
-#include "PackageHe3.hh"
-#include "UtilsException.hh"
-#include "Hist2DMap.hh"
-
-Parser::PackageHe3::PackageHe3(double threshold, double hvlength,double tofscale)
-:ParserHe3(), m_charge_threshold(threshold),
-m_detector_half_length(hvlength),m_tof2us(tofscale)
-{
-
-}
-
-Parser::PackageHe3::~PackageHe3()
-{
-}
-
-double Parser::PackageHe3::getChargeThreshold() const
-{
-  return m_charge_threshold;
-}
-void Parser::PackageHe3::setChargeThreshold(double charge)
-{
-  std::lock_guard<std::mutex> guard(m_mutex);
-  m_charge_threshold = charge;
-}
-
-
-bool Parser::PackageHe3::readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end, Hist2DMap &hitmap) const
-{
-  const uint8_t *package_end;
-  uint64_t offset = 0;
-  if(!findNextPackage(pt, stream_end, package_end, offset))
-    return false;
-
-  const Parser::ParserHe3::Header *header = new Parser::ParserHe3::Header();
-  readHeader(pt, header);
-  delete header;
-
-  Parser::ParserHe3::Info info;
-  readInfo(pt, info);
-  double baseline_factor = 1./info.sample_num_bl;
-
-  Parser::ParserHe3::Hit hit ;
-
-  //the next while loop breaks when pt==package_end-8
-  while (pt != package_end-8) {
-    error_assert(pt<package_end-8); //shouldn't really happen
-    readHit(pt,hit);
-    double upper = hit.upper_charge - hit.upper_baseline*baseline_factor;
-    double lower = hit.lower_charge - hit.lower_baseline*baseline_factor;
-    double tot = upper + lower;
-    //fixme: why tot is sometimes zero?
-    if(!tot || tot<m_charge_threshold)
-      continue;
-    else {
-      hitmap.fill(hit.tube_id, hit.time*m_tof2us ,m_detector_half_length*( 1 + (upper-lower)/tot ) );
-
-        // printf("pos %g, time stamp %d , tube_id %d\n", 150.*( 1 + (upper-lower)/tot ) ,hit.time, hit.tube_id );
-      }
-  }
-  pt = package_end;
-
-  //printf("left %ld, package_end %p, stream_end %p\n", stream_end-package_end, package_end, stream_end);
-  return package_end==stream_end?false:true;
-}
-
-
-bool Parser::PackageHe3::readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end, std::vector<HitInfo>& hitinfo) const
-{
-  const uint8_t *package_end;
-  uint64_t offset=0;
-
-  if(!findNextPackage(pt, stream_end, package_end, offset))
-    return false;
-
-  const Parser::ParserHe3::Header *header = new Parser::ParserHe3::Header();
-  readHeader(pt, header);
-  delete header;
-
-  Parser::ParserHe3::Info info;
-  readInfo(pt, info);
-  double baseline_factor = 1./info.sample_num_bl;
-
-  Parser::ParserHe3::Hit hit ;
-  std::vector<HitInfo> temp;
-  std::swap(temp,hitinfo);
-  hitinfo.reserve(info.hit_cnt);
-
-  //the next while loop breaks when pt==package_end-8
-  while (pt != package_end-8) {
-    error_assert(pt<package_end-8); //shouldn't really happen
-    readHit(pt,hit);
-    double upper = hit.upper_charge - hit.upper_baseline*baseline_factor;
-    double lower = hit.lower_charge - hit.lower_baseline*baseline_factor;
-    double tot = upper + lower;
-    if(!tot || tot<m_charge_threshold)
-      continue;
-    else {
-        hitinfo.push_back(HitInfo( m_detector_half_length*( 1 + (upper-lower)/tot ) ,
-        hit.time*m_tof2us,tot, info.t0_count, hit.tube_id));
-        // printf("pos %g, time stamp %d , tube_id %d\n", 150.*( 1 + (upper-lower)/tot ) ,hit.time, hit.tube_id );
-      }
-  }
-  pt = package_end;
-
-  //printf("left %ld, package_end %p, stream_end %p\n", stream_end-package_end, package_end, stream_end);
-  return package_end==stream_end?false:true;
-}
Index: rthworm/Parser/libsrc/PackageMWPC.cc
===================================================================
--- earthworm/Parser/libsrc/PackageMWPC.cc	(revision 82e3ac03b2993ee5dd25229a6f2b800faf9cb840)
+++ 	(revision )
@@ -1,168 +1,0 @@
-#include "PackageMWPC.hh"
-#include <iostream>       // std::cout
-#include <bitset>
-#include <algorithm>
-#include <cmath>
-
-#include "UtilsException.hh"
-#include "Hist2DMap.hh"
-#include "NumpyHist1D.hh"
-
-Parser::PackageMWPC::PackageMWPC(double threshold, double time_window)
-:ParserMWPC(), m_charge_threshold(threshold), m_time_window(time_window), m_last_t0(0)
-{
-}
-
-Parser::PackageMWPC::~PackageMWPC()
-{
-}
-unsigned eventcnt = 0;
-
-bool Parser::PackageMWPC::readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end,
-  Hist2DMap &hitmap, NumpyHist1D &qhist) const
-{
-  //a new package eventDataArrived
-  //we first check if this package and the data in buffer are from the same T0 peroid
-  //if yes, accumulate package data into the buffer
-  //otherwise, process the old buffer and clean it for this package
-
-  const uint8_t *package_end;
-  uint64_t offset=0;
-  if(!findNextPackage(pt, stream_end, package_end, offset))
-    return false;
-
-  //parsing raw data
-  ParserMWPC::MWPCHeader header;
-  readHeader(pt, header);
-  unsigned mapnum = header.map_num;
-  //x chanel 50, spacing 4mm, y channel 94, spacing 2.2mm
-  // std::bitset<50> x; //In standard C++, bits are initialized with zeros
-  // std::bitset<94> y;
-
-  if(!m_last_t0)
-    m_last_t0 = header.t0cnt;
-
-  //if this is the start of a new t0 signal
-  //process whatever in the map and get ready to restart the accumulation
-  if(header.t0cnt!=m_last_t0 && !m_hit.empty())
-  {
-    //the arrived new package belongs to a subconsequente T0 event, so the old
-    // data in the buffer should be sorted and analysed
-    std::sort(m_hit.begin(), m_hit.end());
-
-    uint8_t chnl = 0;
-    uint16_t Q = 0;
-    unsigned chargeSum = 0;
-    uint32_t eventSz(0), accu_x(0), accu_y(0), accu_xw(0), accu_yw(0);
-    uint64_t hittof=m_hit.front(); //initialize for the loop
-
-    uint64_t realtwindow = m_time_window<<32;
-
-    for(auto ahit: m_hit)
-    {
-      getChannelCharge( ahit, chnl, Q);
-      if(Q<m_charge_threshold)
-        continue;
-
-      if(ahit > hittof + realtwindow ) // || it==last_item_in_map??
-      {
-        //this hit belongs to the next event
-        eventcnt++;
-
-        //fill histograms only if both x and y data are available
-        if(accu_x*accu_y)
-        {
-          //fill charge hist
-          qhist.fill(chargeSum);
-          //fill pixel histogram
-          float x = accu_xw/float(accu_x);
-          float y = accu_yw/float(accu_y);
-          hitmap.fill( 0, hittof, std::round(x) + std::round(y)*50 );
-          printf("%g;%g;%g;%d;  %d\n", y*2.2, (50-x)*4., hittof/40.0, header.t0cnt-1, eventcnt-1 );
-          assert(chargeSum==accu_x+accu_y);
-        }
-      }
-      else
-      {
-        //accumulate
-        // printf("%d %d %d %d\n",eventcnt, it->first, chnl, Q);
-        eventSz++;
-        chnl<51 ? accu_xw += chnl*Q : accu_yw += (chnl-50)*Q;
-        chnl<51 ? accu_x += Q : accu_y += Q;
-        chargeSum += Q;
-      }
-
-    }
-
-    std::vector<uint64_t>  temp; //release memory
-    m_hit.swap(temp);
-    m_last_t0=header.t0cnt;
-  }
-
-  //Sorting hit data
-  // printf("*********%d maps************\n",header.map_num);
-
-  printf("left %ld, package_end %p, stream_end %p\n", stream_end-package_end, package_end, stream_end);
-  pushbackRawData(header.map_num, package_end);
-  return package_end==stream_end?false:true;
-}
-
-
-void Parser::PackageMWPC::pushbackRawData(unsigned eventmapnum, const uint8_t *&pt) const
-{
-  uint32_t temp32=0;
-
-  for(unsigned imap=0;imap<eventmapnum;imap++)
-  {
-    error_assert(*pt == 0xAA);
-    uint32_t t = 0;
-    read_uint32(pt,t);
-    t &= MASK_24;
-    // printf("TdataID %d\n", t);
-    uint32_t eventNum = 0;
-    read_uint32(pt,eventNum);
-
-    // printf("map %d, event number %d \n",imap, eventNum);
-    for(unsigned ievt=0;ievt<eventNum;ievt++)
-    {
-      uint8_t ch = *(pt);
-
-      read_uint32(pt, temp32);
-      //error_assert(ch==*(pt));
-      uint32_t t_hi_res = temp32&MASK_24;
-
-      read_uint32(pt, temp32);
-      //fixme: there is a bug in DAQ, the secend channel num sometimes are left zero
-      temp32 = (temp32&MASK_24) + (ch<<24);
-
-      m_hit.push_back(( ((uint64_t) t_hi_res) <<32) + temp32);
-      printf("ch %d, time stamp %d\n", temp32, t_hi_res);
-    }
-  }
-
-
-}
-
-void Parser::PackageMWPC::write(std::ofstream &file, const char *filename)
-{
-  file.open(filename);
-  auto it=m_tof_cq_map.begin();
-  for(;it!=m_tof_cq_map.end();++it)
-  {
-    uint32_t temp32 = it->second;
-    file << it->first << " " << ( temp32>>24) << " "  <<( (temp32&MASK_12) - ( (temp32>>12)&MASK_12) )<< "\n";
-  }
-  file.close();
-}
-
-void Parser::PackageMWPC::print() const
-{
-  uint8_t ch = 0;
-  uint16_t Q = 0;
-  for(auto it: m_tof_cq_map)
-  {
-    getChannelCharge(it.second, ch, Q);
-    std::cout << it.first << " " << (uint16_t)ch << " " << Q << std::endl;
-  }
-  std::cout << std::endl;
-}
Index: rthworm/Parser/libsrc/PackageMWPCold.cc
===================================================================
--- earthworm/Parser/libsrc/PackageMWPCold.cc	(revision 82e3ac03b2993ee5dd25229a6f2b800faf9cb840)
+++ 	(revision )
@@ -1,174 +1,0 @@
-#include "PackageMWPCold.hh"
-#include <iostream>       // std::cout
-#include <bitset>
-#include "UtilsException.hh"
-#include "Hist2DMap.hh"
-#include "NumpyHist1D.hh"
-#include <cmath>
-
-Parser::PackageMWPCold::PackageMWPCold(double threshold, double time_window)
-:ParserMWPC(), m_charge_threshold(threshold), m_time_window(time_window), m_last_t0(0)
-{
-}
-
-Parser::PackageMWPCold::~PackageMWPCold()
-{
-}
-
-bool Parser::PackageMWPCold::readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end,
-  Hist2DMap &hitmap, NumpyHist1D &qhist) const
-{
-  unsigned eventcnt = 0;
-
-  const uint8_t *package_end;
-  uint64_t offset=0;
-  if(!findNextPackage(pt, stream_end, package_end, offset))
-    return false;
-
-  //parsing raw data
-  ParserMWPC::MWPCHeader header;
-  readHeader(pt, header);
-  unsigned mapnum = header.map_num;
-  //x chanel 50, spacing 4mm, y channel 94, spacing 2.2mm
-  // std::bitset<50> x; //In standard C++, bits are initialized with zeros
-  // std::bitset<94> y;
-
-  if(!m_last_t0)
-    m_last_t0 = header.t0cnt;
-
-  //if this is the start of a new t0 signal
-  //process whatever in the map and get ready to restart the accumulation
-  if(header.t0cnt!=m_last_t0 && !m_tof_cq_map.empty())//if it is the beginning of the next frame, process data
-  {
-    // print();
-    uint8_t chnl = 0;
-    uint16_t Q = 0;
-    unsigned chargeSum = 0;
-    uint32_t hittof=m_tof_cq_map.begin()->first; //initialize the for loop
-    auto last_item_in_map = --(m_tof_cq_map.end());
-    uint32_t eventSz(0), accu_x(0), accu_y(0), accu_xw(0), accu_yw(0);
-
-    for(auto it=m_tof_cq_map.begin();it!=m_tof_cq_map.end();++it)
-    {
-      getChannelCharge(it->second, chnl, Q);
-      if(Q<m_charge_threshold) continue;
-
-      // test if this hit is the new start of next event
-      if(it->first>hittof + m_time_window || it==last_item_in_map)
-      {
-        //finish  accumulation and fill map
-        if(it==last_item_in_map)
-        {
-          //this hit belongs to this event, this item must be accumulated in
-          //this event
-          eventSz++;
-          chnl<51 ? accu_xw += chnl*Q : accu_yw += (chnl-50)*Q;
-          chnl<51 ? accu_x += Q : accu_y += Q;
-          chargeSum += Q;
-        }
-
-        // printf("%d %d %d %d\n",eventcnt, it->first, chnl, Q);
-        eventcnt++;
-
-        if(accu_x*accu_y && eventSz>3)
-        {
-          //fill charge hist
-          qhist.fill(chargeSum);
-          //fill pixel histogram
-          float x = accu_xw/float(accu_x);
-          float y = accu_yw/float(accu_y);
-          hitmap.fill( 0, hittof, std::round(x) + std::round(y)*50 );
-          printf("%g;%g;%g;%d;  %d\n", y*2.2, (50-x)*4., hittof/40.0, header.t0cnt-1, eventcnt-1 );
-          assert(chargeSum==accu_x+accu_y);
-        }
-
-        if(it!=last_item_in_map)
-        {
-          //prepare next event
-          hittof=it->first;
-          chargeSum=Q;
-          eventSz=1;
-          accu_x=0;
-          accu_y=0;
-          accu_xw=0;
-          accu_yw=0;
-
-          chnl<51 ? accu_xw += chnl*Q : accu_yw += (chnl-50)*Q;
-          chnl<51 ? accu_x += Q : accu_y += Q;
-        }
-      }
-      else
-      {
-        //accumulate
-        // printf("%d %d %d %d\n",eventcnt, it->first, chnl, Q);
-        eventSz++;
-        chnl<51 ? accu_xw += chnl*Q : accu_yw += (chnl-50)*Q;
-        chnl<51 ? accu_x += Q : accu_y += Q;
-        chargeSum += Q;
-      }
-    }
-
-    std::multimap<uint32_t,uint32_t> temp; //release memory
-    m_tof_cq_map.swap(temp);
-    m_last_t0=header.t0cnt;
-  }
-
-  //Sorting hit data
-  // printf("*********%d maps************\n",header.map_num);
-  uint32_t temp32=0;
-
-  for(unsigned imap=0;imap<header.map_num;imap++)
-  {
-    error_assert(*pt == 0xAA);
-    uint32_t t = 0;
-    read_uint32(pt,t);
-    t &= MASK_24;
-    // printf("TdataID %d\n", t);
-    uint32_t eventNum = 0;
-    read_uint32(pt,eventNum);
-
-    // printf("map %d, event number %d \n",imap, eventNum);
-    for(unsigned ievt=0;ievt<eventNum;ievt++)
-    {
-      uint8_t ch = *(pt);
-      read_uint32(pt, temp32);
-      //error_assert(ch==*(pt));
-      uint32_t t_hi_res = temp32&MASK_24;
-      read_uint32(pt, temp32);
-      //fixme: there is a bug in DAQ, the secend channel num sometimes are left zero
-      temp32 = (temp32&MASK_24) + (ch<<24);
-      // uint16_t charge = (temp32&MASK_12)- ((temp32>>12)&MASK_12);
-      m_tof_cq_map.emplace_hint(m_tof_cq_map.end(), t_hi_res, temp32);
-
-      // printf("ch %d, charge %d, time stamp %d\n", ch, charge, t_hi_res);
-    }
-  }
-  pt = package_end;
-
-  //printf("left %ld, package_end %p, stream_end %p\n", stream_end-package_end, package_end, stream_end);
-  return package_end==stream_end?false:true;
-}
-
-void Parser::PackageMWPCold::write(std::ofstream &file, const char *filename)
-{
-  file.open(filename);
-  auto it=m_tof_cq_map.begin();
-  for(;it!=m_tof_cq_map.end();++it)
-  {
-    uint32_t temp32 = it->second;
-    file << it->first << " " << ( temp32>>24) << " "  <<( (temp32&MASK_12) - ( (temp32>>12)&MASK_12) )<< "\n";
-  }
-  file.close();
-}
-
-void Parser::PackageMWPCold::print() const
-{
-  uint8_t ch = 0;
-  uint16_t Q = 0;
-  for(auto it: m_tof_cq_map)
-  {
-    getChannelCharge(it.second, ch, Q);
-    std::cout << it.first << " " << (uint16_t)ch << " " << Q << std::endl;
-  }
-  std::cout << std::endl;
-}
Index: rthworm/Parser/libsrc/ParserBase.cc
===================================================================
--- earthworm/Parser/libsrc/ParserBase.cc	(revision 82e3ac03b2993ee5dd25229a6f2b800faf9cb840)
+++ 	(revision )
@@ -1,42 +1,0 @@
-#include "ParserBase.hh"
-#include "UtilsException.hh"
-
-#include <cstdio>
-Parser::ParserBase::ParserBase()
-{
-
-}
-
-Parser::ParserBase::~ParserBase()
-{
-
-}
-
-
-void Parser::ParserBase::read_uint32_many(const uint8_t*& pt, std::vector<uint32_t> &u32_vec, unsigned num) const
-{
-  if(u32_vec.size()!=num)
-    u32_vec.resize(num);
-
-  for(unsigned i=0;i<num;i++) {
-    read_uint32(pt, u32_vec[i]);
-  }
-}
-
-
-bool Parser::ParserBase::findNextPackage(const uint8_t*& start, const uint8_t * const stream_end, const uint8_t*& pkgend, uint64_t &offset) const
-{
-  //fixme: detect zero padding data
-  error_assert_always(start<stream_end);
-  offset=0;
-  for(;start!=stream_end;start++,offset++)
-  {
-    if(findEnd(start,pkgend))
-    {
-      // if(offset) //fixme: add to log
-      //   printf("Found next package in the stream with offst %ld, start at %ld to the end of stream\n", offset, stream_end-start); //fixme : logge
-      return true;
-    }
-  }
-  return false;
-}
Index: rthworm/Parser/libsrc/ParserHe3.cc
===================================================================
--- earthworm/Parser/libsrc/ParserHe3.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,108 +1,0 @@
-#include <cstdio>
-
-#include "ParserHe3.hh"
-#include "UtilsException.hh"
-
-Parser::ParserHe3::ParserHe3()
-:ParserBase()
-{
-}
-
-Parser::ParserHe3::~ParserHe3()
-{
-}
-
-void Parser::ParserHe3::readHeader(const uint8_t*& pt, const Parser::ParserHe3::Header *header) const
-{
-  //Header is POD data
-  error_assert(*pt == PACK_START);
-
-  header = reinterpret_cast<const Header *>(pt);
-  pt += 8;
-
-  // printf("""\nheader:\n  flag 0x%x, instrument 0x%x, detc type 0x%x, module 0x%x\n"""
-  //        """opt_mode 0x%x fre_div 0x%x version 0x%x data_type 0x%x \n"""
-  //   ,header->flag, header->instrument, header->detector_type, header->module
-  //   ,header->opt_mode, header->fre_div_mode, header->data_ver, header->data_type );
-}
-
-void Parser::ParserHe3::readInfo(const uint8_t*& pt, Info &info) const
-{
-  uint32_t raw=0;
-  read_uint32(pt, info.t0_count);
-  read_uint32(pt, raw);
-  info.hit_cnt = (raw >> 18) & MASK_14;
-  info.sample_num_n = (raw >> 6) & MASK_12;
-  info.sample_num_bl = raw & MASK_6;
-
-  // printf("info: \n  t0_cnt %d, hit_cnt %d, n %d, m %d\n"
-  //    ,info.t0_count,  info.hit_cnt, info.sample_num_n, info.sample_num_bl);
-}
-void Parser::ParserHe3::printInfo(const uint8_t* pt) const
-{
-  uint32_t raw=0;
-  Info info;
-  read_uint32(pt, info.t0_count);
-  read_uint32(pt, raw);
-  info.hit_cnt = (raw >> 18) & MASK_14;
-  info.sample_num_n = (raw >> 6) & MASK_12;
-  info.sample_num_bl = raw & MASK_6;
-  printf("info: \n  t0_cnt %d, hit_cnt %d, n %d, m %d\n"
-     ,info.t0_count,  info.hit_cnt, info.sample_num_n, info.sample_num_bl);
-}
-
-
-void Parser::ParserHe3::readHit( const uint8_t*& pt, Hit &hit) const
-{
-  error_assert( ((*pt>>4) & MASK_4)  == DATA_START);
-
-  uint32_t raw=0;
-  read_uint32(pt, raw);
-  hit.time = raw & MASK_24;
-  hit.tube_id = (raw>>24) & MASK_4;
-  //fixme:
-  // //tube_id from DAQ 7 8 9 11, corresponding to 1 2 3 4 in subsequent analysis
-  // hit.tube_id = hit.tube_id==11? hit.tube_id-7:hit.tube_id-6;
-  read_uint32(pt, raw);
-  hit.upper_baseline = raw & MASK_20;
-  read_uint32(pt, raw);
-  hit.lower_baseline = raw & MASK_20;
-  read_uint32(pt, raw);
-  hit.upper_charge = (raw>>16) & MASK_16;
-  hit.lower_charge = raw & MASK_16;
-
-  // printf("hit:const uint8_t*&tube_id %x, upper_baseline %d, lower_baseline %d\n  upper_charge %d, lower_charge %d\n"
-  //   ,hit.time,  hit.tube_id, hit.upper_baseline, hit.lower_baseline,hit.upper_charge, hit.lower_charge);
-}
-
-bool Parser::ParserHe3::findEnd(const uint8_t* pt, const uint8_t*& end) const
-{
-  if(*pt != PACK_START)
-    return false;
-
-  //extract number of hit
-  uint32_t tmp = *(pt+12)<<8;
-  tmp += *(pt+13);
-  uint32_t hitnum = tmp >> 2;
-
-  //estimate package total size
-  uint32_t data_payload_size = hitnum*16;
-  uint32_t estTotSize = 16 + data_payload_size + 8;
-
-  //check the second flag in a package
-  if(*(pt + estTotSize -8) !=  PACK_END)
-    return false;
-
-  uint32_t totByteCount = 0;
-  const uint8_t * pos = pt+estTotSize-4;
-  read_uint32(pos ,totByteCount);
-
-  end =  pt + totByteCount;
-  return estTotSize==totByteCount?true:false;
-}
-
-bool Parser::ParserHe3::is_valid(const uint8_t* pt) const
-{
-  const uint8_t* tmp;
-  return findEnd(pt,tmp);
-}
Index: rthworm/Parser/libsrc/ParserMWPC.cc
===================================================================
--- earthworm/Parser/libsrc/ParserMWPC.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,57 +1,0 @@
-#include "ParserMWPC.hh"
-#include "UtilsException.hh"
-
-Parser::ParserMWPC::ParserMWPC() { }
-Parser::ParserMWPC::~ParserMWPC() { }
-
-void Parser::ParserMWPC::readHeader(const uint8_t*& pt, MWPCHeader& header) const
-{
-  const uint8_t* end = nullptr;
-//  if(findEnd(pt,end))
- //   printf("this is a valid package, size is 0x%x, %p, %p\n", end-pt, pt, end);
-  uint32_t temp = 0;
-  read_uint32 (pt,temp);
-  error_assert(temp==MWPC_SIG);  //fixme: error handling
-
-
-  header.instrment = *pt;
-  header.detector_type = *(++pt);
-  pt+=3;
-  header.opt_mode = *(++pt);
-  header.freq_div_mode = *(++pt);
-  header.data_version = *(++pt);
-  header.data_type = *(++pt);
-
-  pt += 4*7;
-  read_uint32(pt,header.t0cnt);
-  read_uint32(pt,header.payload_bycnt);
-  read_uint32(pt,header.map_num);
-
-  // printf("""instr 0x%x, det type 0x%x, opt mode 0x%x, freq div 0x%x\n"""
-  //        """ data ver 0x%x, data type 0x%x, t0 cnt %d, byte cnt 0x%x, map cnt %d\n""",
-  //       header.instrment, header.detector_type, header.opt_mode, header.freq_div_mode,
-  //       header.data_version, header.data_type,header.t0cnt , header.payload_bycnt, header.map_num);
-  // printf("next byte 0x%x\n", *(pt+12));
-
-  pt+=12; //12 bytes followed are reserved.
-}
-
-bool Parser::ParserMWPC::findEnd(const uint8_t* pt, const uint8_t*& end) const
-{
-  //match token
-  if(*pt!=0xee && *(pt+1)!= 0x12 && *(pt+2)!= 0x34 && *(pt+3)!= 0xee)
-    return false;
-
-  uint32_t bycnt = 0;
-  pt +=44; //jump to the "byte count" position
-  read_uint32 (pt, bycnt);
-  end = pt + bycnt - 48;// read_uint32 moved pt forward by 48
-  return true;
-}
-
-bool Parser::ParserMWPC::is_valid(const uint8_t* pt) const
-{
-  //fixme : check more stuff
-  const uint8_t* bycnt = 0;
-  return findEnd(pt, bycnt);
-}
Index: rthworm/Parser/libsrc/ParserUtils.cc
===================================================================
--- earthworm/Parser/libsrc/ParserUtils.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,9 +1,0 @@
-#include "ParserUtils.hh"
-#include <stdint.h>
-
-int Parser::is_little_endian()
-{
-  //Return 0 for big endian, 1 for little endian.
-  volatile uint32_t i=0x01234567;
-  return (*((uint8_t*)(&i))) == 0x67;
-}
Index: rthworm/Parser/main.cc
===================================================================
--- earthworm/Parser/main.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,22 +1,0 @@
-#include <cstdio>
-#include <fstream>
-#include <vector>
-
-#include "ParserUtils.hh"
-#include "ParserHe3.hh"
-int main(int argc, char *argv[])
-{
-    printf( "This processor is %s endian\n",Parser::is_little_endian()? "little":"big");
-    std::vector<uint8_t> data;
-    for(uint8_t i=1;i<100;i++)
-    {
-      data.push_back(i);
-    }
-
-    auto *he3 = new Parser::ParserHe3();
-    const Parser::ParserHe3::Header *header ;
-    const uint8_t * pt = data.data();
-    he3->readHeader(pt,header);
-
-    return 0;
-}
Index: rthworm/Parser/python/__init__.py
===================================================================
--- earthworm/Parser/python/__init__.py	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,76 +1,0 @@
-#!/usr/bin/env python
-#enable py3 behaviour in py2.6+ (avoid unicode_literals on purpose!)
-from __future__ import division, print_function, absolute_import
-
-import ctypes
-
-_libc = ctypes.CDLL('./libprototype.so')
-print ("runnig _load()")
-ndarray_to_dblp = lambda a : a.ctypes.data_as(ctypes.POINTER(ctypes.c_double))
-ndarray_to_ubtp = lambda a : a.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))
-
-
-def _str2cstr(s):
-    #converts any string (str,bytes,unicode) to bytes
-    try:
-        return s if isinstance(s,bytes) else s.encode('ascii')
-    except UnicodeEncodeError:
-        #Attempt with file-system encoding, in case of non-ASCII path names:
-        return s.encode(sys.getfilesystemencoding())
-
-def _cstr2str(s):
-    #converts bytes object to str (unicode in py3, bytes in py2)
-    try:
-        return s if isinstance(s,str) else s.decode('ascii')
-    except UnicodeDecodeError:
-        return s.decode(sys.getfilesystemencoding())
-
-
-def _wrap(fct_name,restype,argtypes,take_ref = False, hide=False, error_check=True):
-    assert isinstance(argtypes,tuple)
-    raw=getattr(_libc,fct_name)
-    raw.argtypes=argtypes
-    raw.restype=restype
-
-    if take_ref:
-        assert len(argtypes)==1
-        fct = lambda arg : raw(ctypes.byref(arg))
-    else:
-        fct = lambda *args : raw(*args)
-    if error_check:
-        #NB: we should read about return types in the ctypes tutorial. Apparently one
-        #can just set an error checking function as the restype.
-        raw_fct = fct
-        def fcte(*aaa):
-            r = raw_fct(*aaa)
-            # if _ncerror(): fixme:
-            #     _raise_err()
-            # return r
-        fct=fcte
-    if not hide:
-        functions[fct_name] = fct
-    return fct
-
-#_ncerror       = _wrap('ncrystal_error',ctypes.c_int,tuple(),hide=True,error_check=False)
-
-
-class Parser_Parserbase_t(ctypes.Structure):
-     _fields_ = [('internal', ctypes.c_void_p)]
-#
-
-
-class ParserBase(ctypes.Structure):
-    """Base class for Parsers"""
-    def __init__(self):
-        self._Parser_read_uint32 = _wrap('Parser_read_uint32', ctypes.POINTER(ctypes.c_uint) ,(Parser_Parserbase_t,ctypes.c_ubyte
-         ,ctypes.POINTER(ctypes.c_uint) ),hide=True)
-
-        _create_detectorbase = _wrap('create_detectorbase', (Parser_Parserbase_t)  , (), hide=True)
-        self._rawobj = _create_detectorbase()
-
-    def read_uint32(self, pt_in): #fixme
-        data=0
-        self._Parser_read_uint32(self._rawobj, pt_in, data)
-        return data
-
-ParserBase()
Index: rthworm/RedisIO/libinc/RedisIO.hh
===================================================================
--- earthworm/RedisIO/libinc/RedisIO.hh	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,13 +1,0 @@
-#ifndef RedisIO_hh
-#define RedisIO_hh
-
-class RedisIO {
-public:
-  RedisIO();
-  virtual ~RedisIO();
-
-private:
-
-};
-
-#endif
Index: rthworm/RedisIO/libsrc/RedisIO.cc
===================================================================
--- earthworm/RedisIO/libsrc/RedisIO.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,64 +1,0 @@
-#include "RedisIO.hh"
-#include <cpp_redis/cpp_redis>
-#include <iostream>
-
-
-RedisIO::RedisIO()
-{
-  //! Enable logging
- cpp_redis::active_logger = std::unique_ptr<cpp_redis::logger>(new cpp_redis::logger);
-
- //! High availability requires at least 2 io service workers
- cpp_redis::network::set_default_nb_workers(2);
-
- cpp_redis::client client;
-
- //! Add your sentinels by IP/Host & Port
- client.add_sentinel("127.0.0.1", 26379);
-
- //! Call connect with optional timeout
- //! Can put a loop around this until is_connected() returns true.
- client.connect("mymaster", [](const std::string& host, std::size_t port, cpp_redis::connect_state status) {
-   if (status == cpp_redis::connect_state::dropped) {
-     std::cout << "client disconnected from " << host << ":" << port << std::endl;
-   }
- },
-   0, -1, 5000);
-
- // same as client.send({ "SET", "hello", "42" }, ...)
- client.set("hello", "42", [](cpp_redis::reply& reply) {
-   std::cout << "set hello 42: " << reply << std::endl;
-   // if (reply.is_string())
-   //   do_something_with_string(reply.as_string())
- });
-
- while (true) {
-   // same as client.send({ "DECRBY", "hello", 12 }, ...)
-   client.incrby("hello", 12, [](cpp_redis::reply& reply) {
-     std::cout << "incrby hello 12: " << reply << std::endl;
-     // if (reply.is_integer())
-     //   do_something_with_integer(reply.as_integer())
-   });
-
-   // same as client.send({ "GET", "hello" }, ...)
-   client.get("hello", [](cpp_redis::reply& reply) {
-     std::cout << "get hello: " << reply << std::endl;
-     // if (reply.is_string())
-     //   do_something_with_string(reply.as_string())
-   });
-
-   // commands are pipelined and only sent when client.commit() is called
-   // client.commit();
-
-   // synchronous commit, no timeout
-   client.sync_commit();
-   std::cout << std::endl;
-   std::this_thread::sleep_for(std::chrono::milliseconds(3000));
- }
-
-}
-
-RedisIO::~RedisIO()
-{
-
-}
Index: rthworm/Utils/libinc/RedisHelper.hh
===================================================================
--- earthworm/Utils/libinc/RedisHelper.hh	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,36 +1,0 @@
-#ifndef RedisHelper_hh
-#define RedisHelper_hh
-
-#include <string>
-#include <vector>
-#include <typeinfo>
-
-static inline bool is_base64(unsigned char c) {
-  return (isalnum(c) || (c == '+') || (c == '/'));
-}
-
-void base64_encode(unsigned char const * , unsigned int len, std::string &encoded);
-void base64_decode(std::string const &encoded_string, std::string &decoded);
-
-//content in the encoded will be replaced by new data
-void make_jsonarray(unsigned char const * data, unsigned len, const std::string &dtype,
-                    const std::vector<unsigned> &shape, std::string &encoded);
-
-void c2json_int8(const int8_t *data, const std::vector<unsigned>& shape, std::string &encoded);
-void c2json_uint8(const uint8_t *data, const std::vector<unsigned>& shape, std::string &encoded);
-
-void c2json_int16(const int16_t *data, const std::vector<unsigned>& shape, std::string &encoded);
-void c2json_uint16(const uint16_t *data, const std::vector<unsigned>& shape, std::string &encoded);
-
-void c2json_int32(const int32_t *data, const std::vector<unsigned>& shape, std::string &encoded);
-void c2json_uint32(const uint32_t *data, const std::vector<unsigned>& shape, std::string &encoded);
-
-void c2json_int64(const int64_t *data, const std::vector<unsigned>& shape, std::string &encoded);
-void c2json_uint64(const uint64_t *data, const std::vector<unsigned>& shape, std::string &encoded);
-
-void c2json_float(const float *data, const std::vector<unsigned>& shape, std::string &encoded);
-void c2json_double(const double *data, const std::vector<unsigned>& shape, std::string &encoded);
-
-
-
-#endif
Index: rthworm/Utils/libinc/RedisNumpy.hh
===================================================================
--- earthworm/Utils/libinc/RedisNumpy.hh	(revision c7ecea415c9e046d5a08db405078268967e91305)
+++ 	(revision )
@@ -1,106 +1,0 @@
-#ifndef RedisNumpy_hh
-#define RedisNumpy_hh
-
-#include <vector>
-#include <string>
-#include <stdexcept>
-#include <iostream>
-
-//The RedisNumpy class is able to pack C type arrays into the native numpy npy v1.0 format.
-//It can be used to transceive numpy array over Redis store between C++ and python without any encoding/decoding
-
-//defintion of the format can be found at
-//https://docs.scipy.org/doc/numpy-1.14.2/neps/npy-format.html
-//the implementation in numpy is at
-//https://github.com/numpy/numpy/blob/master/numpy/lib/format.py
-
-//Limitations
-//1. limited by format, one chunk of converted data can only represent one numpy array.
-//2. limited by implementation, all numpy array element must have the same type and not compressed.
-//3. limited by implementation, only creating nor parsing numpy data.
-//3. limited by implementation, must by used in little endian system.
-
-class RedisNumpy {
-  //'<'' means little endian
-  //0x3c63 ascii for <c
-  //0x3c66 ascii for <f
-  //0x3c69 ascii for <i
-  //0x3c75 ascii for <u
-
-  //0x31 ascii for 1
-  //0x32 ascii for 2
-  //0x34 ascii for 4
-  //0x38 ascii for 8
-
-  //0x3c633136 for <c16
-
-public:
-  enum data_type : uint32_t {
-    c8 = 0x38633c,
-    f4 = 0x34663c,
-    f8 = 0x38663c,
-    i1 = 0x31693c,
-    i2 = 0x32693c,
-    i4 = 0x34693c,
-    i8 = 0x38693c,
-    u1 = 0x31753c,
-    u2 = 0x32753c,
-    u4 = 0x34753c,
-    u8 = 0x38753c,
-    c16 = 0x3631633c
- };
-public:
-  RedisNumpy();
-  virtual ~RedisNumpy();
-
-  template <typename T>
-  void makeNumpyArr(const std::vector<T> &data, data_type type,
-                    const std::vector<uint64_t> &shape, std::string &npArr);
-
-  template <typename T>
-  void makeNumpyArr(const T *data, unsigned datasize, data_type type,
-                    const std::vector<uint64_t> &shape, std::string &npArr);
-
-private:
-  const std::string m_fixed_magic;
-  int is_little_endian();
-  void makeNumpyArr(const uint8_t  *data, unsigned len,
-                    data_type type, const std::vector<uint64_t> &shape, std::string &npArr);
-private:
-  //use the data_type to construct. getTypeString retures the ascii name of the type in npy format
-  union U32toASCII {
-    uint32_t u32;
-    char  ascii[4];
-    U32toASCII(uint32_t a) : u32(a) {};
-    std::string getTypeString() {
-      std::string type_str;
-      for(unsigned i=0;i<4;i++) {
-        if(!ascii[i])
-          return type_str;
-        type_str += *(ascii+i);
-      }
-      if(type_str.empty()) //shouldn't really reach here
-        throw std::invalid_argument("data_type ascii array can't be all zero");
-      return type_str;
-    }
-  };
-};
-
-template <typename T>
-void RedisNumpy::makeNumpyArr(const std::vector<T> &data, data_type type,
-                              const std::vector<uint64_t> &shape, std::string &npArr)
-{
-  makeNumpyArr( reinterpret_cast<const uint8_t*>(data.data()),
-                data.size()*sizeof(T), type, shape , npArr );
-}
-
-template <typename T>
-void RedisNumpy::makeNumpyArr(const T *data, unsigned datasize, data_type type,
-                              const std::vector<uint64_t> &shape, std::string &npArr)
-{
-  makeNumpyArr( reinterpret_cast<const uint8_t*>(data), datasize*sizeof(T), type, shape , npArr );
-}
-
-
-
-#endif
Index: rthworm/Utils/libinc/UtilsException.hh
===================================================================
--- earthworm/Utils/libinc/UtilsException.hh	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,69 +1,0 @@
-#ifndef Utils_Exception_hh
-#define Utils_Exception_hh
-
-
-#include <stdexcept>
-#include <sstream>
-#include <string>
-
-namespace Error {
-
-  class Exception : public std::runtime_error {
-  public:
-    explicit Exception(const std::string& msg, const char * f, unsigned l) throw();
-    explicit Exception(const char * msg,  const char * f, unsigned l) throw();
-    virtual const char * getTypeName() const throw() = 0;
-    const char * getFile() const throw() { return m_file; }
-    unsigned getLineNo() const throw() { return m_lineno; }
-    Exception( const Exception & o ) throw();
-    Exception & operator= ( const Exception & o ) throw();
-    virtual ~Exception() throw();
-  private:
-    const char * m_file;
-    unsigned m_lineno;
-  };
-
-#define ADD_ERROR_TYPE(ErrType)                                                               \
-  struct ErrType : public Exception {                                                                \
-    explicit ErrType(const std::string& m, const char * f, unsigned l) throw() : Exception(m,f,l) {} \
-    explicit ErrType(const char * m,  const char * f, unsigned l) throw() : Exception(m,f,l) {}      \
-    virtual const char * getTypeName() const throw() { return #ErrType; }                            \
-    virtual ~ErrType() throw();                                                                      \
-  }
-  //List of error types (destructors implemented in .cc):
-  ADD_ERROR_TYPE(FileNotFound);
-  ADD_ERROR_TYPE(DataLoadError);
-  ADD_ERROR_TYPE(MissingInfo);
-  ADD_ERROR_TYPE(CalcError);
-  ADD_ERROR_TYPE(LogicError);
-  ADD_ERROR_TYPE(BadInput);
-#undef ADD_ERROR_TYPE
-}
-
-#define ERROR_THROW(ErrType, msg)                     \
-  {                                                   \
-    throw ::Error::ErrType(msg,__FILE__,__LINE__);    \
-  }
-
-#define ERROR_THROW2(ErrType, msg)        \
-  {                                       \
-    std::ostringstream err_oss;           \
-    err_oss << msg;                       \
-    ERROR_THROW(ErrType,err_oss.str())    \
-  }
-
-
-#define error_str(s) #s
-#define error_xstr(s) error_str(s)
-#define error_assert_always(x) do { if (!(x)) { ERROR_THROW(LogicError,\
-                              "Assertion failure: " error_xstr(x)); } } while(0)
-
-#ifndef NDEBUG
-#  define error_assert(x) error_assert_always(x)
-#  define error_assert2(x) error_assert_always(x)
-#else
-#  define error_assert(x) do {} while(0)
-#  define error_assert2(x) do { (void)sizeof(x); } while(0)//use but dont evaluate x
-#endif
-
-#endif
Index: rthworm/Utils/libsrc/RedisHelper.cc
===================================================================
--- earthworm/Utils/libsrc/RedisHelper.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,195 +1,0 @@
-#include "RedisHelper.hh"
-#include "UtilsException.hh"
-#include <iostream>
-
-static const std::string base64_chars =
-             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-             "abcdefghijklmnopqrstuvwxyz"
-             "0123456789+/";
-
-
-void base64_encode(unsigned char const *bytes_to_encode, unsigned int in_len, std::string &ret)
-{
-  int i = 0;
-  int j = 0;
-  unsigned char char_array_3[3];
-  unsigned char char_array_4[4];
-
-  while (in_len--) {
-    char_array_3[i++] = *(bytes_to_encode++);
-    if (i == 3) {
-      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
-      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
-      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
-      char_array_4[3] = char_array_3[2] & 0x3f;
-
-      for(i = 0; (i <4) ; i++)
-        ret += base64_chars[char_array_4[i]];
-      i = 0;
-    }
-  }
-
-  if (i)
-  {
-    for(j = i; j < 3; j++)
-      char_array_3[j] = '\0';
-
-    char_array_4[0] = ( char_array_3[0] & 0xfc) >> 2;
-    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
-    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
-
-    for (j = 0; (j < i + 1); j++)
-      ret += base64_chars[char_array_4[j]];
-
-    while((i++ < 3))
-      ret += '=';
-
-  }
-
-}
-
-void base64_decode(std::string const& encoded_string, std::string &ret)
-{
-  size_t in_len = encoded_string.size();
-  int i = 0;
-  int j = 0;
-  int in_ = 0;
-  unsigned char char_array_4[4], char_array_3[3];
-
-  while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
-    char_array_4[i++] = encoded_string[in_]; in_++;
-    if (i ==4) {
-      for (i = 0; i <4; i++)
-        char_array_4[i] = base64_chars.find(char_array_4[i]) & 0xff;
-
-      char_array_3[0] = ( char_array_4[0] << 2       ) + ((char_array_4[1] & 0x30) >> 4);
-      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
-      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) +   char_array_4[3];
-
-      for (i = 0; (i < 3); i++)
-        ret += char_array_3[i];
-      i = 0;
-    }
-  }
-
-  if (i) {
-    for (j = 0; j < i; j++)
-      char_array_4[j] = base64_chars.find(char_array_4[j]) & 0xff;
-
-    char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
-    char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
-
-    for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
-  }
-}
-
-void make_jsonarray(unsigned char const * data, unsigned len, const std::string &dtype,
-                    const std::vector<unsigned> &shape, std::string &encoded)
-{
-  encoded = "{\"dtype\": \"" + dtype;
-  encoded.reserve(len*2);
-
-  encoded += "\", \"shape\": [";
-  error_assert_always(!shape.empty());
-  unsigned lastid = shape.size()-1;
-  for(unsigned i=0;i<lastid;i++)
-  {
-    encoded += std::to_string(shape[i])+", ";
-  }
-  encoded += std::to_string(shape[lastid]);
-
-  encoded += "], \"__ndarray__\": \"";
-  base64_encode(reinterpret_cast<const unsigned char*> ( data ), len, encoded);
-  encoded += "\"}";
-}
-
-void c2json_int8(const int8_t *data, const std::vector<unsigned>& shape, std::string &encoded)
-{
-  unsigned len=1;
-  for(auto v:shape)
-    len *= v;
-  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(int8_t), "int8",
-                 shape, encoded);
-}
-
-void c2json_uint8(const uint8_t *data, const std::vector<unsigned>& shape, std::string &encoded)
-{
-  unsigned len=1;
-  for(auto v:shape)
-    len *= v;
-  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(uint8_t), "uint8",
-                 shape, encoded);
-}
-
-void c2json_int16(const int16_t *data, const std::vector<unsigned>& shape, std::string &encoded)
-{
-  unsigned len=1;
-  for(auto v:shape)
-    len *= v;
-  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(int16_t), "int16",
-                 shape, encoded);
-}
-
-void c2json_uint16(const uint16_t *data, const std::vector<unsigned>& shape, std::string &encoded)
-{
-  unsigned len=1;
-  for(auto v:shape)
-    len *= v;
-  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(uint16_t), "uint16",
-                 shape, encoded);
-}
-
-
-void c2json_int32(const int32_t *data, const std::vector<unsigned>& shape, std::string &encoded)
-{
-  unsigned len=1;
-  for(auto v:shape)
-    len *= v;
-  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(int32_t), "int32",
-                 shape, encoded);
-}
-
-void c2json_uint32(const uint32_t *data, const std::vector<unsigned>& shape, std::string &encoded)
-{
-  unsigned len=1;
-  for(auto v:shape)
-    len *= v;
-  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(uint32_t), "uint32",
-                 shape, encoded);
-}
-
-void c2json_int64(const int64_t *data, const std::vector<unsigned>& shape, std::string &encoded)
-{
-  unsigned len=1;
-  for(auto v:shape)
-    len *= v;
-  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(int64_t), "int64",
-                 shape, encoded);
-}
-
-void c2json_uint64(const uint64_t *data, const std::vector<unsigned>& shape, std::string &encoded)
-{
-  unsigned len=1;
-  for(auto v:shape)
-    len *= v;
-  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(uint64_t), "uint64",
-                 shape, encoded);
-}
-
-void c2json_float(const float *data, const std::vector<unsigned>& shape, std::string &encoded)
-{
-  unsigned len=1;
-  for(auto v:shape)
-    len *= v;
-  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(float), "float32",
-                 shape, encoded);
-}
-
-void c2json_double(const double *data, const std::vector<unsigned>& shape, std::string &encoded)
-{
-  unsigned len=1;
-  for(auto v:shape)
-    len *= v;
-  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(double), "float64",
-                 shape, encoded);
-}
Index: rthworm/Utils/libsrc/RedisNumpy.cc
===================================================================
--- earthworm/Utils/libsrc/RedisNumpy.cc	(revision c7ecea415c9e046d5a08db405078268967e91305)
+++ 	(revision )
@@ -1,58 +1,0 @@
-#include "RedisNumpy.hh"
-#include "UtilsException.hh"
-#include <cstring>
-
-RedisNumpy::RedisNumpy()
-:m_fixed_magic( "\x93NUMPY")
-{
-  if(!is_little_endian())
-    throw std::runtime_error("RedisNumpy support only little endian system"); //fixme:check at compile time
-}
-
-RedisNumpy::~RedisNumpy()
-{
-
-}
-
-int RedisNumpy::is_little_endian()
-{
-  //Return 0 for big endian, 1 for little endian.
-  volatile uint32_t i=0x01234567;
-  return (*((uint8_t*)(&i))) == 0x67;
-}
-
-void RedisNumpy::makeNumpyArr(const uint8_t *data, unsigned len,
-                  data_type dtype, const std::vector<uint64_t> &shape, std::string &npArr)
-{
-  npArr.reserve(len + 128); //a guess of tot size
-
-  npArr = m_fixed_magic +'\x01'+'\x00' + "  ";
-  npArr += "{'descr': '" + U32toASCII(dtype).getTypeString() + "', 'fortran_order': False, 'shape': (" ;
-
-  for(auto v:shape)
-    npArr += std::to_string(v) + ",";
-  if(shape.size()>1)
-    npArr.pop_back();
-
-  npArr += "), }";
-
-  unsigned dict_size = npArr.size();
-  if(dict_size>65535)
-    throw std::length_error("header in npy 1.0 format can't be larger than 65535 bytes, see https://docs.scipy.org/doc/numpy-1.14.2/neps/npy-format.html");
-
-  //total meta info size mush be evenly divisible by 64 for alignment purposes.
-  //-1, because terminated by a newline '\n'
-  unsigned tot = ((dict_size/64)+1)*64;
-
-  //sizeof("\x93NUMPY\x01\00")+sizeof(HEADER_LEN)=10 bytes
-  uint16_t header_len_with_padding = tot-10;
-
-  npArr[8] = ( unsigned char ) (header_len_with_padding & 0xff) ;
-  npArr[9] = ( unsigned char ) ((header_len_with_padding>>8) & 0xff);
-
-  unsigned padding_size = tot - dict_size - 1;
-  npArr.append(padding_size,'\x20');
-  npArr += "\n";
-
-  npArr.append(reinterpret_cast<const char* >(data),len);
-}
Index: rthworm/Utils/libsrc/UtilsException.cc
===================================================================
--- earthworm/Utils/libsrc/UtilsException.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,45 +1,0 @@
-#include "UtilsException.hh"
-
-
-namespace Error {
-
-  Exception::Exception(const std::string& msg, const char * f, unsigned l) throw()
-    : std::runtime_error(msg),
-      m_file(f),
-      m_lineno(l)
-  {
-  }
-
-  Exception::Exception(const char * msg,  const char * f, unsigned l) throw()
-    : std::runtime_error(msg),
-      m_file(f),
-      m_lineno(l)
-  {
-  }
-
-  Exception::Exception( const Exception & o ) throw()
-    : std::runtime_error(o),
-      m_file(o.m_file),
-      m_lineno(o.m_lineno)
-  {
-  }
-
-  Exception & Exception::operator= ( const Exception & o ) throw()
-  {
-    std::runtime_error::operator=(o);
-    m_file = o.m_file;
-    m_lineno = o.m_lineno;
-    return *this;
-  }
-
-  Exception::~Exception() throw()
-  {
-  }
-
-  FileNotFound::~FileNotFound() throw() {}
-  MissingInfo::~MissingInfo() throw() {}
-  DataLoadError::~DataLoadError() throw() {}
-  LogicError::~LogicError() throw() {}
-  CalcError::~CalcError() throw() {}
-  BadInput::~BadInput() throw() {}
-}
Index: rthworm/cpythonprototype/libinc/ctypes_api.hh
===================================================================
--- earthworm/cpythonprototype/libinc/ctypes_api.hh	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,22 +1,0 @@
-#pragma once
-
-#ifdef __cplusplus
-#  include <cstdint>
-#else
-#  include <stdint.h>
-#  include <stdbool.h>
-#endif
-
-#if defined (_WIN32) || defined (__CYGWIN__) || defined (WIN32)
-#  ifdef NCrystal_EXPORTS
-#    define EXPORT_SYMBOL __declspec(dllexport)
-#  else
-#    define EXPORT_SYMBOL __declspec(dllimport)
-#  endif
-#else
-#  if ( defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__)
-#    define EXPORT_SYMBOL    __attribute__ ((visibility ("default")))
-#  else
-#    define EXPORT_SYMBOL
-#  endif
-#endif
Index: rthworm/cpythonprototype/libinc/prototype.h
===================================================================
--- earthworm/cpythonprototype/libinc/prototype.h	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,23 +1,0 @@
-#ifndef prototype_h
-#define prototype_h
-
-
-#include "ctypes_api.hh"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-  EXPORT_SYMBOL   int ncrystal_error();/* returns 1 if an error condition occurred. */
-
-  typedef struct { void * internal; } Parser_Parserbase_t;
-
-  EXPORT_SYMBOL Parser_Parserbase_t create_detectorbase();
-  EXPORT_SYMBOL void  Parser_read_uint32( Parser_Parserbase_t, const uint8_t* it , uint32_t *u32);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
Index: rthworm/cpythonprototype/libsrc/prototype.cc
===================================================================
--- earthworm/cpythonprototype/libsrc/prototype.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ 	(revision )
@@ -1,86 +1,0 @@
-#include <cstring>
-
-#include "prototype.h"
-#include "UtilsException.hh"
-#include "ParserBase.hh"
-
-static int quietonerror = 0;
-static int haltonerror = 1;
-static int waserror = 0;
-static char errmsg[512];
-static char errtype[64];
-static void (*custom_error_handler)(char *,char*) = 0;
-
-/*
-int ncrystal_error()
-{
-  return waserror;
-}
-
-void setError(const char *msg, const char * etype = 0) throw() {
-  if (!etype)
-    etype="ncrystal_c-interface";
-  strncpy(errmsg,msg,sizeof(errmsg));
-  strncpy(errtype,etype,sizeof(errtype));
-  //Ensure final null-char in case of very long input strings:
-  errmsg[sizeof(errmsg)-1]='\0';
-  errtype[sizeof(errtype)-1]='\0';
-  if (custom_error_handler) {
-    (*custom_error_handler)(errtype,errmsg);
-  }
-  waserror = 1;
-  if (!quietonerror)
-    printf("ERROR [%s]: %s\n",errtype,errmsg);
-  if (haltonerror) {
-    printf("Terminating due to ERROR\n");
-    exit(1);
-  }
-}
-
-void handleError(const std::exception &e) throw() {
-  const Error::Exception* nce = dynamic_cast<const Error::Exception*>(&e);
-  if (nce) {
-    setError(nce->what(),nce->getTypeName());
-    return;
-  }
-  const std::runtime_error* stdrte = dynamic_cast<const std::runtime_error*>(&e);
-  if (stdrte)
-    setError(stdrte->what(),"std::runtime_error");
-  else
-    setError("<unknown>","std::exception");
-}
-
-#define ERRCATCH catch (std::exception& e) { handleError(e); }
-
-Parser::ParserBase * extract_detectorbase(Parser_Parserbase_t o) {
-  error_assert(o.internal);
-  return reinterpret_cast<Parser::ParserBase*>(o.internal);
-}
-
-Parser_Parserbase_t create_detectorbase()
-{
-  Parser_Parserbase_t o;
-  o.internal = 0;
-  try {
-    const Parser::ParserBase * db = new Parser::ParserBase();
-    error_assert(db);
-    o.internal = (void*)db;
-  } ERRCATCH;
-  return o;
-}
-
-
-void Parser_read_uint32( Parser_Parserbase_t ci_t, const uint8_t* it , uint32_t *u32)
-{
-  // if (!ncrystal_valid(&ci_t)) {
-  //   ncc::setError("ncrystal_info_dspacing_from_hkl called with invalid crystal info object");
-  //   return 0.0;
-  // }
-  // try {
-    Parser::ParserBase * ci = extract_detectorbase(ci_t);
-    ci->read_uint32(it, *u32);
-  //} ERRCATCH;
-  //return 0.0;
-}
-
-*/
Index: examples/test_b64coding.cc
===================================================================
--- examples/test_b64coding.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ examples/test_b64coding.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,102 @@
+#include "RedisHelper.hh"
+#include <iostream>
+#include <vector>
+#include <typeinfo>
+
+int main() {
+
+  const char *python_ref[] =
+  {"{\"dtype\": \"int8\", \"shape\": [6], \"__ndarray__\": \"AQIDBDJ/\"}",
+  "{\"dtype\": \"uint8\", \"shape\": [6], \"__ndarray__\": \"AQIDBDJ/\"}",
+  "{\"dtype\": \"int16\", \"shape\": [6], \"__ndarray__\": \"AQACAAMABAAyAH8A\"}",
+  "{\"dtype\": \"uint16\", \"shape\": [6], \"__ndarray__\": \"AQACAAMABAAyAH8A\"}",
+  "{\"dtype\": \"int32\", \"shape\": [6], \"__ndarray__\": \"AQAAAAIAAAADAAAABAAAADIAAAB/AAAA\"}",
+  "{\"dtype\": \"uint32\", \"shape\": [6], \"__ndarray__\": \"AQAAAAIAAAADAAAABAAAADIAAAB/AAAA\"}",
+  "{\"dtype\": \"int64\", \"shape\": [6], \"__ndarray__\": \"AQAAAAAAAAACAAAAAAAAAAMAAAAAAAAABAAAAAAAAAAyAAAAAAAAAH8AAAAAAAAA\"}",
+  "{\"dtype\": \"uint64\", \"shape\": [6], \"__ndarray__\": \"AQAAAAAAAAACAAAAAAAAAAMAAAAAAAAABAAAAAAAAAAyAAAAAAAAAH8AAAAAAAAA\"}",
+  "{\"dtype\": \"float32\", \"shape\": [6], \"__ndarray__\": \"AACAPwAAAEAAAEBAAACAQAAASEIAAP5C\"}",
+  "{\"dtype\": \"float64\", \"shape\": [6], \"__ndarray__\": \"AAAAAAAA8D8AAAAAAAAAQAAAAAAAAAhAAAAAAAAAEEAAAAAAAABJQAAAAAAAwF9A\"}"};
+
+
+  std::vector<std::string> python_ref_vec(python_ref, python_ref+10);
+
+  std::string str;
+
+  c2json_int8(std::vector<int8_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
+  if(str!=python_ref[0]) {
+    std::cout << "failed to pass test " << 0 << std::endl;
+    return 1;
+  }
+  c2json_uint8(std::vector<uint8_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
+  if(str!=python_ref[1]) {
+    std::cout << "failed to pass test " << 1 << std::endl;
+    return 1;
+  }
+  c2json_int16(std::vector<int16_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
+  if(str!=python_ref[2]) {
+    std::cout << "failed to pass test " << 2 << std::endl;
+    return 1;
+  }
+  c2json_uint16(std::vector<uint16_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
+  if(str!=python_ref[3]) {
+    std::cout << "failed to pass test " << 3 << std::endl;
+    return 1;
+  }
+  c2json_int32(std::vector<int32_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
+  if(str!=python_ref[4]) {
+    std::cout << "failed to pass test " << 4 << std::endl;
+    return 1;
+  }
+  c2json_uint32(std::vector<uint32_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
+  if(str!=python_ref[5]) {
+    std::cout << "failed to pass test " << 5 << std::endl;
+    return 1;
+  }
+  c2json_int64(std::vector<int64_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
+  if(str!=python_ref[6]) {
+    std::cout << "failed to pass test " << 6 << std::endl;
+    return 1;
+  }
+  c2json_uint64(std::vector<uint64_t> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
+  if(str!=python_ref[7]) {
+    std::cout << "failed to pass test " << 7 << std::endl;
+    return 1;
+  }
+  c2json_float(std::vector<float> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
+  if(str!=python_ref[8]) {
+    std::cout << "failed to pass test " << 8 << std::endl;
+    return 1;
+  }
+  c2json_double(std::vector<double> {1,2,3,4,50,127}.data(), std::vector<unsigned>{6}, str);
+  if(str!=python_ref[9]) {
+    std::cout << "failed to pass test " << 9 << std::endl;
+    return 1;
+  }
+
+
+  std::cout << "passed all python cross comparison. " << std::endl;
+
+
+
+  //reference generated by python as
+  // import base64
+  // bytes_data = range(0,256)
+  // d="".join(map(chr, bytes_data))
+  // base64.b64encode(d)
+
+  std::string ref = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==";
+  unsigned char bytes[256];
+  for(unsigned i=0;i<256;i++)
+    bytes[i]=i;
+
+  std::string encoded;
+  base64_encode(bytes , 256, encoded) ;
+  if(encoded!=ref) {
+    std::cout <<  "error!" << std::endl;
+    return 2;
+  }
+  else
+    std::cout << "passed!" << std::endl;
+  return 0;
+
+}
Index: examples/test_redis.cc
===================================================================
--- examples/test_redis.cc	(revision 01f0608013698e4770346b1b7859deb80a93c871)
+++ examples/test_redis.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -17,5 +17,4 @@
   client.add_sentinel("10.1.31.116", 9001);
 
-
   //! Call connect with optional timeout
   //! Can put a loop around this until is_connected() returns true.
@@ -23,4 +22,6 @@
     if (status == cpp_redis::connect_state::dropped) {
       std::cout << "client disconnected from " << host << ":" << port << std::endl;
+      __CPP_REDIS_LOG(error, "This is a warn message");
+
     }
   },
Index: examples/test_redisnumpy.cc
===================================================================
--- examples/test_redisnumpy.cc	(revision 82e3ac03b2993ee5dd25229a6f2b800faf9cb840)
+++ examples/test_redisnumpy.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -17,7 +17,4 @@
   for(unsigned i=0;i<sz;i++)
     data.push_back(i);
-
-  std::string encoded;
-  // std::cout << "encoded as " << encoded << std::endl;
 
   auto start = std::chrono::system_clock::now();
Index: src/CMakeLists.txt
===================================================================
--- src/CMakeLists.txt	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/CMakeLists.txt	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,60 @@
+project(earthworm)
+
+# add external package
+include(ExternalProject)
+
+set(EXTERNAL_INSTALL_LOCATION ${CMAKE_BINARY_DIR}/extern)
+
+if(WITH_REDIS)
+ExternalProject_Add(expkg_cpp_redis
+    GIT_REPOSITORY https://github.com/cpp-redis/cpp_redis.git
+    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION}
+    BUILD_COMMAND make -j
+    INSTALL_COMMAND make install
+    UPDATE_COMMAND ""
+)
+endif()
+
+
+#include_directories(${EXTERNAL_INSTALL_LOCATION}/include)
+#link_directories(${EXTERNAL_INSTALL_LOCATION}/lib)
+
+#add source
+file(GLOB PSR_SRC "${PROJECT_SOURCE_DIR}/Parser/libsrc/*.cc")
+file(GLOB HIS_SRC "${PROJECT_SOURCE_DIR}/Hist/libsrc/*.cc")
+file(GLOB UTL_SRC "${PROJECT_SOURCE_DIR}/Utils/libsrc/*.cc")
+file(GLOB DIM_SRC "${PROJECT_SOURCE_DIR}/DimRecv/libsrc/*.cc")
+file(GLOB PRO_SRC "${PROJECT_SOURCE_DIR}/cpythonprototype/libsrc/*.cc")
+
+if(WITH_REDIS)
+file(GLOB RIS_SRC "${PROJECT_SOURCE_DIR}/RedisIO/libsrc/*.cc")
+endif()
+
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${PSR_SRC} ${HIS_SRC} ${UTL_SRC}  ${PRO_SRC} ${DIM_SRC} ${RIS_SRC})
+
+if(WITH_REDIS)
+target_link_libraries(${PROJECT_NAME}  pthread  ${CMAKE_SOURCE_DIR}/extern/dim/linux/libdim.a
+                      ${EXTERNAL_INSTALL_LOCATION}/lib/libcpp_redis.a
+                      ${EXTERNAL_INSTALL_LOCATION}/lib/libtacopie.a)
+else()
+target_link_libraries(${PROJECT_NAME} pthread  ${CMAKE_SOURCE_DIR}/extern/dim/linux/libdim.a)
+
+endif()
+
+if(WITH_REDIS)
+add_dependencies(earthworm expkg_cpp_redis)
+endif()
+
+target_include_directories( ${PROJECT_NAME}
+    PUBLIC
+    ${PROJECT_SOURCE_DIR}/Utils/libinc
+    ${PROJECT_SOURCE_DIR}/Hist/libinc
+    ${PROJECT_SOURCE_DIR}/Parser/libinc
+    ${PROJECT_SOURCE_DIR}/cpythonprototype/libinc
+    ${PROJECT_SOURCE_DIR}/RedisIO/libinc
+    ${PROJECT_SOURCE_DIR}/DimRecv/libinc
+    ${CMAKE_SOURCE_DIR}/extern/dim/inc
+    ${CMAKE_SOURCE_DIR}/extern/
+    ${EXTERNAL_INSTALL_LOCATION}/include
+)
Index: src/DimRecv/libinc/DAQInterface.hh
===================================================================
--- src/DimRecv/libinc/DAQInterface.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/DimRecv/libinc/DAQInterface.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,86 @@
+#ifndef DimRecv_DAQInterface_hh
+#define DimRecv_DAQInterface_hh
+
+// DimClient class
+//Inform the Server that this client would like the Server to execute an ExitHandler when it dies.
+// static setExitHandler ( char * serverName) ;
+// Instruct the Server to execute the virtual method errorHandler whenever the DIM server sees an error.
+// If no errorHandler is declared the DIM server prints an error message.
+// static addErrorHandler (DimErrorHandler *handler ) ;
+
+
+#include <dic.hxx>
+#include "UtilsException.hh"
+
+#include <iostream>
+#include <string>
+#include <future>
+#include <mutex>
+#include <vector>
+#include <chrono>
+#include <utility>      // std::pair
+
+#include "DaqTask.hh"
+
+// using tasktype = std::pair < std::future<unsigned>, std::vector<uint8_t> > ;
+
+class ErrorHandler : public DimErrorHandler
+{
+	void errorHandler(int severity, int code, char *msg)
+	{
+		int index = 0;
+		char **services;
+		if(code)
+    {
+
+    }
+		std::cout << severity << " " << msg << std::endl;
+		services = DimClient::getServerServices();
+		std::cout<< "from "<< DimClient::getServerName() << " services:" << std::endl;
+		while(services[index])
+		{
+			std::cout << services[index] << std::endl;
+			index++;
+		}
+	}
+public:
+	ErrorHandler() {DimClient::addErrorHandler(this);}
+};
+
+
+//This is the base class for decoding detector raw data.
+class DAQInterface: public DimClient {
+public:
+  DAQInterface(std::string daq_name="DAQ");
+  virtual ~DAQInterface();
+  void infoHandler() override;
+	void setActiveStatus(bool act) ;
+
+
+private:
+	//remove finished calculation in m_tasks to release resources,
+	//based on the Erase–remove idiom.
+	void houseKeeping();
+
+	// static std::vector<DAQInterface*> m_instances;
+
+  bool m_active;
+	//dim
+  ErrorHandler m_errhdl;
+  DimStampedInfo m_daq_data;
+
+  // task and info
+  std::vector<DaqTask> m_tasks;
+  int64_t m_num_trigger, m_received_byte, m_processed_byte;
+	int64_t m_processed_event;
+
+	// house keeping
+  std::mutex m_task_mutex, m_hist_mutex;
+  std::chrono::milliseconds m_houskpg_intvl_ms;
+	std::chrono::system_clock::time_point m_start_time;
+
+  std::thread m_hk_thread;
+
+};
+
+#endif
Index: src/DimRecv/libinc/DaqTask.hh
===================================================================
--- src/DimRecv/libinc/DaqTask.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/DimRecv/libinc/DaqTask.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,38 @@
+#ifndef DimRecv_DaqTask_hh
+#define DimRecv_DaqTask_hh
+
+#include <future>
+#include <vector>
+#include <mutex>
+
+class DaqTask {
+public:
+  DaqTask(uint8_t* begin, uint8_t* end);
+  virtual ~DaqTask();
+
+  // Move initialization
+  DaqTask(DaqTask&& other) ;
+  // Copy initialization
+  DaqTask(const DaqTask& other) ;
+  // Move assignment
+  DaqTask& operator = (DaqTask&& other) ;
+  // Copy assignment
+  DaqTask& operator = (const DaqTask& other) ;
+
+
+  uint64_t readyAndValid();
+  void start();
+  void setTime(int second, int ms);
+  void getTime(int &second, int &ms) const;
+
+
+private:
+  std::vector<uint8_t> m_data;
+  std::shared_future<uint64_t> m_future;
+  int m_time_s, m_time_ms; //since 1/1/1970, in seconds
+  mutable std::mutex m_run_mutex;
+
+  uint64_t run();
+};
+
+#endif
Index: src/DimRecv/libinc/DimServer.hh
===================================================================
--- src/DimRecv/libinc/DimServer.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/DimRecv/libinc/DimServer.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,32 @@
+#ifndef DimRecv_DimServer_hh
+#define DimRecv_DimServer_hh
+
+#include <stdint.h>
+#include <vector>
+#include <future>
+#include <mutex>
+#include <unordered_map>
+#include "UtilsException.hh"
+
+
+//This is the base class for decoding detector raw data.
+class DimServer {
+
+public:
+  DimServer();
+  virtual ~DimServer();
+
+private:
+  unsigned int m_dimServerID;
+  static std::mutex m_mutex;
+  static unsigned dostuff();
+  static void eventDataArrived(void *tag, void *buf, int *size);
+  static std::vector< std::future<unsigned> > m_tasks;
+  static std::vector< std::vector<uint8_t> > m_data;
+
+};
+
+std::mutex DimServer::m_mutex;
+std::vector< std::future<unsigned> > DimServer::m_tasks;
+std::vector< std::vector<uint8_t> > DimServer::m_data;
+#endif
Index: src/DimRecv/libinc/Retriver.hh
===================================================================
--- src/DimRecv/libinc/Retriver.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/DimRecv/libinc/Retriver.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,32 @@
+#ifndef DimRecv_Retriver_hh
+#define DimRecv_Retriver_hh
+
+#include <stdint.h>
+#include <vector>
+#include <future>
+#include <mutex>
+#include <unordered_map>
+#include "UtilsException.hh"
+
+
+//This is the base class for decoding detector raw data.
+class Retriver {
+
+public:
+  Retriver();
+  virtual ~Retriver();
+
+private:
+  unsigned int m_dimServerID;
+  static std::mutex m_mutex;
+  static unsigned dostuff();
+  static void eventDataArrived(void *tag, void *buf, int *size);
+  static std::vector< std::future<unsigned> > m_tasks;
+  static std::vector< std::vector<uint8_t> > m_data;
+
+};
+
+std::mutex Retriver::m_mutex;
+std::vector< std::future<unsigned> > Retriver::m_tasks;
+std::vector< std::vector<uint8_t> > Retriver::m_data;
+#endif
Index: src/DimRecv/libsrc/DAQInterface.cc
===================================================================
--- src/DimRecv/libsrc/DAQInterface.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/DimRecv/libsrc/DAQInterface.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,109 @@
+#include "DAQInterface.hh"
+#include <iostream>
+#include <algorithm>  // remove_if
+#include <time.h>
+#include <csignal>
+
+DAQInterface::DAQInterface(std::string daq_name)
+: DimClient(), m_active(true), m_errhdl()
+, m_daq_data(daq_name.c_str(),const_cast<char *>("daq"), this)
+, m_num_trigger(0), m_received_byte(0), m_processed_byte(0), m_processed_event(0)
+, m_houskpg_intvl_ms(1000), m_start_time(std::chrono::system_clock::now())
+{
+  addErrorHandler(&m_errhdl);
+  std::cout << "service name is " << daq_name << std::endl;
+  // setExitHandler("RUN_INFO");
+  m_hk_thread = std::thread(&DAQInterface::houseKeeping, this);
+}
+
+DAQInterface::~DAQInterface()
+{
+  if(m_hk_thread.joinable())
+    m_hk_thread.detach();
+}
+
+
+void DAQInterface::setActiveStatus(bool act)
+{
+  std::lock_guard<std::mutex> guard(m_task_mutex);
+  m_active=act;
+}
+
+void DAQInterface::infoHandler()
+{
+  std::lock_guard<std::mutex> guard(m_task_mutex);
+  // auto start = std::chrono::system_clock::now();
+
+  DimInfo *curr = getInfo(); // get current DimInfo address
+  if(curr == &m_daq_data && m_active)
+  {
+    //if(!m_num_trigger) return; //info handler will be triggered by constructor in dim v20
+    unsigned dsize  = curr->getSize();
+    m_received_byte += dsize;
+
+    uint8_t *data = static_cast<uint8_t*>(curr->getData());
+    std::vector<uint8_t> buf(data, data+dsize);
+
+    m_tasks.emplace_back( DaqTask(data, data+dsize));
+    m_tasks.back().setTime(curr->getTimestamp(), curr->getTimestampMillisecs());
+    m_tasks.back().start();
+  }
+  else   {
+    //fixme:log
+  }
+
+  m_num_trigger++;
+
+  // auto end = std::chrono::system_clock::now();
+  // std::chrono::duration<double> elapsed_seconds = end-start;
+  // std::time_t end_time = std::chrono::system_clock::to_time_t(end);
+  // std::cout << "elapsed time: " << elapsed_seconds.count()*1000 << "ms\n";
+
+}
+
+void DAQInterface::houseKeeping()
+{
+  std::cout <<"Starting house kepping ..." << std::endl;
+
+  while (1) {
+    std::this_thread::sleep_for(m_houskpg_intvl_ms);
+    if(m_tasks.empty()) continue;
+
+    std::lock_guard<std::mutex> guard(m_task_mutex);
+
+    unsigned processed =0;
+
+    auto newend = std::remove_if(m_tasks.begin(), m_tasks.end(),
+    [&](DaqTask &atask ) -> bool
+    {
+      uint64_t processed = atask.readyAndValid();
+      if(! processed )
+        return false;
+      else
+      {
+        int bytes = processed & 0xffffffff;
+        int events = (processed >> 32) & 0xffffffff;
+        m_processed_byte += bytes;
+        m_processed_event += events;
+        return true;
+      }
+    });
+
+    if(newend == m_tasks.end() ) continue;
+
+    unsigned deleted = m_tasks.end() - newend;
+    m_tasks.erase(newend, m_tasks.end());
+
+    std::cout <<  '\r' << "processed " << m_processed_byte/1024/1024  << "MB. Received "
+    << m_processed_byte/1024/1024 << "MB. Processed " <<  m_processed_byte*100./m_received_byte <<"%. ";
+
+    std::chrono::duration<double> elapsed_seconds = std::chrono::system_clock::now()-m_start_time;
+		double t = elapsed_seconds.count();
+
+    std::cout << "processed " << m_processed_event  << " events. Event rate "
+    <<  m_processed_event/t <<" /s. ";
+
+    std::cout  << m_tasks.size() << " tasks in queue, " << deleted << " finished tasks"
+    << std::flush << std::flush << std::flush;
+  }
+}
Index: src/DimRecv/libsrc/DaqTask.cc
===================================================================
--- src/DimRecv/libsrc/DaqTask.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/DimRecv/libsrc/DaqTask.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,122 @@
+#include "DaqTask.hh"
+#include <thread>
+#include <chrono>
+#include <iostream>
+#include "PackageHe3.hh"
+
+DaqTask::DaqTask(uint8_t* begin, uint8_t* end)
+:m_data(begin, end), m_time_s(0), m_time_ms(0)
+{
+
+}
+
+DaqTask::~DaqTask()
+{
+
+}
+
+
+uint64_t DaqTask::readyAndValid()
+{
+  std::lock_guard<std::mutex> guard(m_run_mutex);
+
+  if(!m_future.valid())
+    return 0;
+  auto status = m_future.wait_for(std::chrono::milliseconds(0));
+  return status == std::future_status::ready ? m_future.get() : 0;
+}
+
+void DaqTask::start()
+{
+  std::lock_guard<std::mutex> guard(m_run_mutex);
+  m_future = std::async(std::launch::async, &DaqTask::run, this).share();
+}
+
+uint64_t DaqTask::run()
+{
+  // printf("running. m_data size %zu\n", m_data.size());
+
+  std::lock_guard<std::mutex> guard(m_run_mutex);
+
+  const uint8_t * abuf = m_data.data();
+  int event_cnt=0;
+  std::vector<Parser::HitInfo> hitinfo;
+  Parser::PackageHe3 he3(0.);
+
+  while(he3.readNextPackage(abuf, m_data.data()+m_data.size(), hitinfo))
+  {
+    event_cnt+=hitinfo.size();
+  }
+
+  // if(event_cnt)
+  // {
+  //   char fn[200];
+  //   sprintf(fn,"data/%d_%d.dat",m_time_s, m_time_ms);
+  //   FILE *datafile = fopen(fn, "wb");
+  //   fwrite (m_data.data() , sizeof(char), m_data.size(), datafile);
+  //   fclose(datafile);
+  //   // printf("%s, %d events\n", fn, event_cnt);
+  // }
+
+  uint64_t shiftedEvt = event_cnt*4294967296;  //shifting 32 bits to the higher order
+  return (uint64_t)m_data.size() +  shiftedEvt;
+}
+
+void DaqTask::setTime(int second, int ms)
+{
+  std::lock_guard<std::mutex> guard(m_run_mutex);
+  m_time_s = second;
+  m_time_ms = ms;
+}
+void DaqTask::getTime(int &second, int &ms) const
+{
+  std::lock_guard<std::mutex> guard(m_run_mutex);
+  second = m_time_s;
+  ms = m_time_ms;
+}
+
+// Move initialization
+DaqTask::DaqTask(DaqTask&& other) {
+  std::lock_guard<std::mutex> lock(other.m_run_mutex);
+  m_data = std::move(other.m_data);
+  m_future = std::move(other.m_future);
+  m_time_s = other.m_time_s;
+  m_time_ms = other.m_time_ms;
+  other.m_time_s = 0;
+  other.m_time_ms = 0;
+};
+
+// Copy initialization
+DaqTask::DaqTask(const DaqTask& other) {
+  std::lock_guard<std::mutex> lock(other.m_run_mutex);
+  m_data = other.m_data;
+  m_future = other.m_future;
+  m_time_s = other.m_time_s;
+  m_time_ms = other.m_time_ms;
+};
+
+// Move assignment
+DaqTask& DaqTask::operator = (DaqTask&& other) {
+  std::lock(m_run_mutex, other.m_run_mutex);
+  std::lock_guard<std::mutex> self_lock(m_run_mutex, std::adopt_lock);
+  std::lock_guard<std::mutex> other_lock(other.m_run_mutex, std::adopt_lock);
+  m_data = std::move(other.m_data);
+  m_future = std::move(other.m_future);
+  m_time_s = other.m_time_s;
+  m_time_ms = other.m_time_ms;
+  other.m_time_s = 0;
+  other.m_time_ms = 0;
+  return *this;
+};
+
+// Copy assignment
+DaqTask& DaqTask::operator = (const DaqTask& other) {
+  std::lock(m_run_mutex, other.m_run_mutex);
+  std::lock_guard<std::mutex> self_lock(m_run_mutex, std::adopt_lock);
+  std::lock_guard<std::mutex> other_lock(other.m_run_mutex, std::adopt_lock);
+  m_data = other.m_data;
+  m_future = other.m_future;
+  m_time_s = other.m_time_s;
+  m_time_ms = other.m_time_ms;
+  return *this;
+};
Index: src/DimRecv/libsrc/DimServer.cc
===================================================================
--- src/DimRecv/libsrc/DimServer.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/DimRecv/libsrc/DimServer.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,70 @@
+#include "DimServer.hh"
+#ifdef __cplusplus
+extern "C"{
+#include "dic.h"
+}
+#endif
+
+
+DimServer::DimServer()
+:m_dimServerID(0)
+{
+  char* envNode = getenv("DIM_DNS_NODE");
+  char* envPort = getenv("DIM_DNS_PORT");
+  // if(envNode and envPort) {
+  // LogInfo << "DIM_DNS_NODE: " << envNode << std::endl;
+  // LogInfo << "DIM_DNS_PORT: " << envPort << std::endl;
+  static int no_link = -1;
+  //xx. https://dim.web.cern.ch/dimCdic.html#dic_info_service_stamped
+  // unsigned int dic_info_service_stamped (name, type, timeout, address, size, user_routine, tag, fill_address, fill_size)
+  // 1. char *name: service name, same name used by server when declaring the service.
+  // 2. int type;
+  //    Type of service, constants defined are: ONCE_ONLY, TIMED or MONITORED:
+  //    MONITORED: The client will receive the data when the server updates it (by calling dis_update_service()),
+  //  but also at regular intervals if the "timeout" parameter is different from 0. The "timeout" parameter can be set to 0 to receive data only on server update.
+  // 3. int timeout;
+  //   For a TIMED or MONITORED service "timeout" indicates the time interval the server should use to send new data, for ONCE_ONLY  services it indicates the time after
+  //   which the service is considered to have failed.
+  // 4. int *address;
+  //    Address of the buffer where to store the data when the service returns from the server. This parameter can be set to 0 and only the callback routine will be executed.
+  // 5. int size;
+  //    The size in bytes of the previous buffer (if specified).
+  // 6. void *user_routine;
+  //    The address of a routine to be executed when new data is returned from the server, the parameters of this routine will be specified later in this document.
+  //   Can be set to 0 if no callback routine is necessary.
+  // 7. long tag;
+  //    A parameter to be sent to the user_routine in order to identify the service that has completed.
+  // 8. int *fill_address;
+  //    Address of a buffer containing data to be stored in the service buffer or passed to the callback routine in case the service doesn't succeed.
+  // 9. int fill_size;
+  //    The size in bytes of the previous buffer.
+
+  // return unsigned int service_id;
+  // The service identifier, to be used when (if) releasing the service.
+
+  m_dimServerID = dic_info_service_stamped( "what is the name??", MONITORED, 0, 0, 0,
+   &DimServer::eventDataArrived, 1200, &no_link, 4 );
+  // ERROR_THROW("Failed to establish dim connection");
+  // else throw SniperException("DIM_DNS_NODE or DIM_DNS_PORT undefined!");
+}
+
+DimServer::~DimServer()
+{
+
+}
+
+unsigned DimServer::dostuff()
+{
+  return 1;
+}
+
+void DimServer::eventDataArrived(void *tag, void *buf, int *size )
+{
+  if( *static_cast<const int*>(tag) == 1200)
+  {
+    std::unique_lock<std::mutex> mlock(m_mutex);
+    m_data.emplace_back(std::vector<uint8_t> ( (uint8_t*)buf, (uint8_t*)buf+(*size) ) );
+    // std::future<unsigned> task = std::async(std::launch::async, DimServer::dostuff);
+    m_tasks.emplace_back(std::async(std::launch::async, DimServer::dostuff));
+  }
+}
Index: src/DimRecv/libsrc/Retriver.cc
===================================================================
--- src/DimRecv/libsrc/Retriver.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/DimRecv/libsrc/Retriver.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,70 @@
+#include "Retriver.hh"
+#ifdef __cplusplus
+extern "C"{
+#include "dic.h"
+}
+#endif
+
+
+Retriver::Retriver()
+:m_dimServerID(0)
+{
+  char* envNode = getenv("DIM_DNS_NODE");
+  char* envPort = getenv("DIM_DNS_PORT");
+  // if(envNode and envPort) {
+  // LogInfo << "DIM_DNS_NODE: " << envNode << std::endl;
+  // LogInfo << "DIM_DNS_PORT: " << envPort << std::endl;
+  static int no_link = -1;
+  //xx. https://dim.web.cern.ch/dimCdic.html#dic_info_service_stamped
+  // unsigned int dic_info_service_stamped (name, type, timeout, address, size, user_routine, tag, fill_address, fill_size)
+  // 1. char *name: service name, same name used by server when declaring the service.
+  // 2. int type;
+  //    Type of service, constants defined are: ONCE_ONLY, TIMED or MONITORED:
+  //    MONITORED: The client will receive the data when the server updates it (by calling dis_update_service()),
+  //  but also at regular intervals if the "timeout" parameter is different from 0. The "timeout" parameter can be set to 0 to receive data only on server update.
+  // 3. int timeout;
+  //   For a TIMED or MONITORED service "timeout" indicates the time interval the server should use to send new data, for ONCE_ONLY  services it indicates the time after
+  //   which the service is considered to have failed.
+  // 4. int *address;
+  //    Address of the buffer where to store the data when the service returns from the server. This parameter can be set to 0 and only the callback routine will be executed.
+  // 5. int size;
+  //    The size in bytes of the previous buffer (if specified).
+  // 6. void *user_routine;
+  //    The address of a routine to be executed when new data is returned from the server, the parameters of this routine will be specified later in this document.
+  //   Can be set to 0 if no callback routine is necessary.
+  // 7. long tag;
+  //    A parameter to be sent to the user_routine in order to identify the service that has completed.
+  // 8. int *fill_address;
+  //    Address of a buffer containing data to be stored in the service buffer or passed to the callback routine in case the service doesn't succeed.
+  // 9. int fill_size;
+  //    The size in bytes of the previous buffer.
+
+  // return unsigned int service_id;
+  // The service identifier, to be used when (if) releasing the service.
+
+  m_dimServerID = dic_info_service_stamped( "what is the name??", MONITORED, 0, 0, 0,
+   &Retriver::eventDataArrived, 1200, &no_link, 4 );
+  // ERROR_THROW("Failed to establish dim connection");
+  // else throw SniperException("DIM_DNS_NODE or DIM_DNS_PORT undefined!");
+}
+
+Retriver::~Retriver()
+{
+
+}
+
+unsigned Retriver::dostuff()
+{
+  return 1;
+}
+
+void Retriver::eventDataArrived(void *tag, void *buf, int *size )
+{
+  if( *static_cast<const int*>(tag) == 1200)
+  {
+    std::unique_lock<std::mutex> mlock(m_mutex);
+    m_data.emplace_back(std::vector<uint8_t> ( (uint8_t*)buf, (uint8_t*)buf+(*size) ) );
+    // std::future<unsigned> task = std::async(std::launch::async, Retriver::dostuff);
+    m_tasks.emplace_back(std::async(std::launch::async, Retriver::dostuff));
+  }
+}
Index: src/Hist/libinc/Hist2DMap.hh
===================================================================
--- src/Hist/libinc/Hist2DMap.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Hist/libinc/Hist2DMap.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,50 @@
+#ifndef Histogram_Hist2DMap_hh
+#define Histogram_Hist2DMap_hh
+
+#include <map>
+#include <vector>
+#include <mutex>
+
+#include "NumpyHist2D.hh"
+
+// This class reads information from a full package.
+  class Hist2DMap {
+  public:
+    Hist2DMap(unsigned nbinsx, double xmin, double xmax,
+           unsigned nbinsy, double ymin, double ymax);
+    virtual ~Hist2DMap();
+
+    inline void fill(unsigned key, double x, double y);
+    void reset();
+    std::map<unsigned, NumpyHist2D* >::const_iterator getHistMapBegin() const;
+    std::map<unsigned, NumpyHist2D* >::const_iterator getHistMapEnd() const;
+
+  private:
+    std::mutex m_histmap_mutex;
+    std::map<unsigned, NumpyHist2D* > m_histmap;
+    unsigned m_xbin;
+    double m_xl, m_xu;
+    unsigned m_ybin;
+    double m_yl, m_yu;
+  };
+
+
+
+inline void Hist2DMap::fill(unsigned key, double x, double y)
+{
+  // Lock The Data structure
+  std::lock_guard<std::mutex> guard(m_histmap_mutex);
+
+  auto it_hist = m_histmap.find(key);
+  NumpyHist2D *histpt;
+  //create a new histogram for a new key
+  if(it_hist==m_histmap.end()) {
+    histpt = new NumpyHist2D(m_xbin, m_xl, m_xu, m_ybin, m_yl, m_yu);
+    m_histmap[key] = histpt;
+  }
+  else
+    histpt = it_hist->second;
+
+  histpt->fill(x,y);
+}
+#endif
Index: src/Hist/libinc/NumpyHist1D.hh
===================================================================
--- src/Hist/libinc/NumpyHist1D.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Hist/libinc/NumpyHist1D.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,26 @@
+#ifndef NumpyHist1D_hh
+#define NumpyHist1D_hh
+
+#include "NumpyHistBase.hh"
+
+
+class NumpyHist1D : public NumpyHistBase {
+public:
+  explicit NumpyHist1D(unsigned nbins, double xmin, double xmax);
+  virtual ~NumpyHist1D();
+
+  unsigned dimension() const override { return 1; }  ;
+  void serialise(std::string &serialised) const override;
+
+  void fill(double val);
+  void fill(double val, double weight);
+
+private:
+  double m_binfactor;
+
+};
+
+
+
+
+#endif
Index: src/Hist/libinc/NumpyHist2D.hh
===================================================================
--- src/Hist/libinc/NumpyHist2D.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Hist/libinc/NumpyHist2D.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,32 @@
+#ifndef NumpyHist2D_hh
+#define NumpyHist2D_hh
+
+#include "NumpyHistBase.hh"
+
+
+class NumpyHist2D : public NumpyHistBase {
+public:
+
+  explicit NumpyHist2D(unsigned nxbins, double xmin, double xmax,
+              unsigned nybins, double ymin, double ymax);
+  virtual ~NumpyHist2D();
+
+  unsigned dimension() const override { return 2; }  ;
+  void serialise(std::string &serialised) const override;
+
+  void fill(double xval, double yval);
+  void fill(double xval, double yval, double weight);
+
+private:
+  double m_xbinfactor, m_ybinfactor;
+  double m_ymin;
+  double m_ymax;
+  uint32_t m_xnbins, m_ynbins;
+
+
+};
+
+
+
+
+#endif
Index: src/Hist/libinc/NumpyHistBase.hh
===================================================================
--- src/Hist/libinc/NumpyHistBase.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Hist/libinc/NumpyHistBase.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,57 @@
+#ifndef NumpyHistBase_hh
+#define NumpyHistBase_hh
+
+#include <string>
+#include <cassert>
+#include <vector>
+#include <stdexcept>
+#include <mutex>
+
+class NumpyHistBase {
+public:
+  explicit NumpyHistBase(unsigned nbins);
+  virtual ~NumpyHistBase();
+
+  double getXMin() const {return m_xmin;}
+  double getXMax() const {return m_xmax;}
+  double getIntegral() const {return m_sumW;};
+  double getOverflow() const {return m_overflow;};
+  double getUnderflow() const {return m_underflow;};
+  double getMinFilled() const {return m_minfilled;};
+  double getMaxFilled() const {return m_maxfilled;};
+  double getNBins() const {return m_nbins;};
+
+  void scale(double scalefact);
+  void reset();
+  void save(const std::string &filename) const;
+
+  virtual unsigned dimension() const = 0;
+  virtual void serialise(std::string &serialised) const = 0;
+
+protected:
+  void serialise_numpy(const std::vector<uint64_t> &shape, std::string &serialised) const;
+  mutable std::mutex m_hist_mutex;
+  std::vector<double> m_data;
+  double m_xmin;
+  double m_xmax;
+  double m_sumW;
+  double m_underflow;
+  double m_overflow;
+  double m_minfilled;
+  double m_maxfilled;
+  uint32_t m_nbins;
+
+private:
+  //Copy/assignment are forbidden:
+  // Move initialization
+  NumpyHistBase(NumpyHistBase&& other) = delete;
+  // Copy initialization
+  NumpyHistBase(const NumpyHistBase& other) = delete;
+  // Move assignment
+  NumpyHistBase& operator = (NumpyHistBase&& other) = delete;
+  // Copy assignment
+  NumpyHistBase& operator = (const NumpyHistBase& other) = delete;
+
+};
+
+#endif
Index: src/Hist/libsrc/Hist2DMap.cc
===================================================================
--- src/Hist/libsrc/Hist2DMap.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Hist/libsrc/Hist2DMap.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,34 @@
+#include "Hist2DMap.hh"
+#include "UtilsException.hh"
+#include "NumpyHist2D.hh"
+
+Hist2DMap::Hist2DMap(unsigned nbinx, double xmin, double xmax,
+       unsigned nbiny, double ymin, double ymax)
+: m_xbin(nbinx), m_xl(xmin), m_xu(xmax), m_ybin(nbiny), m_yl(ymin), m_yu(ymax)
+{
+}
+
+Hist2DMap::~Hist2DMap()
+{
+  auto it = m_histmap.begin();
+  for ( ; it != m_histmap.end(); ++it)
+     delete it->second;
+}
+
+void Hist2DMap::reset()
+{
+  auto it = m_histmap.begin();
+  for ( ; it != m_histmap.end(); ++it)
+     it->second->reset();
+}
+
+
+std::map<unsigned, NumpyHist2D* >::const_iterator Hist2DMap::getHistMapBegin() const
+{
+  return m_histmap.begin();
+}
+
+std::map<unsigned, NumpyHist2D* >::const_iterator Hist2DMap::getHistMapEnd() const
+{
+  return m_histmap.end();
+}
Index: src/Hist/libsrc/NumpyHist1D.cc
===================================================================
--- src/Hist/libsrc/NumpyHist1D.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Hist/libsrc/NumpyHist1D.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,55 @@
+#include "NumpyHist1D.hh"
+#include <cmath>
+#include <vector>
+
+NumpyHist1D::NumpyHist1D(unsigned nbins, double xmin, double xmax)
+:NumpyHistBase(nbins), m_binfactor(nbins/(xmax-xmin))
+{
+  m_xmin=xmin, m_xmax=xmax, m_nbins=nbins;
+}
+
+NumpyHist1D::~NumpyHist1D()
+{
+}
+
+
+void NumpyHist1D::serialise(std::string &serialised) const
+{
+  std::lock_guard<std::mutex> guard(m_hist_mutex);
+  serialise_numpy(std::vector<uint64_t>{m_nbins}, serialised);
+}
+
+//Normal filling:
+void NumpyHist1D::fill(double val)
+{
+  std::lock_guard<std::mutex> guard(m_hist_mutex);
+
+  if(val<m_xmin) {
+    m_underflow++;
+    return;
+  }
+  else if(val>m_xmax) {
+    m_overflow++;
+    return;
+  }
+
+  unsigned i = floor((val-m_xmin)*m_binfactor);
+  ++m_data[i];
+}
+
+void NumpyHist1D::fill(double val, double w)
+{
+  std::lock_guard<std::mutex> guard(m_hist_mutex);
+
+  if(val<m_xmin) {
+    m_underflow += w;
+    return;
+  }
+  else if(val>m_xmax) {
+    m_overflow += w;
+    return;
+  }
+
+  unsigned i = floor((val-m_xmin)*m_binfactor);
+  m_data[i] += w;
+}
Index: src/Hist/libsrc/NumpyHist2D.cc
===================================================================
--- src/Hist/libsrc/NumpyHist2D.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Hist/libsrc/NumpyHist2D.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,63 @@
+#include "NumpyHist2D.hh"
+#include <cmath>
+#include <vector>
+#include <iostream>
+
+NumpyHist2D::NumpyHist2D(unsigned xnbins, double xmin, double xmax,
+                         unsigned ynbins, double ymin, double ymax)
+:NumpyHistBase(xnbins*ynbins), m_xbinfactor(xnbins/(xmax-xmin)),
+m_ybinfactor(ynbins/(ymax-ymin))
+{
+  m_xmin=xmin, m_xmax=xmax, m_xnbins=xnbins;
+  m_ymin=ymin, m_ymax=ymax, m_ynbins=ynbins;
+  m_nbins = m_xnbins * m_ynbins;
+
+  // std::invalid_argument("data can not be shaped by the given shape vector");
+
+}
+
+NumpyHist2D::~NumpyHist2D()
+{
+}
+
+void NumpyHist2D::serialise(std::string &serialised) const
+{
+  std::lock_guard<std::mutex> guard(m_hist_mutex);
+
+  serialise_numpy(std::vector<uint64_t>{m_xnbins, m_ynbins}, serialised);
+}
+
+//Normal filling:
+void NumpyHist2D::fill(double xval, double yval)
+{
+  std::lock_guard<std::mutex> guard(m_hist_mutex);
+
+  if(xval<m_xmin ||  yval<m_ymin) {
+    m_underflow++;
+    return;
+  }
+  else if(xval>m_xmax || yval>m_ymax) {
+    m_overflow++;
+    return;
+  }
+  unsigned ix = floor((xval-m_xmin)*m_xbinfactor);
+  unsigned iy = floor((yval-m_ymin)*m_ybinfactor);
+  ++m_data[ix*m_ynbins + iy];
+}
+
+void NumpyHist2D::fill(double xval, double yval, double w)
+{
+  std::lock_guard<std::mutex> guard(m_hist_mutex);
+
+  if(xval<m_xmin ||  yval<m_ymin) {
+    m_underflow+=w;
+    return;
+  }
+  else if(xval>m_xmax || yval>m_ymax) {
+    m_overflow+=w;
+    return;
+  }
+  unsigned ix = floor((xval-m_xmin)*m_xbinfactor);
+  unsigned iy = floor((yval-m_ymin)*m_ybinfactor);
+  m_data[iy*m_xnbins + ix]+=w;
+}
Index: src/Hist/libsrc/NumpyHistBase.cc
===================================================================
--- src/Hist/libsrc/NumpyHistBase.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Hist/libsrc/NumpyHistBase.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,63 @@
+#include "NumpyHistBase.hh"
+#include "RedisNumpy.hh"
+#include <stdexcept>
+#include <fstream>
+
+NumpyHistBase::NumpyHistBase(unsigned nbin)
+: m_data(nbin,0.), m_xmin(0), m_xmax(0), m_sumW(0), m_underflow(0),
+ m_overflow(0),m_minfilled(0), m_maxfilled(0), m_nbins(0)
+{
+
+}
+
+NumpyHistBase::~NumpyHistBase()
+{
+}
+
+void NumpyHistBase::save(const std::string &filename) const
+{
+  std::lock_guard<std::mutex> guard(m_hist_mutex);
+
+  std::string bdata;
+  serialise(bdata);
+  std::ofstream outfile(filename, std::ofstream::binary);
+  outfile << bdata;
+  outfile.close();
+}
+
+
+void NumpyHistBase::serialise_numpy(const std::vector<uint64_t> &shape, std::string &serialise) const
+{
+  std::lock_guard<std::mutex> guard(m_hist_mutex);
+
+  uint64_t elementnum=1;
+  for(auto v:shape)
+    elementnum *= v;
+
+  if(elementnum!=m_nbins)
+    std::invalid_argument("data can not be shaped by the given shape vector");
+
+  RedisNumpy nvt;
+  nvt.makeNumpyArr(m_data, RedisNumpy::data_type::f8,
+                   shape, serialise);
+}
+
+void NumpyHistBase::scale(double scalefact)
+{
+  std::lock_guard<std::mutex> guard(m_hist_mutex);
+
+  for(unsigned i=0;i<m_nbins;i++)
+    m_data[i] *= scalefact;
+}
+
+void NumpyHistBase::reset()
+{
+  std::lock_guard<std::mutex> guard(m_hist_mutex);
+
+  std::fill(m_data.begin(), m_data.begin()+m_nbins, 0.);
+  m_sumW = 0.;
+  m_underflow = 0.;
+  m_overflow = 0.;
+  m_minfilled = 0.;
+  m_maxfilled = 0.;
+}
Index: src/Parser/libinc/PackageHe3.hh
===================================================================
--- src/Parser/libinc/PackageHe3.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libinc/PackageHe3.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,44 @@
+#ifndef Parser_PackageHe3_hh
+#define Parser_PackageHe3_hh
+
+#include <map>
+#include <mutex>
+
+#include "ParserHe3.hh"
+
+class Hist2DMap;
+
+//This class reads information from a full package.
+namespace Parser {
+  struct HitInfo {
+    double pos;
+    double t;
+    double chargesum;
+    uint32_t hit_t0;
+    uint8_t tube_id;
+    HitInfo(): pos(0.),t(0.),chargesum(0.),hit_t0(0), tube_id(0) {}
+    HitInfo(double position, double time, double chargesum,uint32_t t0, uint8_t tube)
+      : pos(position),t(time),chargesum(chargesum), hit_t0(t0), tube_id(tube) {}
+  };
+
+  //Reflectormetor uses He3 detector of 300mm length.
+  //time stamp should be divided by 80 to convert to micro-second
+  //fixme :  put m_detector_half_length and m_tof2us elsewhere
+  class EXPORT_SYMBOL PackageHe3: public ParserHe3 {
+  public:
+    PackageHe3(double threshold, double hvlength=150., double tofscale=1./80);
+
+    ~PackageHe3() override;
+    //fixme: hit position is scale by a constant 150
+    //returns false when reach the end of the data stream
+    bool readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end, std::vector<HitInfo>& hitinfo) const;
+    bool readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end, Hist2DMap &hitmap) const;
+
+    double getChargeThreshold() const;
+    void setChargeThreshold(double charge);
+  private:
+    std::mutex m_mutex;
+    double m_charge_threshold, m_detector_half_length, m_tof2us;
+  };
+}
+#endif
Index: src/Parser/libinc/PackageMWPC.hh
===================================================================
--- src/Parser/libinc/PackageMWPC.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libinc/PackageMWPC.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,52 @@
+#ifndef Parser_PackageMWPC_hh
+#define Parser_PackageMWPC_hh
+
+#include <map>
+#include "ParserMWPC.hh"
+#include <fstream>
+
+class Hist2DMap;
+
+class NumpyHist1D;
+
+
+//This class reads information from a full package.
+namespace Parser {
+  //fixme :  put m_detector_half_length and m_tof2us elsewhere
+  class EXPORT_SYMBOL PackageMWPC: public ParserMWPC {
+  public:
+    PackageMWPC(double threshold, double time_window );
+    ~PackageMWPC() override;
+
+    //returns false when reach the end of the data stream
+    bool readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end,
+                         Hist2DMap &hitmap,
+                         NumpyHist1D &qhist) const;
+    void write(std::ofstream &file, const char *filename);
+    void print() const;
+
+    double getChargeThreshold() const;
+    void setChargeThreshold(double charge);
+
+  private:
+    double m_charge_threshold;
+    uint64_t m_time_window;
+    mutable uint32_t m_last_t0;
+    mutable std::multimap<uint32_t,uint32_t> m_tof_cq_map; //<TOF, chanel+Q>
+    mutable std::vector<uint64_t> m_hit;
+
+    void pushbackRawData(unsigned eventmapnum, const uint8_t *&pt) const;
+
+    inline void getChannelCharge(uint32_t in, uint8_t& channel, uint16_t& charge ) const;
+
+  };
+
+  inline void Parser::PackageMWPC::getChannelCharge(uint32_t in, uint8_t& channel, uint16_t& charge) const
+  {
+    channel = in>>24;
+    uint16_t baseline = ((in>>12)&MASK_12) ; //fixme the document states the baseline value is the combination of 8 samples!?
+    uint16_t chage = (in&MASK_12) ;
+    charge = chage>baseline ? chage-baseline: 0  ; //fixme emit warning if overflowed
+  }
+}
+#endif
Index: src/Parser/libinc/PackageMWPCold.hh
===================================================================
--- src/Parser/libinc/PackageMWPCold.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libinc/PackageMWPCold.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,50 @@
+#ifndef Parser_PackageMWPCold_hh
+#define Parser_PackageMWPCold_hh
+
+#include <map>
+#include "ParserMWPC.hh"
+#include <fstream>
+
+  class Hist2DMap;
+  class NumpyHist1D;
+
+
+//This class reads information from a full package.
+namespace Parser {
+  //fixme :  put m_detector_half_length and m_tof2us elsewhere
+  class EXPORT_SYMBOL PackageMWPCold: public ParserMWPC {
+  public:
+    PackageMWPCold(double threshold, double time_window );
+    ~PackageMWPCold() override;
+
+    //returns false when reach the end of the data stream
+    bool readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end,
+                         Hist2DMap &hitmap,
+                         NumpyHist1D &qhist) const;
+    void write(std::ofstream &file, const char *filename);
+    void print() const;
+
+    double getChargeThreshold() const;
+    void setChargeThreshold(double charge);
+
+  private:
+    double m_charge_threshold;
+    uint64_t m_time_window;
+    mutable uint32_t m_last_t0;
+    mutable std::multimap<uint32_t,uint32_t> m_tof_cq_map; //<TOF, chanel+Q>
+
+    void pushbackRawData(unsigned eventmapnum, const uint8_t *&pt) const;
+
+    inline void getChannelCharge(uint32_t in, uint8_t& channel, uint16_t& charge ) const;
+
+  };
+
+  inline void Parser::PackageMWPCold::getChannelCharge(uint32_t in, uint8_t& channel, uint16_t& charge) const
+  {
+    channel = in>>24;
+    uint16_t baseline = ((in>>12)&MASK_12) ; //fixme the document states the baseline value is the combination of 8 samples!?
+    uint16_t chage = (in&MASK_12) ;
+    charge = chage>baseline ? chage-baseline: 0  ; //fixme emit warning if overflowed
+  }
+}
+#endif
Index: src/Parser/libinc/ParserBase.hh
===================================================================
--- src/Parser/libinc/ParserBase.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libinc/ParserBase.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,59 @@
+#ifndef Parser_ParserBase_hh
+#define Parser_ParserBase_hh
+
+#include <stdint.h>
+#include <vector>
+#include <string>
+#include "ctypes_api.hh"
+
+//This is the base class for decoding detector raw data.
+//fixme change to stream based class
+namespace EXPORT_SYMBOL Parser {
+  class ParserBase {
+  public:
+    ParserBase();
+    virtual ~ParserBase();
+
+    //read unsigned 32-bit integer from buffer
+    void read_uint32(const uint8_t*& pt, uint32_t &u32) const;
+    //slow, use with care
+    inline void read_uint32_many(const uint8_t*& pt, std::vector<uint32_t> &u32_vec, unsigned num=4) const;
+
+    //find the end position of a package
+    //Function returns true if the end position of a valid package is found
+    virtual bool findEnd(const uint8_t* pt, const uint8_t*& end) const = 0 ;
+
+    //sanity check. Slow, use with care. fixme: validation should be more detailed
+    virtual bool is_valid(const uint8_t* pt) const = 0 ;
+
+    //search for next valid package. Slow, use with care.
+    virtual bool findNextPackage(const uint8_t*& start, const uint8_t * const stop, const uint8_t*& pkgend, uint64_t &offset) const ;
+
+  public:
+    enum BIT_MASK: uint32_t {
+      MASK_4  = 0XF,
+      MASK_6  = 0X3F,
+      MASK_8  = 0XFF,
+      MASK_12  = 0XFFF,
+      MASK_14  = 0X3FFF,
+      MASK_16 = 0XFFFF,
+      MASK_20 = 0xFFFFF,
+      MASK_24 = 0XFFFFFF,
+      MASK_28 = 0XFFFFFFF
+    };
+
+  };
+
+  inline void Parser::ParserBase::read_uint32(const uint8_t*& pt, uint32_t &u32) const
+  {
+    //endian free
+    //Fixme: could be optimised after profiling
+    u32 = (*pt)<<24 ;
+    u32 += (*(++pt))<<16 ;
+    u32 += (*(++pt))<<8 ;
+    u32 += *(++pt) ;
+    pt++;
+  }
+
+}
+#endif
Index: src/Parser/libinc/ParserHe3.hh
===================================================================
--- src/Parser/libinc/ParserHe3.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libinc/ParserHe3.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,69 @@
+#ifndef Parser_ParserHe3_hh
+#define Parser_ParserHe3_hh
+
+#include <stdint.h>
+#include <vector>
+
+#include "ParserBase.hh"
+
+//This class reads segments of raw package from He3 detector.
+namespace Parser {
+
+  class EXPORT_SYMBOL ParserHe3: public ParserBase {
+  public:
+    struct Header {
+      uint8_t flag; //0xFA
+      uint8_t instrument;
+      uint8_t detector_type;
+      uint8_t module;
+      uint8_t opt_mode;
+      uint8_t fre_div_mode;
+      uint8_t data_ver;
+      uint8_t data_type;
+    };
+
+    struct Info {
+      uint32_t t0_count;
+      uint16_t hit_cnt;
+      uint16_t sample_num_n; //sampled number of points on the waveform
+      uint16_t sample_num_bl; //sampled number of points on the baseline
+      Info() : t0_count(), hit_cnt(), sample_num_n(), sample_num_bl() {}
+    };
+
+    struct Hit {
+      uint32_t time;
+      uint32_t upper_baseline;
+      uint32_t lower_baseline;
+      uint16_t upper_charge;
+      uint16_t lower_charge;
+      uint8_t tube_id;
+    };
+
+
+
+   enum FLAG: uint32_t {
+     DATA_START  = 0XE,
+     PACK_START  = 0xFA,
+     PACK_END  = 0XFB
+   };
+
+
+  public:
+    ParserHe3();
+    virtual ~ParserHe3();
+    void readHeader(const uint8_t*& pt, const Header *header) const;
+    void readInfo(const uint8_t*& pt, Info &info) const;
+    //input pt remain untouched
+    void printInfo(const uint8_t* pt) const;
+
+    //it_payload should point at the data flag 0xE, otherwise time is set to zero.
+    void readHit( const uint8_t*& pt_payload, Hit &hit) const ;
+
+    bool findEnd(const uint8_t* pt, const uint8_t*& end) const override;
+    bool is_valid(const uint8_t* pt) const override;
+
+  private:
+
+  };
+}
+#endif
Index: src/Parser/libinc/ParserMWPC.hh
===================================================================
--- src/Parser/libinc/ParserMWPC.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libinc/ParserMWPC.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,42 @@
+#ifndef Parser_ParserMWPC_hh
+#define Parser_ParserMWPC_hh
+
+#include <stdint.h>
+#include <vector>
+
+#include "ParserBase.hh"
+
+//This class reads segments of raw package from He3 detector.
+namespace Parser {
+
+  class EXPORT_SYMBOL ParserMWPC: public ParserBase {
+  public:
+    struct MWPCHeader {
+      uint8_t instrment, detector_type, opt_mode, freq_div_mode, data_version, data_type;
+      uint8_t model_status[6];
+      uint32_t model_bycnt[6];
+      uint32_t t0cnt, payload_bycnt,map_num;
+    };
+
+
+
+   enum MWPCFLAG: uint32_t {
+     MWPC_HIT  = 0xAA,
+     MWPC_SIG  = 0XEE1234EE
+   };
+
+
+  public:
+    ParserMWPC();
+    ~ParserMWPC() override;
+    void readHeader(const uint8_t*& pt, MWPCHeader& header) const;
+    void readHit();
+
+    bool findEnd(const uint8_t* pt, const uint8_t*& end) const override;
+    bool is_valid(const uint8_t* pt) const override;
+
+  private:
+
+  };
+}
+#endif
Index: src/Parser/libinc/ParserUtils.hh
===================================================================
--- src/Parser/libinc/ParserUtils.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libinc/ParserUtils.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,8 @@
+#ifndef Parser_Utils_hh
+#define Parser_Utils_hh
+
+namespace Parser {
+  int is_little_endian();
+}
+
+#endif
Index: src/Parser/libsrc/PackageHe3.cc
===================================================================
--- src/Parser/libsrc/PackageHe3.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libsrc/PackageHe3.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,107 @@
+#include "PackageHe3.hh"
+#include "UtilsException.hh"
+#include "Hist2DMap.hh"
+
+Parser::PackageHe3::PackageHe3(double threshold, double hvlength,double tofscale)
+:ParserHe3(), m_charge_threshold(threshold),
+m_detector_half_length(hvlength),m_tof2us(tofscale)
+{
+
+}
+
+Parser::PackageHe3::~PackageHe3()
+{
+}
+
+double Parser::PackageHe3::getChargeThreshold() const
+{
+  return m_charge_threshold;
+}
+void Parser::PackageHe3::setChargeThreshold(double charge)
+{
+  std::lock_guard<std::mutex> guard(m_mutex);
+  m_charge_threshold = charge;
+}
+
+
+bool Parser::PackageHe3::readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end, Hist2DMap &hitmap) const
+{
+  const uint8_t *package_end;
+  uint64_t offset = 0;
+  if(!findNextPackage(pt, stream_end, package_end, offset))
+    return false;
+
+  const Parser::ParserHe3::Header *header = new Parser::ParserHe3::Header();
+  readHeader(pt, header);
+  delete header;
+
+  Parser::ParserHe3::Info info;
+  readInfo(pt, info);
+  double baseline_factor = 1./info.sample_num_bl;
+
+  Parser::ParserHe3::Hit hit ;
+
+  //the next while loop breaks when pt==package_end-8
+  while (pt != package_end-8) {
+    error_assert(pt<package_end-8); //shouldn't really happen
+    readHit(pt,hit);
+    double upper = hit.upper_charge - hit.upper_baseline*baseline_factor;
+    double lower = hit.lower_charge - hit.lower_baseline*baseline_factor;
+    double tot = upper + lower;
+    //fixme: why tot is sometimes zero?
+    if(!tot || tot<m_charge_threshold)
+      continue;
+    else {
+      hitmap.fill(hit.tube_id, hit.time*m_tof2us ,m_detector_half_length*( 1 + (upper-lower)/tot ) );
+
+        // printf("pos %g, time stamp %d , tube_id %d\n", 150.*( 1 + (upper-lower)/tot ) ,hit.time, hit.tube_id );
+      }
+  }
+  pt = package_end;
+
+  //printf("left %ld, package_end %p, stream_end %p\n", stream_end-package_end, package_end, stream_end);
+  return package_end==stream_end?false:true;
+}
+
+
+bool Parser::PackageHe3::readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end, std::vector<HitInfo>& hitinfo) const
+{
+  const uint8_t *package_end;
+  uint64_t offset=0;
+
+  if(!findNextPackage(pt, stream_end, package_end, offset))
+    return false;
+
+  const Parser::ParserHe3::Header *header = new Parser::ParserHe3::Header();
+  readHeader(pt, header);
+  delete header;
+
+  Parser::ParserHe3::Info info;
+  readInfo(pt, info);
+  double baseline_factor = 1./info.sample_num_bl;
+
+  Parser::ParserHe3::Hit hit ;
+  std::vector<HitInfo> temp;
+  std::swap(temp,hitinfo);
+  hitinfo.reserve(info.hit_cnt);
+
+  //the next while loop breaks when pt==package_end-8
+  while (pt != package_end-8) {
+    error_assert(pt<package_end-8); //shouldn't really happen
+    readHit(pt,hit);
+    double upper = hit.upper_charge - hit.upper_baseline*baseline_factor;
+    double lower = hit.lower_charge - hit.lower_baseline*baseline_factor;
+    double tot = upper + lower;
+    if(!tot || tot<m_charge_threshold)
+      continue;
+    else {
+        hitinfo.push_back(HitInfo( m_detector_half_length*( 1 + (upper-lower)/tot ) ,
+        hit.time*m_tof2us,tot, info.t0_count, hit.tube_id));
+        // printf("pos %g, time stamp %d , tube_id %d\n", 150.*( 1 + (upper-lower)/tot ) ,hit.time, hit.tube_id );
+      }
+  }
+  pt = package_end;
+
+  //printf("left %ld, package_end %p, stream_end %p\n", stream_end-package_end, package_end, stream_end);
+  return package_end==stream_end?false:true;
+}
Index: src/Parser/libsrc/PackageMWPC.cc
===================================================================
--- src/Parser/libsrc/PackageMWPC.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libsrc/PackageMWPC.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,168 @@
+#include "PackageMWPC.hh"
+#include <iostream>       // std::cout
+#include <bitset>
+#include <algorithm>
+#include <cmath>
+
+#include "UtilsException.hh"
+#include "Hist2DMap.hh"
+#include "NumpyHist1D.hh"
+
+Parser::PackageMWPC::PackageMWPC(double threshold, double time_window)
+:ParserMWPC(), m_charge_threshold(threshold), m_time_window(time_window), m_last_t0(0)
+{
+}
+
+Parser::PackageMWPC::~PackageMWPC()
+{
+}
+unsigned eventcnt = 0;
+
+bool Parser::PackageMWPC::readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end,
+  Hist2DMap &hitmap, NumpyHist1D &qhist) const
+{
+  //a new package eventDataArrived
+  //we first check if this package and the data in buffer are from the same T0 peroid
+  //if yes, accumulate package data into the buffer
+  //otherwise, process the old buffer and clean it for this package
+
+  const uint8_t *package_end;
+  uint64_t offset=0;
+  if(!findNextPackage(pt, stream_end, package_end, offset))
+    return false;
+
+  //parsing raw data
+  ParserMWPC::MWPCHeader header;
+  readHeader(pt, header);
+  unsigned mapnum = header.map_num;
+  //x chanel 50, spacing 4mm, y channel 94, spacing 2.2mm
+  // std::bitset<50> x; //In standard C++, bits are initialized with zeros
+  // std::bitset<94> y;
+
+  if(!m_last_t0)
+    m_last_t0 = header.t0cnt;
+
+  //if this is the start of a new t0 signal
+  //process whatever in the map and get ready to restart the accumulation
+  if(header.t0cnt!=m_last_t0 && !m_hit.empty())
+  {
+    //the arrived new package belongs to a subconsequente T0 event, so the old
+    // data in the buffer should be sorted and analysed
+    std::sort(m_hit.begin(), m_hit.end());
+
+    uint8_t chnl = 0;
+    uint16_t Q = 0;
+    unsigned chargeSum = 0;
+    uint32_t eventSz(0), accu_x(0), accu_y(0), accu_xw(0), accu_yw(0);
+    uint64_t hittof=m_hit.front(); //initialize for the loop
+
+    uint64_t realtwindow = m_time_window<<32;
+
+    for(auto ahit: m_hit)
+    {
+      getChannelCharge( ahit, chnl, Q);
+      if(Q<m_charge_threshold)
+        continue;
+
+      if(ahit > hittof + realtwindow ) // || it==last_item_in_map??
+      {
+        //this hit belongs to the next event
+        eventcnt++;
+
+        //fill histograms only if both x and y data are available
+        if(accu_x*accu_y)
+        {
+          //fill charge hist
+          qhist.fill(chargeSum);
+          //fill pixel histogram
+          float x = accu_xw/float(accu_x);
+          float y = accu_yw/float(accu_y);
+          hitmap.fill( 0, hittof, std::round(x) + std::round(y)*50 );
+          printf("%g;%g;%g;%d;  %d\n", y*2.2, (50-x)*4., hittof/40.0, header.t0cnt-1, eventcnt-1 );
+          assert(chargeSum==accu_x+accu_y);
+        }
+      }
+      else
+      {
+        //accumulate
+        // printf("%d %d %d %d\n",eventcnt, it->first, chnl, Q);
+        eventSz++;
+        chnl<51 ? accu_xw += chnl*Q : accu_yw += (chnl-50)*Q;
+        chnl<51 ? accu_x += Q : accu_y += Q;
+        chargeSum += Q;
+      }
+
+    }
+
+    std::vector<uint64_t>  temp; //release memory
+    m_hit.swap(temp);
+    m_last_t0=header.t0cnt;
+  }
+
+  //Sorting hit data
+  // printf("*********%d maps************\n",header.map_num);
+
+  printf("left %ld, package_end %p, stream_end %p\n", stream_end-package_end, package_end, stream_end);
+  pushbackRawData(header.map_num, package_end);
+  return package_end==stream_end?false:true;
+}
+
+
+void Parser::PackageMWPC::pushbackRawData(unsigned eventmapnum, const uint8_t *&pt) const
+{
+  uint32_t temp32=0;
+
+  for(unsigned imap=0;imap<eventmapnum;imap++)
+  {
+    error_assert(*pt == 0xAA);
+    uint32_t t = 0;
+    read_uint32(pt,t);
+    t &= MASK_24;
+    // printf("TdataID %d\n", t);
+    uint32_t eventNum = 0;
+    read_uint32(pt,eventNum);
+
+    // printf("map %d, event number %d \n",imap, eventNum);
+    for(unsigned ievt=0;ievt<eventNum;ievt++)
+    {
+      uint8_t ch = *(pt);
+
+      read_uint32(pt, temp32);
+      //error_assert(ch==*(pt));
+      uint32_t t_hi_res = temp32&MASK_24;
+
+      read_uint32(pt, temp32);
+      //fixme: there is a bug in DAQ, the secend channel num sometimes are left zero
+      temp32 = (temp32&MASK_24) + (ch<<24);
+
+      m_hit.push_back(( ((uint64_t) t_hi_res) <<32) + temp32);
+      printf("ch %d, time stamp %d\n", temp32, t_hi_res);
+    }
+  }
+
+
+}
+
+void Parser::PackageMWPC::write(std::ofstream &file, const char *filename)
+{
+  file.open(filename);
+  auto it=m_tof_cq_map.begin();
+  for(;it!=m_tof_cq_map.end();++it)
+  {
+    uint32_t temp32 = it->second;
+    file << it->first << " " << ( temp32>>24) << " "  <<( (temp32&MASK_12) - ( (temp32>>12)&MASK_12) )<< "\n";
+  }
+  file.close();
+}
+
+void Parser::PackageMWPC::print() const
+{
+  uint8_t ch = 0;
+  uint16_t Q = 0;
+  for(auto it: m_tof_cq_map)
+  {
+    getChannelCharge(it.second, ch, Q);
+    std::cout << it.first << " " << (uint16_t)ch << " " << Q << std::endl;
+  }
+  std::cout << std::endl;
+}
Index: src/Parser/libsrc/PackageMWPCold.cc
===================================================================
--- src/Parser/libsrc/PackageMWPCold.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libsrc/PackageMWPCold.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,174 @@
+#include "PackageMWPCold.hh"
+#include <iostream>       // std::cout
+#include <bitset>
+#include "UtilsException.hh"
+#include "Hist2DMap.hh"
+#include "NumpyHist1D.hh"
+#include <cmath>
+
+Parser::PackageMWPCold::PackageMWPCold(double threshold, double time_window)
+:ParserMWPC(), m_charge_threshold(threshold), m_time_window(time_window), m_last_t0(0)
+{
+}
+
+Parser::PackageMWPCold::~PackageMWPCold()
+{
+}
+
+bool Parser::PackageMWPCold::readNextPackage(const uint8_t*& pt, const uint8_t * const stream_end,
+  Hist2DMap &hitmap, NumpyHist1D &qhist) const
+{
+  unsigned eventcnt = 0;
+
+  const uint8_t *package_end;
+  uint64_t offset=0;
+  if(!findNextPackage(pt, stream_end, package_end, offset))
+    return false;
+
+  //parsing raw data
+  ParserMWPC::MWPCHeader header;
+  readHeader(pt, header);
+  unsigned mapnum = header.map_num;
+  //x chanel 50, spacing 4mm, y channel 94, spacing 2.2mm
+  // std::bitset<50> x; //In standard C++, bits are initialized with zeros
+  // std::bitset<94> y;
+
+  if(!m_last_t0)
+    m_last_t0 = header.t0cnt;
+
+  //if this is the start of a new t0 signal
+  //process whatever in the map and get ready to restart the accumulation
+  if(header.t0cnt!=m_last_t0 && !m_tof_cq_map.empty())//if it is the beginning of the next frame, process data
+  {
+    // print();
+    uint8_t chnl = 0;
+    uint16_t Q = 0;
+    unsigned chargeSum = 0;
+    uint32_t hittof=m_tof_cq_map.begin()->first; //initialize the for loop
+    auto last_item_in_map = --(m_tof_cq_map.end());
+    uint32_t eventSz(0), accu_x(0), accu_y(0), accu_xw(0), accu_yw(0);
+
+    for(auto it=m_tof_cq_map.begin();it!=m_tof_cq_map.end();++it)
+    {
+      getChannelCharge(it->second, chnl, Q);
+      if(Q<m_charge_threshold) continue;
+
+      // test if this hit is the new start of next event
+      if(it->first>hittof + m_time_window || it==last_item_in_map)
+      {
+        //finish  accumulation and fill map
+        if(it==last_item_in_map)
+        {
+          //this hit belongs to this event, this item must be accumulated in
+          //this event
+          eventSz++;
+          chnl<51 ? accu_xw += chnl*Q : accu_yw += (chnl-50)*Q;
+          chnl<51 ? accu_x += Q : accu_y += Q;
+          chargeSum += Q;
+        }
+
+        // printf("%d %d %d %d\n",eventcnt, it->first, chnl, Q);
+        eventcnt++;
+
+        if(accu_x*accu_y && eventSz>3)
+        {
+          //fill charge hist
+          qhist.fill(chargeSum);
+          //fill pixel histogram
+          float x = accu_xw/float(accu_x);
+          float y = accu_yw/float(accu_y);
+          hitmap.fill( 0, hittof, std::round(x) + std::round(y)*50 );
+          printf("%g;%g;%g;%d;  %d\n", y*2.2, (50-x)*4., hittof/40.0, header.t0cnt-1, eventcnt-1 );
+          assert(chargeSum==accu_x+accu_y);
+        }
+
+        if(it!=last_item_in_map)
+        {
+          //prepare next event
+          hittof=it->first;
+          chargeSum=Q;
+          eventSz=1;
+          accu_x=0;
+          accu_y=0;
+          accu_xw=0;
+          accu_yw=0;
+
+          chnl<51 ? accu_xw += chnl*Q : accu_yw += (chnl-50)*Q;
+          chnl<51 ? accu_x += Q : accu_y += Q;
+        }
+      }
+      else
+      {
+        //accumulate
+        // printf("%d %d %d %d\n",eventcnt, it->first, chnl, Q);
+        eventSz++;
+        chnl<51 ? accu_xw += chnl*Q : accu_yw += (chnl-50)*Q;
+        chnl<51 ? accu_x += Q : accu_y += Q;
+        chargeSum += Q;
+      }
+    }
+
+    std::multimap<uint32_t,uint32_t> temp; //release memory
+    m_tof_cq_map.swap(temp);
+    m_last_t0=header.t0cnt;
+  }
+
+  //Sorting hit data
+  // printf("*********%d maps************\n",header.map_num);
+  uint32_t temp32=0;
+
+  for(unsigned imap=0;imap<header.map_num;imap++)
+  {
+    error_assert(*pt == 0xAA);
+    uint32_t t = 0;
+    read_uint32(pt,t);
+    t &= MASK_24;
+    // printf("TdataID %d\n", t);
+    uint32_t eventNum = 0;
+    read_uint32(pt,eventNum);
+
+    // printf("map %d, event number %d \n",imap, eventNum);
+    for(unsigned ievt=0;ievt<eventNum;ievt++)
+    {
+      uint8_t ch = *(pt);
+      read_uint32(pt, temp32);
+      //error_assert(ch==*(pt));
+      uint32_t t_hi_res = temp32&MASK_24;
+      read_uint32(pt, temp32);
+      //fixme: there is a bug in DAQ, the secend channel num sometimes are left zero
+      temp32 = (temp32&MASK_24) + (ch<<24);
+      // uint16_t charge = (temp32&MASK_12)- ((temp32>>12)&MASK_12);
+      m_tof_cq_map.emplace_hint(m_tof_cq_map.end(), t_hi_res, temp32);
+
+      // printf("ch %d, charge %d, time stamp %d\n", ch, charge, t_hi_res);
+    }
+  }
+  pt = package_end;
+
+  //printf("left %ld, package_end %p, stream_end %p\n", stream_end-package_end, package_end, stream_end);
+  return package_end==stream_end?false:true;
+}
+
+void Parser::PackageMWPCold::write(std::ofstream &file, const char *filename)
+{
+  file.open(filename);
+  auto it=m_tof_cq_map.begin();
+  for(;it!=m_tof_cq_map.end();++it)
+  {
+    uint32_t temp32 = it->second;
+    file << it->first << " " << ( temp32>>24) << " "  <<( (temp32&MASK_12) - ( (temp32>>12)&MASK_12) )<< "\n";
+  }
+  file.close();
+}
+
+void Parser::PackageMWPCold::print() const
+{
+  uint8_t ch = 0;
+  uint16_t Q = 0;
+  for(auto it: m_tof_cq_map)
+  {
+    getChannelCharge(it.second, ch, Q);
+    std::cout << it.first << " " << (uint16_t)ch << " " << Q << std::endl;
+  }
+  std::cout << std::endl;
+}
Index: src/Parser/libsrc/ParserBase.cc
===================================================================
--- src/Parser/libsrc/ParserBase.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libsrc/ParserBase.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,42 @@
+#include "ParserBase.hh"
+#include "UtilsException.hh"
+
+#include <cstdio>
+Parser::ParserBase::ParserBase()
+{
+
+}
+
+Parser::ParserBase::~ParserBase()
+{
+
+}
+
+
+void Parser::ParserBase::read_uint32_many(const uint8_t*& pt, std::vector<uint32_t> &u32_vec, unsigned num) const
+{
+  if(u32_vec.size()!=num)
+    u32_vec.resize(num);
+
+  for(unsigned i=0;i<num;i++) {
+    read_uint32(pt, u32_vec[i]);
+  }
+}
+
+
+bool Parser::ParserBase::findNextPackage(const uint8_t*& start, const uint8_t * const stream_end, const uint8_t*& pkgend, uint64_t &offset) const
+{
+  //fixme: detect zero padding data
+  error_assert_always(start<stream_end);
+  offset=0;
+  for(;start!=stream_end;start++,offset++)
+  {
+    if(findEnd(start,pkgend))
+    {
+      // if(offset) //fixme: add to log
+      //   printf("Found next package in the stream with offst %ld, start at %ld to the end of stream\n", offset, stream_end-start); //fixme : logge
+      return true;
+    }
+  }
+  return false;
+}
Index: src/Parser/libsrc/ParserHe3.cc
===================================================================
--- src/Parser/libsrc/ParserHe3.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libsrc/ParserHe3.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,108 @@
+#include <cstdio>
+
+#include "ParserHe3.hh"
+#include "UtilsException.hh"
+
+Parser::ParserHe3::ParserHe3()
+:ParserBase()
+{
+}
+
+Parser::ParserHe3::~ParserHe3()
+{
+}
+
+void Parser::ParserHe3::readHeader(const uint8_t*& pt, const Parser::ParserHe3::Header *header) const
+{
+  //Header is POD data
+  error_assert(*pt == PACK_START);
+
+  header = reinterpret_cast<const Header *>(pt);
+  pt += 8;
+
+  // printf("""\nheader:\n  flag 0x%x, instrument 0x%x, detc type 0x%x, module 0x%x\n"""
+  //        """opt_mode 0x%x fre_div 0x%x version 0x%x data_type 0x%x \n"""
+  //   ,header->flag, header->instrument, header->detector_type, header->module
+  //   ,header->opt_mode, header->fre_div_mode, header->data_ver, header->data_type );
+}
+
+void Parser::ParserHe3::readInfo(const uint8_t*& pt, Info &info) const
+{
+  uint32_t raw=0;
+  read_uint32(pt, info.t0_count);
+  read_uint32(pt, raw);
+  info.hit_cnt = (raw >> 18) & MASK_14;
+  info.sample_num_n = (raw >> 6) & MASK_12;
+  info.sample_num_bl = raw & MASK_6;
+
+  // printf("info: \n  t0_cnt %d, hit_cnt %d, n %d, m %d\n"
+  //    ,info.t0_count,  info.hit_cnt, info.sample_num_n, info.sample_num_bl);
+}
+void Parser::ParserHe3::printInfo(const uint8_t* pt) const
+{
+  uint32_t raw=0;
+  Info info;
+  read_uint32(pt, info.t0_count);
+  read_uint32(pt, raw);
+  info.hit_cnt = (raw >> 18) & MASK_14;
+  info.sample_num_n = (raw >> 6) & MASK_12;
+  info.sample_num_bl = raw & MASK_6;
+  printf("info: \n  t0_cnt %d, hit_cnt %d, n %d, m %d\n"
+     ,info.t0_count,  info.hit_cnt, info.sample_num_n, info.sample_num_bl);
+}
+
+
+void Parser::ParserHe3::readHit( const uint8_t*& pt, Hit &hit) const
+{
+  error_assert( ((*pt>>4) & MASK_4)  == DATA_START);
+
+  uint32_t raw=0;
+  read_uint32(pt, raw);
+  hit.time = raw & MASK_24;
+  hit.tube_id = (raw>>24) & MASK_4;
+  //fixme:
+  // //tube_id from DAQ 7 8 9 11, corresponding to 1 2 3 4 in subsequent analysis
+  // hit.tube_id = hit.tube_id==11? hit.tube_id-7:hit.tube_id-6;
+  read_uint32(pt, raw);
+  hit.upper_baseline = raw & MASK_20;
+  read_uint32(pt, raw);
+  hit.lower_baseline = raw & MASK_20;
+  read_uint32(pt, raw);
+  hit.upper_charge = (raw>>16) & MASK_16;
+  hit.lower_charge = raw & MASK_16;
+
+  // printf("hit:const uint8_t*&tube_id %x, upper_baseline %d, lower_baseline %d\n  upper_charge %d, lower_charge %d\n"
+  //   ,hit.time,  hit.tube_id, hit.upper_baseline, hit.lower_baseline,hit.upper_charge, hit.lower_charge);
+}
+
+bool Parser::ParserHe3::findEnd(const uint8_t* pt, const uint8_t*& end) const
+{
+  if(*pt != PACK_START)
+    return false;
+
+  //extract number of hit
+  uint32_t tmp = *(pt+12)<<8;
+  tmp += *(pt+13);
+  uint32_t hitnum = tmp >> 2;
+
+  //estimate package total size
+  uint32_t data_payload_size = hitnum*16;
+  uint32_t estTotSize = 16 + data_payload_size + 8;
+
+  //check the second flag in a package
+  if(*(pt + estTotSize -8) !=  PACK_END)
+    return false;
+
+  uint32_t totByteCount = 0;
+  const uint8_t * pos = pt+estTotSize-4;
+  read_uint32(pos ,totByteCount);
+
+  end =  pt + totByteCount;
+  return estTotSize==totByteCount?true:false;
+}
+
+bool Parser::ParserHe3::is_valid(const uint8_t* pt) const
+{
+  const uint8_t* tmp;
+  return findEnd(pt,tmp);
+}
Index: src/Parser/libsrc/ParserMWPC.cc
===================================================================
--- src/Parser/libsrc/ParserMWPC.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libsrc/ParserMWPC.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,57 @@
+#include "ParserMWPC.hh"
+#include "UtilsException.hh"
+
+Parser::ParserMWPC::ParserMWPC() { }
+Parser::ParserMWPC::~ParserMWPC() { }
+
+void Parser::ParserMWPC::readHeader(const uint8_t*& pt, MWPCHeader& header) const
+{
+  const uint8_t* end = nullptr;
+//  if(findEnd(pt,end))
+ //   printf("this is a valid package, size is 0x%x, %p, %p\n", end-pt, pt, end);
+  uint32_t temp = 0;
+  read_uint32 (pt,temp);
+  error_assert(temp==MWPC_SIG);  //fixme: error handling
+
+
+  header.instrment = *pt;
+  header.detector_type = *(++pt);
+  pt+=3;
+  header.opt_mode = *(++pt);
+  header.freq_div_mode = *(++pt);
+  header.data_version = *(++pt);
+  header.data_type = *(++pt);
+
+  pt += 4*7;
+  read_uint32(pt,header.t0cnt);
+  read_uint32(pt,header.payload_bycnt);
+  read_uint32(pt,header.map_num);
+
+  // printf("""instr 0x%x, det type 0x%x, opt mode 0x%x, freq div 0x%x\n"""
+  //        """ data ver 0x%x, data type 0x%x, t0 cnt %d, byte cnt 0x%x, map cnt %d\n""",
+  //       header.instrment, header.detector_type, header.opt_mode, header.freq_div_mode,
+  //       header.data_version, header.data_type,header.t0cnt , header.payload_bycnt, header.map_num);
+  // printf("next byte 0x%x\n", *(pt+12));
+
+  pt+=12; //12 bytes followed are reserved.
+}
+
+bool Parser::ParserMWPC::findEnd(const uint8_t* pt, const uint8_t*& end) const
+{
+  //match token
+  if(*pt!=0xee && *(pt+1)!= 0x12 && *(pt+2)!= 0x34 && *(pt+3)!= 0xee)
+    return false;
+
+  uint32_t bycnt = 0;
+  pt +=44; //jump to the "byte count" position
+  read_uint32 (pt, bycnt);
+  end = pt + bycnt - 48;// read_uint32 moved pt forward by 48
+  return true;
+}
+
+bool Parser::ParserMWPC::is_valid(const uint8_t* pt) const
+{
+  //fixme : check more stuff
+  const uint8_t* bycnt = 0;
+  return findEnd(pt, bycnt);
+}
Index: src/Parser/libsrc/ParserUtils.cc
===================================================================
--- src/Parser/libsrc/ParserUtils.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/libsrc/ParserUtils.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,9 @@
+#include "ParserUtils.hh"
+#include <stdint.h>
+
+int Parser::is_little_endian()
+{
+  //Return 0 for big endian, 1 for little endian.
+  volatile uint32_t i=0x01234567;
+  return (*((uint8_t*)(&i))) == 0x67;
+}
Index: src/Parser/main.cc
===================================================================
--- src/Parser/main.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/main.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,22 @@
+#include <cstdio>
+#include <fstream>
+#include <vector>
+
+#include "ParserUtils.hh"
+#include "ParserHe3.hh"
+int main(int argc, char *argv[])
+{
+    printf( "This processor is %s endian\n",Parser::is_little_endian()? "little":"big");
+    std::vector<uint8_t> data;
+    for(uint8_t i=1;i<100;i++)
+    {
+      data.push_back(i);
+    }
+
+    auto *he3 = new Parser::ParserHe3();
+    const Parser::ParserHe3::Header *header ;
+    const uint8_t * pt = data.data();
+    he3->readHeader(pt,header);
+
+    return 0;
+}
Index: src/Parser/python/__init__.py
===================================================================
--- src/Parser/python/__init__.py	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Parser/python/__init__.py	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+#enable py3 behaviour in py2.6+ (avoid unicode_literals on purpose!)
+from __future__ import division, print_function, absolute_import
+
+import ctypes
+
+_libc = ctypes.CDLL('./libprototype.so')
+print ("runnig _load()")
+ndarray_to_dblp = lambda a : a.ctypes.data_as(ctypes.POINTER(ctypes.c_double))
+ndarray_to_ubtp = lambda a : a.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))
+
+
+def _str2cstr(s):
+    #converts any string (str,bytes,unicode) to bytes
+    try:
+        return s if isinstance(s,bytes) else s.encode('ascii')
+    except UnicodeEncodeError:
+        #Attempt with file-system encoding, in case of non-ASCII path names:
+        return s.encode(sys.getfilesystemencoding())
+
+def _cstr2str(s):
+    #converts bytes object to str (unicode in py3, bytes in py2)
+    try:
+        return s if isinstance(s,str) else s.decode('ascii')
+    except UnicodeDecodeError:
+        return s.decode(sys.getfilesystemencoding())
+
+
+def _wrap(fct_name,restype,argtypes,take_ref = False, hide=False, error_check=True):
+    assert isinstance(argtypes,tuple)
+    raw=getattr(_libc,fct_name)
+    raw.argtypes=argtypes
+    raw.restype=restype
+
+    if take_ref:
+        assert len(argtypes)==1
+        fct = lambda arg : raw(ctypes.byref(arg))
+    else:
+        fct = lambda *args : raw(*args)
+    if error_check:
+        #NB: we should read about return types in the ctypes tutorial. Apparently one
+        #can just set an error checking function as the restype.
+        raw_fct = fct
+        def fcte(*aaa):
+            r = raw_fct(*aaa)
+            # if _ncerror(): fixme:
+            #     _raise_err()
+            # return r
+        fct=fcte
+    if not hide:
+        functions[fct_name] = fct
+    return fct
+
+#_ncerror       = _wrap('ncrystal_error',ctypes.c_int,tuple(),hide=True,error_check=False)
+
+
+class Parser_Parserbase_t(ctypes.Structure):
+     _fields_ = [('internal', ctypes.c_void_p)]
+#
+
+
+class ParserBase(ctypes.Structure):
+    """Base class for Parsers"""
+    def __init__(self):
+        self._Parser_read_uint32 = _wrap('Parser_read_uint32', ctypes.POINTER(ctypes.c_uint) ,(Parser_Parserbase_t,ctypes.c_ubyte
+         ,ctypes.POINTER(ctypes.c_uint) ),hide=True)
+
+        _create_detectorbase = _wrap('create_detectorbase', (Parser_Parserbase_t)  , (), hide=True)
+        self._rawobj = _create_detectorbase()
+
+    def read_uint32(self, pt_in): #fixme
+        data=0
+        self._Parser_read_uint32(self._rawobj, pt_in, data)
+        return data
+
+ParserBase()
Index: src/RedisIO/libinc/RedisIO.hh
===================================================================
--- src/RedisIO/libinc/RedisIO.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/RedisIO/libinc/RedisIO.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,21 @@
+#ifndef RedisIO_hh
+#define RedisIO_hh
+
+#include <string>
+#include <cpp_redis/cpp_redis>
+
+class RedisIO {
+public:
+  RedisIO(const std::string& ip_addr, unsigned port, const std::string& usrname, const std::string& password);
+  virtual ~RedisIO();
+
+  void str2send(const std::string& path, const std::string& str);
+  void syncCommit();
+
+
+private:
+  cpp_redis::client m_client;
+
+};
+
+#endif
Index: src/RedisIO/libsrc/RedisIO.cc
===================================================================
--- src/RedisIO/libsrc/RedisIO.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/RedisIO/libsrc/RedisIO.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,62 @@
+#include "RedisIO.hh"
+#include <iostream>
+
+
+RedisIO::RedisIO(const std::string& ip_addr, unsigned port, const std::string& usrname, const std::string& password)
+{
+  //! Enable logging
+  cpp_redis::active_logger = std::unique_ptr<cpp_redis::logger>(new cpp_redis::logger);
+
+  //! High availability requires at least 2 io service workers
+  cpp_redis::network::set_default_nb_workers(2);
+
+  cpp_redis::client m_client;
+
+  //! Add your sentinels by IP/Host & Port
+  m_client.add_sentinel(ip_addr, port);
+
+  //! Call connect with optional timeout
+  //! Can put a loop around this until is_connected() returns true.
+  m_client.connect(usrname, [](const std::string& host, std::size_t port, cpp_redis::connect_state status) {
+    if (status == cpp_redis::connect_state::dropped) {
+      std::cout << "client disconnected from " << host << ":" << port << std::endl;
+    }
+  },
+    0, -1, 5000);
+
+  m_client.auth(password, [](const cpp_redis::reply& reply) {
+    if (reply.is_error()) { std::cerr << "Authentication failed: " << reply.as_string() << std::endl; }
+    else
+    {
+      std::cout << "successful authentication" << std::endl;
+    }
+  });
+
+}
+
+RedisIO::~RedisIO()
+{
+
+}
+
+void RedisIO::str2send(const std::string& path, const std::string& str)
+{
+  m_client.set(path, str, [](cpp_redis::reply& reply) {
+    if (reply.is_string() )
+    {
+      if(reply.as_string()!="OK")
+      {
+        __CPP_REDIS_LOG(info, path+" returns OK");
+        return;
+      }
+    }
+    __CPP_REDIS_LOG(warn, " failed to receive acknowledgment from "+path);
+
+  });
+}
+
+
+void RedisIO::syncCommit()
+{
+  m_client.sync_commit();
+}
Index: src/Utils/libinc/RedisHelper.hh
===================================================================
--- src/Utils/libinc/RedisHelper.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Utils/libinc/RedisHelper.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,36 @@
+#ifndef RedisHelper_hh
+#define RedisHelper_hh
+
+#include <string>
+#include <vector>
+#include <typeinfo>
+
+static inline bool is_base64(unsigned char c) {
+  return (isalnum(c) || (c == '+') || (c == '/'));
+}
+
+void base64_encode(unsigned char const * , unsigned int len, std::string &encoded);
+void base64_decode(std::string const &encoded_string, std::string &decoded);
+
+//content in the encoded will be replaced by new data
+void make_jsonarray(unsigned char const * data, unsigned len, const std::string &dtype,
+                    const std::vector<unsigned> &shape, std::string &encoded);
+
+void c2json_int8(const int8_t *data, const std::vector<unsigned>& shape, std::string &encoded);
+void c2json_uint8(const uint8_t *data, const std::vector<unsigned>& shape, std::string &encoded);
+
+void c2json_int16(const int16_t *data, const std::vector<unsigned>& shape, std::string &encoded);
+void c2json_uint16(const uint16_t *data, const std::vector<unsigned>& shape, std::string &encoded);
+
+void c2json_int32(const int32_t *data, const std::vector<unsigned>& shape, std::string &encoded);
+void c2json_uint32(const uint32_t *data, const std::vector<unsigned>& shape, std::string &encoded);
+
+void c2json_int64(const int64_t *data, const std::vector<unsigned>& shape, std::string &encoded);
+void c2json_uint64(const uint64_t *data, const std::vector<unsigned>& shape, std::string &encoded);
+
+void c2json_float(const float *data, const std::vector<unsigned>& shape, std::string &encoded);
+void c2json_double(const double *data, const std::vector<unsigned>& shape, std::string &encoded);
+
+
+
+#endif
Index: src/Utils/libinc/RedisNumpy.hh
===================================================================
--- src/Utils/libinc/RedisNumpy.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Utils/libinc/RedisNumpy.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,106 @@
+#ifndef RedisNumpy_hh
+#define RedisNumpy_hh
+
+#include <vector>
+#include <string>
+#include <stdexcept>
+#include <iostream>
+
+//The RedisNumpy class is able to pack C type arrays into the native numpy npy v1.0 format.
+//It can be used to transceive numpy array over Redis store between C++ and python without any encoding/decoding
+
+//defintion of the format can be found at
+//https://docs.scipy.org/doc/numpy-1.14.2/neps/npy-format.html
+//the implementation in numpy is at
+//https://github.com/numpy/numpy/blob/master/numpy/lib/format.py
+
+//Limitations
+//1. limited by format, one chunk of converted data can only represent one numpy array.
+//2. limited by implementation, all numpy array element must have the same type and not compressed.
+//3. limited by implementation, only creating nor parsing numpy data.
+//3. limited by implementation, must by used in little endian system.
+
+class RedisNumpy {
+  //'<'' means little endian
+  //0x3c63 ascii for <c
+  //0x3c66 ascii for <f
+  //0x3c69 ascii for <i
+  //0x3c75 ascii for <u
+
+  //0x31 ascii for 1
+  //0x32 ascii for 2
+  //0x34 ascii for 4
+  //0x38 ascii for 8
+
+  //0x3c633136 for <c16
+
+public:
+  enum data_type : uint32_t {
+    c8 = 0x38633c,
+    f4 = 0x34663c,
+    f8 = 0x38663c,
+    i1 = 0x31693c,
+    i2 = 0x32693c,
+    i4 = 0x34693c,
+    i8 = 0x38693c,
+    u1 = 0x31753c,
+    u2 = 0x32753c,
+    u4 = 0x34753c,
+    u8 = 0x38753c,
+    c16 = 0x3631633c
+ };
+public:
+  RedisNumpy();
+  virtual ~RedisNumpy();
+
+  template <typename T>
+  void makeNumpyArr(const std::vector<T> &data, data_type type,
+                    const std::vector<uint64_t> &shape, std::string &npArr);
+
+  template <typename T>
+  void makeNumpyArr(const T *data, unsigned datasize, data_type type,
+                    const std::vector<uint64_t> &shape, std::string &npArr);
+
+private:
+  const std::string m_fixed_magic;
+  int is_little_endian();
+  void makeNumpyArr(const uint8_t  *data, unsigned len,
+                    data_type type, const std::vector<uint64_t> &shape, std::string &npArr);
+private:
+  //use the data_type to construct. getTypeString retures the ascii name of the type in npy format
+  union U32toASCII {
+    uint32_t u32;
+    char  ascii[4];
+    U32toASCII(uint32_t a) : u32(a) {};
+    std::string getTypeString() {
+      std::string type_str;
+      for(unsigned i=0;i<4;i++) {
+        if(!ascii[i])
+          return type_str;
+        type_str += *(ascii+i);
+      }
+      if(type_str.empty()) //shouldn't really reach here
+        throw std::invalid_argument("data_type ascii array can't be all zero");
+      return type_str;
+    }
+  };
+};
+
+template <typename T>
+void RedisNumpy::makeNumpyArr(const std::vector<T> &data, data_type type,
+                              const std::vector<uint64_t> &shape, std::string &npArr)
+{
+  makeNumpyArr( reinterpret_cast<const uint8_t*>(data.data()),
+                data.size()*sizeof(T), type, shape , npArr );
+}
+
+template <typename T>
+void RedisNumpy::makeNumpyArr(const T *data, unsigned datasize, data_type type,
+                              const std::vector<uint64_t> &shape, std::string &npArr)
+{
+  makeNumpyArr( reinterpret_cast<const uint8_t*>(data), datasize*sizeof(T), type, shape , npArr );
+}
+
+
+
+#endif
Index: src/Utils/libinc/UtilsException.hh
===================================================================
--- src/Utils/libinc/UtilsException.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Utils/libinc/UtilsException.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,69 @@
+#ifndef Utils_Exception_hh
+#define Utils_Exception_hh
+
+
+#include <stdexcept>
+#include <sstream>
+#include <string>
+
+namespace Error {
+
+  class Exception : public std::runtime_error {
+  public:
+    explicit Exception(const std::string& msg, const char * f, unsigned l) throw();
+    explicit Exception(const char * msg,  const char * f, unsigned l) throw();
+    virtual const char * getTypeName() const throw() = 0;
+    const char * getFile() const throw() { return m_file; }
+    unsigned getLineNo() const throw() { return m_lineno; }
+    Exception( const Exception & o ) throw();
+    Exception & operator= ( const Exception & o ) throw();
+    virtual ~Exception() throw();
+  private:
+    const char * m_file;
+    unsigned m_lineno;
+  };
+
+#define ADD_ERROR_TYPE(ErrType)                                                               \
+  struct ErrType : public Exception {                                                                \
+    explicit ErrType(const std::string& m, const char * f, unsigned l) throw() : Exception(m,f,l) {} \
+    explicit ErrType(const char * m,  const char * f, unsigned l) throw() : Exception(m,f,l) {}      \
+    virtual const char * getTypeName() const throw() { return #ErrType; }                            \
+    virtual ~ErrType() throw();                                                                      \
+  }
+  //List of error types (destructors implemented in .cc):
+  ADD_ERROR_TYPE(FileNotFound);
+  ADD_ERROR_TYPE(DataLoadError);
+  ADD_ERROR_TYPE(MissingInfo);
+  ADD_ERROR_TYPE(CalcError);
+  ADD_ERROR_TYPE(LogicError);
+  ADD_ERROR_TYPE(BadInput);
+#undef ADD_ERROR_TYPE
+}
+
+#define ERROR_THROW(ErrType, msg)                     \
+  {                                                   \
+    throw ::Error::ErrType(msg,__FILE__,__LINE__);    \
+  }
+
+#define ERROR_THROW2(ErrType, msg)        \
+  {                                       \
+    std::ostringstream err_oss;           \
+    err_oss << msg;                       \
+    ERROR_THROW(ErrType,err_oss.str())    \
+  }
+
+
+#define error_str(s) #s
+#define error_xstr(s) error_str(s)
+#define error_assert_always(x) do { if (!(x)) { ERROR_THROW(LogicError,\
+                              "Assertion failure: " error_xstr(x)); } } while(0)
+
+#ifndef NDEBUG
+#  define error_assert(x) error_assert_always(x)
+#  define error_assert2(x) error_assert_always(x)
+#else
+#  define error_assert(x) do {} while(0)
+#  define error_assert2(x) do { (void)sizeof(x); } while(0)//use but dont evaluate x
+#endif
+
+#endif
Index: src/Utils/libsrc/RedisHelper.cc
===================================================================
--- src/Utils/libsrc/RedisHelper.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Utils/libsrc/RedisHelper.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,195 @@
+#include "RedisHelper.hh"
+#include "UtilsException.hh"
+#include <iostream>
+
+static const std::string base64_chars =
+             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+             "abcdefghijklmnopqrstuvwxyz"
+             "0123456789+/";
+
+
+void base64_encode(unsigned char const *bytes_to_encode, unsigned int in_len, std::string &ret)
+{
+  int i = 0;
+  int j = 0;
+  unsigned char char_array_3[3];
+  unsigned char char_array_4[4];
+
+  while (in_len--) {
+    char_array_3[i++] = *(bytes_to_encode++);
+    if (i == 3) {
+      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+      char_array_4[3] = char_array_3[2] & 0x3f;
+
+      for(i = 0; (i <4) ; i++)
+        ret += base64_chars[char_array_4[i]];
+      i = 0;
+    }
+  }
+
+  if (i)
+  {
+    for(j = i; j < 3; j++)
+      char_array_3[j] = '\0';
+
+    char_array_4[0] = ( char_array_3[0] & 0xfc) >> 2;
+    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+
+    for (j = 0; (j < i + 1); j++)
+      ret += base64_chars[char_array_4[j]];
+
+    while((i++ < 3))
+      ret += '=';
+
+  }
+
+}
+
+void base64_decode(std::string const& encoded_string, std::string &ret)
+{
+  size_t in_len = encoded_string.size();
+  int i = 0;
+  int j = 0;
+  int in_ = 0;
+  unsigned char char_array_4[4], char_array_3[3];
+
+  while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
+    char_array_4[i++] = encoded_string[in_]; in_++;
+    if (i ==4) {
+      for (i = 0; i <4; i++)
+        char_array_4[i] = base64_chars.find(char_array_4[i]) & 0xff;
+
+      char_array_3[0] = ( char_array_4[0] << 2       ) + ((char_array_4[1] & 0x30) >> 4);
+      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) +   char_array_4[3];
+
+      for (i = 0; (i < 3); i++)
+        ret += char_array_3[i];
+      i = 0;
+    }
+  }
+
+  if (i) {
+    for (j = 0; j < i; j++)
+      char_array_4[j] = base64_chars.find(char_array_4[j]) & 0xff;
+
+    char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+    char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+
+    for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
+  }
+}
+
+void make_jsonarray(unsigned char const * data, unsigned len, const std::string &dtype,
+                    const std::vector<unsigned> &shape, std::string &encoded)
+{
+  encoded = "{\"dtype\": \"" + dtype;
+  encoded.reserve(len*2);
+
+  encoded += "\", \"shape\": [";
+  error_assert_always(!shape.empty());
+  unsigned lastid = shape.size()-1;
+  for(unsigned i=0;i<lastid;i++)
+  {
+    encoded += std::to_string(shape[i])+", ";
+  }
+  encoded += std::to_string(shape[lastid]);
+
+  encoded += "], \"__ndarray__\": \"";
+  base64_encode(reinterpret_cast<const unsigned char*> ( data ), len, encoded);
+  encoded += "\"}";
+}
+
+void c2json_int8(const int8_t *data, const std::vector<unsigned>& shape, std::string &encoded)
+{
+  unsigned len=1;
+  for(auto v:shape)
+    len *= v;
+  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(int8_t), "int8",
+                 shape, encoded);
+}
+
+void c2json_uint8(const uint8_t *data, const std::vector<unsigned>& shape, std::string &encoded)
+{
+  unsigned len=1;
+  for(auto v:shape)
+    len *= v;
+  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(uint8_t), "uint8",
+                 shape, encoded);
+}
+
+void c2json_int16(const int16_t *data, const std::vector<unsigned>& shape, std::string &encoded)
+{
+  unsigned len=1;
+  for(auto v:shape)
+    len *= v;
+  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(int16_t), "int16",
+                 shape, encoded);
+}
+
+void c2json_uint16(const uint16_t *data, const std::vector<unsigned>& shape, std::string &encoded)
+{
+  unsigned len=1;
+  for(auto v:shape)
+    len *= v;
+  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(uint16_t), "uint16",
+                 shape, encoded);
+}
+
+
+void c2json_int32(const int32_t *data, const std::vector<unsigned>& shape, std::string &encoded)
+{
+  unsigned len=1;
+  for(auto v:shape)
+    len *= v;
+  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(int32_t), "int32",
+                 shape, encoded);
+}
+
+void c2json_uint32(const uint32_t *data, const std::vector<unsigned>& shape, std::string &encoded)
+{
+  unsigned len=1;
+  for(auto v:shape)
+    len *= v;
+  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(uint32_t), "uint32",
+                 shape, encoded);
+}
+
+void c2json_int64(const int64_t *data, const std::vector<unsigned>& shape, std::string &encoded)
+{
+  unsigned len=1;
+  for(auto v:shape)
+    len *= v;
+  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(int64_t), "int64",
+                 shape, encoded);
+}
+
+void c2json_uint64(const uint64_t *data, const std::vector<unsigned>& shape, std::string &encoded)
+{
+  unsigned len=1;
+  for(auto v:shape)
+    len *= v;
+  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(uint64_t), "uint64",
+                 shape, encoded);
+}
+
+void c2json_float(const float *data, const std::vector<unsigned>& shape, std::string &encoded)
+{
+  unsigned len=1;
+  for(auto v:shape)
+    len *= v;
+  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(float), "float32",
+                 shape, encoded);
+}
+
+void c2json_double(const double *data, const std::vector<unsigned>& shape, std::string &encoded)
+{
+  unsigned len=1;
+  for(auto v:shape)
+    len *= v;
+  make_jsonarray(reinterpret_cast<const unsigned char*> ( data ), len*sizeof(double), "float64",
+                 shape, encoded);
+}
Index: src/Utils/libsrc/RedisNumpy.cc
===================================================================
--- src/Utils/libsrc/RedisNumpy.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Utils/libsrc/RedisNumpy.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,58 @@
+#include "RedisNumpy.hh"
+#include "UtilsException.hh"
+#include <cstring>
+
+RedisNumpy::RedisNumpy()
+:m_fixed_magic( "\x93NUMPY")
+{
+  if(!is_little_endian())
+    throw std::runtime_error("RedisNumpy support only little endian system"); //fixme:check at compile time
+}
+
+RedisNumpy::~RedisNumpy()
+{
+
+}
+
+int RedisNumpy::is_little_endian()
+{
+  //Return 0 for big endian, 1 for little endian.
+  volatile uint32_t i=0x01234567;
+  return (*((uint8_t*)(&i))) == 0x67;
+}
+
+void RedisNumpy::makeNumpyArr(const uint8_t *data, unsigned len,
+                  data_type dtype, const std::vector<uint64_t> &shape, std::string &npArr)
+{
+  npArr.reserve(len + 128); //a guess of tot size
+
+  npArr = m_fixed_magic +'\x01'+'\x00' + "  ";
+  npArr += "{'descr': '" + U32toASCII(dtype).getTypeString() + "', 'fortran_order': False, 'shape': (" ;
+
+  for(auto v:shape)
+    npArr += std::to_string(v) + ",";
+  if(shape.size()>1)
+    npArr.pop_back();
+
+  npArr += "), }";
+
+  unsigned dict_size = npArr.size();
+  if(dict_size>65535)
+    throw std::length_error("header in npy 1.0 format can't be larger than 65535 bytes, see https://docs.scipy.org/doc/numpy-1.14.2/neps/npy-format.html");
+
+  //total meta info size mush be evenly divisible by 64 for alignment purposes.
+  //-1, because terminated by a newline '\n'
+  unsigned tot = ((dict_size/64)+1)*64;
+
+  //sizeof("\x93NUMPY\x01\00")+sizeof(HEADER_LEN)=10 bytes
+  uint16_t header_len_with_padding = tot-10;
+
+  npArr[8] = ( unsigned char ) (header_len_with_padding & 0xff) ;
+  npArr[9] = ( unsigned char ) ((header_len_with_padding>>8) & 0xff);
+
+  unsigned padding_size = tot - dict_size - 1;
+  npArr.append(padding_size,'\x20');
+  npArr += "\n";
+
+  npArr.append(reinterpret_cast<const char* >(data),len);
+}
Index: src/Utils/libsrc/UtilsException.cc
===================================================================
--- src/Utils/libsrc/UtilsException.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/Utils/libsrc/UtilsException.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,45 @@
+#include "UtilsException.hh"
+
+
+namespace Error {
+
+  Exception::Exception(const std::string& msg, const char * f, unsigned l) throw()
+    : std::runtime_error(msg),
+      m_file(f),
+      m_lineno(l)
+  {
+  }
+
+  Exception::Exception(const char * msg,  const char * f, unsigned l) throw()
+    : std::runtime_error(msg),
+      m_file(f),
+      m_lineno(l)
+  {
+  }
+
+  Exception::Exception( const Exception & o ) throw()
+    : std::runtime_error(o),
+      m_file(o.m_file),
+      m_lineno(o.m_lineno)
+  {
+  }
+
+  Exception & Exception::operator= ( const Exception & o ) throw()
+  {
+    std::runtime_error::operator=(o);
+    m_file = o.m_file;
+    m_lineno = o.m_lineno;
+    return *this;
+  }
+
+  Exception::~Exception() throw()
+  {
+  }
+
+  FileNotFound::~FileNotFound() throw() {}
+  MissingInfo::~MissingInfo() throw() {}
+  DataLoadError::~DataLoadError() throw() {}
+  LogicError::~LogicError() throw() {}
+  CalcError::~CalcError() throw() {}
+  BadInput::~BadInput() throw() {}
+}
Index: src/cpythonprototype/libinc/ctypes_api.hh
===================================================================
--- src/cpythonprototype/libinc/ctypes_api.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/cpythonprototype/libinc/ctypes_api.hh	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,22 @@
+#pragma once
+
+#ifdef __cplusplus
+#  include <cstdint>
+#else
+#  include <stdint.h>
+#  include <stdbool.h>
+#endif
+
+#if defined (_WIN32) || defined (__CYGWIN__) || defined (WIN32)
+#  ifdef NCrystal_EXPORTS
+#    define EXPORT_SYMBOL __declspec(dllexport)
+#  else
+#    define EXPORT_SYMBOL __declspec(dllimport)
+#  endif
+#else
+#  if ( defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__)
+#    define EXPORT_SYMBOL    __attribute__ ((visibility ("default")))
+#  else
+#    define EXPORT_SYMBOL
+#  endif
+#endif
Index: src/cpythonprototype/libinc/prototype.h
===================================================================
--- src/cpythonprototype/libinc/prototype.h	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/cpythonprototype/libinc/prototype.h	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,23 @@
+#ifndef prototype_h
+#define prototype_h
+
+
+#include "ctypes_api.hh"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  EXPORT_SYMBOL   int ncrystal_error();/* returns 1 if an error condition occurred. */
+
+  typedef struct { void * internal; } Parser_Parserbase_t;
+
+  EXPORT_SYMBOL Parser_Parserbase_t create_detectorbase();
+  EXPORT_SYMBOL void  Parser_read_uint32( Parser_Parserbase_t, const uint8_t* it , uint32_t *u32);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: src/cpythonprototype/libsrc/prototype.cc
===================================================================
--- src/cpythonprototype/libsrc/prototype.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
+++ src/cpythonprototype/libsrc/prototype.cc	(revision 8d7392fe3ebbeb5d7235c40558549a313e35f7a2)
@@ -0,0 +1,86 @@
+#include <cstring>
+
+#include "prototype.h"
+#include "UtilsException.hh"
+#include "ParserBase.hh"
+
+static int quietonerror = 0;
+static int haltonerror = 1;
+static int waserror = 0;
+static char errmsg[512];
+static char errtype[64];
+static void (*custom_error_handler)(char *,char*) = 0;
+
+/*
+int ncrystal_error()
+{
+  return waserror;
+}
+
+void setError(const char *msg, const char * etype = 0) throw() {
+  if (!etype)
+    etype="ncrystal_c-interface";
+  strncpy(errmsg,msg,sizeof(errmsg));
+  strncpy(errtype,etype,sizeof(errtype));
+  //Ensure final null-char in case of very long input strings:
+  errmsg[sizeof(errmsg)-1]='\0';
+  errtype[sizeof(errtype)-1]='\0';
+  if (custom_error_handler) {
+    (*custom_error_handler)(errtype,errmsg);
+  }
+  waserror = 1;
+  if (!quietonerror)
+    printf("ERROR [%s]: %s\n",errtype,errmsg);
+  if (haltonerror) {
+    printf("Terminating due to ERROR\n");
+    exit(1);
+  }
+}
+
+void handleError(const std::exception &e) throw() {
+  const Error::Exception* nce = dynamic_cast<const Error::Exception*>(&e);
+  if (nce) {
+    setError(nce->what(),nce->getTypeName());
+    return;
+  }
+  const std::runtime_error* stdrte = dynamic_cast<const std::runtime_error*>(&e);
+  if (stdrte)
+    setError(stdrte->what(),"std::runtime_error");
+  else
+    setError("<unknown>","std::exception");
+}
+
+#define ERRCATCH catch (std::exception& e) { handleError(e); }
+
+Parser::ParserBase * extract_detectorbase(Parser_Parserbase_t o) {
+  error_assert(o.internal);
+  return reinterpret_cast<Parser::ParserBase*>(o.internal);
+}
+
+Parser_Parserbase_t create_detectorbase()
+{
+  Parser_Parserbase_t o;
+  o.internal = 0;
+  try {
+    const Parser::ParserBase * db = new Parser::ParserBase();
+    error_assert(db);
+    o.internal = (void*)db;
+  } ERRCATCH;
+  return o;
+}
+
+
+void Parser_read_uint32( Parser_Parserbase_t ci_t, const uint8_t* it , uint32_t *u32)
+{
+  // if (!ncrystal_valid(&ci_t)) {
+  //   ncc::setError("ncrystal_info_dspacing_from_hkl called with invalid crystal info object");
+  //   return 0.0;
+  // }
+  // try {
+    Parser::ParserBase * ci = extract_detectorbase(ci_t);
+    ci->read_uint32(it, *u32);
+  //} ERRCATCH;
+  //return 0.0;
+}
+
+*/
