#include "UtsusemiEventDataConverterNeunetWithPH.hh"
//////////////////////////////////////////////////////////
UtsusemiEventDataConverterNeunetWithPH::
UtsusemiEventDataConverterNeunetWithPH(){
    Initialize();
}

//////////////////////////////////////////////////////////
UtsusemiEventDataConverterNeunetWithPH::
~UtsusemiEventDataConverterNeunetWithPH(){
    delete stools;
}

//////////////////////////////////////////////////////////
void UtsusemiEventDataConverterNeunetWithPH::
Initialize(){
    _MessageTag = "UtsusemiEventDataConverterNeunetWithPH >> ";
    stools = new StringTools();
}

//////////////////////////////////////////////////////////
bool UtsusemiEventDataConverterNeunetWithPH::
LoadParamFiles( std::string w_file, std::string d_file, std::string c_file ){
    if (SetEventParams( w_file, d_file )){
        if (c_file!="") SetCaseInfoParams( c_file );
        return true;
    }
    return false;

}

//////////////////////////////////////////////////////////
void UtsusemiEventDataConverterNeunetWithPH::
SetElementContainerNeunet( UInt4 outer_pixel_id, ElementContainer* ec, UInt4 caseId ){
    if (caseId<=0) return;

    Int4 tof_bin_type = _EventDecoder->PutTofBinType( outer_pixel_id );
    if (tof_bin_type<0){
        UtsusemiWarning( _MessageTag+"There is no information of tof_bin_type." );
    }else{

        SetElementContainer(outer_pixel_id, ec, caseId);

    }
}

//////////////////////////////////////////////////////////
Int4 UtsusemiEventDataConverterNeunetWithPH::
LoadEventDataFiles( UInt4 runNumber, std::string pathToData, std::string pathToT0data ){
    std::vector<UInt4> tmp(1, runNumber);
    return LoadEventDataFiles( tmp, pathToData, pathToT0data );
}
//////////////////////////////////////////////////////////
Int4 UtsusemiEventDataConverterNeunetWithPH::
LoadEventDataFiles( std::vector<UInt4> runNumbers, std::string pathToData, std::string pathToT0data ){
    if (runNumbers.empty()) return 0;
    if (runNumbers[0]<=0){
        _runNumbers.clear();
        _runNumbers.push_back(0);
        return 0;
    }

    std::vector< std::vector< std::vector< std::vector<Int4>* >* >* >* _PixelInfoStore = _EventDecoder->_wirInfo->PixelInfoStore;
    if (_PixelInfoStore==NULL){
        UtsusemiError( _MessageTag+"ReadEventData > There is no information about pixels from WiringInfo.xml" );
        return -2;
    }
    //std::cout << "################ LoadEventDataFiles "<< std::endl;
    SetDataPath( pathToData, pathToT0data, runNumbers, false, _PixelInfoStore );
    if (_isReady){
        for (UInt4 daq=0; daq<(_PixelInfoStore->size()); daq++){
            if (_PixelInfoStore->at(daq)!=NULL){
                for (UInt4 mod=0; mod<(_PixelInfoStore->at(daq)->size()); mod++){
                    if (_PixelInfoStore->at(daq)->at(mod)!=NULL){
                        UtsusemiMessage(_MessageTag+"ReadEventData >> Load event data file for daq,mod="+stools->UInt4ToString(daq)+","+stools->UInt4ToString(mod));
                        //clock_t t1,t2;
                        //t1=clock();
                        ReadEventData( daq, mod );
                        //t2=clock();
                        //std::cout << _MessageTag+"ReadEventData >> time of cost=" << t2-t1 << std::endl;
                        if (!(_isReady)){
                            UtsusemiMessage(_MessageTag+"ReadEventData >>> fails to read Event data (daq="+stools->UInt4ToString(daq)+", mod="+stools->UInt4ToString(mod));
                            for (UInt4 i=0; i<(_PixelInfoStore->at(daq)->at(mod)->size()); i++){
                                if (_PixelInfoStore->at(daq)->at(mod)->at(i)!=NULL){
                                    Int4 det_id = _PixelInfoStore->at(daq)->at(mod)->at(i)->at(1);
                                    if ( det_id>=(_isUnReadDetId.size()) ) _isUnReadDetId.resize( (det_id+1), false );
                                    _isUnReadDetId[det_id]=true;
                                    UtsusemiMessage( _MessageTag+"ReadEventData >>> masked on detId="+stools->UInt4ToString(det_id) );
                                }
                            }
                        }
                    }
                }
            }
        }
        //ReadEventData();
        if (!(_isReady)){
            UtsusemiError( _MessageTag+"LoadEventDataFiles >>> fails to read some event data files " );
        }
    }else{
        UtsusemiError( _MessageTag+"LoadEventDataFiles >>> fails to SetDataPath " );
        return -1;
    }
    return 0;
}

//////////////////////////////////////////////////////////
Int4 UtsusemiEventDataConverterNeunetWithPH::
SetElementContainerMatrix( ElementContainerMatrix* ecm, UInt4 caseId ){
    UInt4 outerPixelId = 0;
    Int4 tofBinType = -1;
    while(true){
        if (_EventDecoder->_wirInfo->TofBinInfoList[outerPixelId]!=NULL){
            std::vector<Double>* tofBinInfo = _EventDecoder->_wirInfo->TofBinInfoList[outerPixelId];

            UInt4 tof_pat_id = (UInt4)(tofBinInfo->at(0));
            if (_EventDecoder->_wirInfo->TofBinPtnInfo[ tof_pat_id ]!=NULL){
                tofBinType = _EventDecoder->_wirInfo->TofBinPtnInfo[ tof_pat_id ]->type;
                break;
            }
        }
        outerPixelId++;
    }

    if (tofBinType<0) return -3;

    Int4 ret = _SetElementContainerMatrix(ecm, caseId );
    if (ret!=0) return ret;

    HeaderBase* hh = ecm->PutHeaderPointer();
    std::vector<std::string> process_h = hh->PutStringVector(UTSUSEMI_KEY_HEAD_DATAPROCESSED);
    //std::cout << "@@@@@@ TOF_BIN_TYPE=" << tofBinType << std::endl;
    if (tofBinType==20){
        process_h.push_back( "TOF TO ENERGY TRANSFER" );
        //std::vector< Double > EfixV( _EventDecoder->_tofBinConv->PutEfixVect() );
        //if (!(EfixV.empty())) {
        //    hh->Add( UTSUSEMI_KEY_HEAD_EI, EfixV[0] );
        //    for (UInt4 i=0;i<ecm->PutSize();i++) ecm->PutPointer(i)->PutHeaderPointer()->Add( UTSUSEMI_KEY_HEAD_EI, EfixV[0] );
        //}
        std::vector<Double> params = _EventDecoder->_wirDict->PutParams(tofBinType);
        if (!(params.empty())){
            hh->Add( UTSUSEMI_KEY_HEAD_EI, params[0] );
            for (UInt4 i=0;i<ecm->PutSize();i++) ecm->PutPointer(i)->PutHeaderPointer()->Add( UTSUSEMI_KEY_HEAD_EI, params[0] );
        }
    }else if (tofBinType==21){
        process_h.push_back( "TOF TO ENERGY" );
    }else if (tofBinType==22){
        process_h.push_back( "TOF TO Q" );
    }else{
        process_h.push_back( "EVENTS TO TOF" );
    }

    hh->OverWrite(UTSUSEMI_KEY_HEAD_DATAPROCESSED,process_h);

    return 0;
}

//////////////////////////////////////////////////////////
Int4 UtsusemiEventDataConverterNeunetWithPH::
SetElementContainerMatrix( ElementContainerMatrix* ecm, UInt4 runNumber, std::string pathToData, std::string pathToT0data, UInt4 caseId ){
    Int4 ret = LoadEventDataFiles( runNumber, pathToData, pathToT0data );
    if (ret==0) return SetElementContainerMatrix( ecm, caseId );
    else return ret;
}
//////////////////////////////////////////////////////////
Int4 UtsusemiEventDataConverterNeunetWithPH::
SetElementContainerMatrix( ElementContainerMatrix* ecm, std::vector<UInt4> runNumbers, std::string pathToData, std::string pathToT0data, UInt4 caseId ){
    Int4 ret = LoadEventDataFiles( runNumbers, pathToData, pathToT0data );
    if (ret==0) return SetElementContainerMatrix( ecm, caseId );
    else return ret;
}

//////////////////////////////////////////////////////////
Int4 UtsusemiEventDataConverterNeunetWithPH::
_SetElementContainerMatrix( ElementContainerMatrix* ecm, UInt4 caseId ){

    std::vector< std::vector< std::vector< std::vector<Int4>* >* >* >* pixelInfoStore = _EventDecoder->_wirInfo->PixelInfoStore;
    std::vector< std::vector<Double>* >* detPositionInfoVect = _EventDecoder->_detInfo->detPositionInfoVect;

    HeaderBase* ecm_h = ecm->PutHeaderPointer();
    if (!AddRunInfoToHeader( ecm_h, caseId )){
        return -4;
    }

    UInt4 outerPixelId=0;
    Int4 tofBinType = -1;
    while(true){
        if (_EventDecoder->_wirInfo->TofBinInfoList[outerPixelId]!=NULL){
            std::vector<Double>* tofBinInfo = _EventDecoder->_wirInfo->TofBinInfoList[outerPixelId];

            UInt4 tof_pat_id = (UInt4)(tofBinInfo->at(0));
            if (_EventDecoder->_wirInfo->TofBinPtnInfo[ tof_pat_id ]!=NULL){
                tofBinType = _EventDecoder->_wirInfo->TofBinPtnInfo[ tof_pat_id ]->type;
                break;
            }
        }
        outerPixelId++;
    }

    if (tofBinType<0) return -3;

    std::vector<std::string> process_h;
    process_h.push_back( "E2H" );

    ecm_h->Add( UTSUSEMI_KEY_HEAD_DATAPROCESSED, process_h );

    std::vector<Int4> table_ECA;
    UInt4 index_ECA = 0;
    for (UInt4 daqId=0; daqId<(pixelInfoStore->size()); daqId++){
        if (pixelInfoStore->at(daqId)==NULL) continue;
        for (UInt4 modNo=0; modNo<(pixelInfoStore->at(daqId)->size()); modNo++){
            if (pixelInfoStore->at(daqId)->at(modNo)==NULL) continue;
            for (UInt4 psdNo=0; psdNo<(pixelInfoStore->at(daqId)->at(modNo)->size()); psdNo++){
                UInt4 detId = pixelInfoStore->at(daqId)->at(modNo)->at(psdNo)->at(1);
                if (detId<0) continue;
                if (table_ECA.size()<=detId) table_ECA.resize( detId+1,-1 );
                table_ECA[detId]=index_ECA;
                index_ECA++;
            }
        }
    }
    clock_t t1,t2;
    t1=clock();

    ecm->Allocate(index_ECA);

    std::vector<Int4> bankIdList = _EventDecoder->_detInfo->PutBankIdList();
    std::vector<std::string> bankNameList = _EventDecoder->_detInfo->PutBankName();
    bool isSetBankInfo = true;
    if (bankIdList.empty()) isSetBankInfo = false;

    UInt4 num_of_det = (_EventDecoder->_wirInfo->MaxDetId)+1;
    std::vector<Int4> hashTableOfBankId( num_of_det, -1 );
    std::vector<Int4> hashTableOfIndexInBank( num_of_det, -1 );
    std::vector<Int4> bankSizeList( bankIdList.size(), 0 );
    if (isSetBankInfo){
        //ecm_h->Add( UTSUSEMI_KEY_HEAD_BANKIDLIST, bankIdList );
        //ecm_h->Add( UTSUSEMI_KEY_HEAD_BANKNAMELIST, bankNameList );

        for (UInt4 i=0; i<bankIdList.size(); i++){
            std::vector<Int4> tmp = _EventDecoder->_detInfo->PutDetIdInBank( bankIdList[i] );
            if (tmp.empty()){
            }else{
                bankSizeList[i]=(Int4)(tmp.size());
                for (UInt4 j=0; j<tmp.size(); j++){
                    if (tmp[j]<0){
                    }else{
                        if (tmp[j]<(Int4)num_of_det) {
                            hashTableOfBankId[(UInt4)(tmp[j])]=bankIdList[i];
                            hashTableOfIndexInBank[(UInt4)(tmp[j])]=j;
                        }
                    }
                }
            }
        }
        //ecm_h->Add( UTSUSEMI_KEY_HEAD_BANKSIZELIST, bankSizeList );
    }


#ifdef MULTH
    omp_set_num_threads( _NumOfMulTh );
#endif

    for (UInt4 daqId=0; daqId<(pixelInfoStore->size()); daqId++){
        if (pixelInfoStore->at(daqId)==NULL) continue;
        for (UInt4 modNo=0; modNo<(pixelInfoStore->at(daqId)->size()); modNo++){
            if (pixelInfoStore->at(daqId)->at(modNo)==NULL) continue;
            for (UInt4 psdNo=0; psdNo<(pixelInfoStore->at(daqId)->at(modNo)->size()); psdNo++){
                UInt4 detId = pixelInfoStore->at(daqId)->at(modNo)->at(psdNo)->at(1);
                if (detId<0) continue;
                Int4 head_pixelId = pixelInfoStore->at(daqId)->at(modNo)->at(psdNo)->at(2);
                Int4 num_pixels = pixelInfoStore->at(daqId)->at(modNo)->at(psdNo)->at(3);

                ElementContainerArray* ECA = new ElementContainerArray();
                HeaderBase* h_ECA = ECA->PutHeaderPointer();
                h_ECA->Add( std::string(UTSUSEMI_KEY_HEAD_MASKED), 0 );
                h_ECA->Add( std::string(UTSUSEMI_KEY_HEAD_DETTYPE), std::string(UTSUSEMI_KEY_HEAD_DETTYPE_PSD) );
                h_ECA->Add( std::string("PSDID"), Int4(detId) );
                h_ECA->Add( std::string(UTSUSEMI_KEY_HEAD_DETID), Int4(detId) );
                if (isSetBankInfo) {
                    h_ECA->Add( std::string(UTSUSEMI_KEY_HEAD_BANKID), hashTableOfBankId[detId] );
                    h_ECA->Add( std::string(UTSUSEMI_KEY_HEAD_INDEXINBANK), hashTableOfIndexInBank[detId] );
                }
                std::vector<Int4> maskedEC;
                maskedEC.push_back(-1);
                h_ECA->Add( std::string(UTSUSEMI_KEY_HEAD_MASKDEC), maskedEC );
                h_ECA->Add( "PulseHeight", PutPulseHeight(detId) );

                ECA->Allocate( (UInt4)num_pixels );

                if (detPositionInfoVect!=NULL)
                    if (detId<detPositionInfoVect->size())
                        if (detPositionInfoVect->at(detId)!=NULL)
                            h_ECA->Add( std::string(UTSUSEMI_KEY_HEAD_DETPOSINFO), *(detPositionInfoVect->at(detId)) );

#pragma omp parallel for
#if (_OPENMP >= 200805)  // OpenMP 3.0 and later
                for (UInt4 pixel=0; pixel<(UInt4)num_pixels; pixel++){
#else
                for (Int4 pixel=0; pixel<num_pixels; pixel++){
#endif
                    UInt4 pixelId = head_pixelId + pixel;
                    ElementContainer* EC = new ElementContainer();
                    HeaderBase* h_EC = EC->PutHeaderPointer();
                    h_EC->Add(std::string("PSDID"), Int4(detId) );
                    h_EC->Add(std::string(UTSUSEMI_KEY_HEAD_DETID), Int4(detId) );
                    h_EC->Add(std::string(UTSUSEMI_KEY_HEAD_MASKED), 0 );
                    h_EC->Add(std::string(UTSUSEMI_KEY_HEAD_PIXELID), Int4(pixelId) );

                    std::string label = "Run"+stools->Int4ToString(_runNumber)+"("+stools->Int4ToString(detId)+","+stools->Int4ToString(pixel)+")";
                    h_EC->Add(std::string(UTSUSEMI_KEY_HEAD_LABEL), label );

                    std::vector<Double> ppv(3,0.0);
                    ppv[0] = _EventDecoder->_pixelPositionVect[ pixelId ]->at(0);
                    ppv[1] = _EventDecoder->_pixelPositionVect[ pixelId ]->at(1);
                    ppv[2] = _EventDecoder->_pixelPositionVect[ pixelId ]->at(2);
                    h_EC->Add(std::string(UTSUSEMI_KEY_HEAD_PIXELPOSITION),ppv);
                    h_EC->Add(std::string(UTSUSEMI_KEY_HEAD_PIXELSOLIDANGLE), _EventDecoder->_pixelSolidAngleVect[ pixelId ] );

                    SetElementContainerNeunet( pixelId, EC, caseId );

                    EC->AddToHeader(std::string(UTSUSEMI_KEY_HEAD_TOTALCOUNTS), EC->Sum() );

                    ECA->Set( pixel, EC );

                }
                ecm->Set( table_ECA[detId], ECA );
            }
        }

    }

    if (isSetBankInfo) {
        UtsusemiMessage(_MessageTag+" Create Bank Info" );
        std::vector<bool> reqBank( bankIdList.size(), false );
        for (UInt4 i=0;i<ecm->PutSize();i++){
            HeaderBase* hhh = ecm->PutPointer(i)->PutHeaderPointer();
            if (hhh->CheckKey( std::string(UTSUSEMI_KEY_HEAD_BANKID) )==1){
                Int4 bank_id = hhh->PutInt4( std::string(UTSUSEMI_KEY_HEAD_BANKID) );
                if (bank_id<0){
                    Int4 det_id = hhh->PutInt4( std::string(UTSUSEMI_KEY_HEAD_DETID) );
                    UtsusemiWarning( _MessageTag+"DETID="+stools->UInt4ToString(det_id)+" is not set in bank info" );
                }else{
                    if (reqBank[bank_id]) continue;
                    else reqBank[bank_id]=true;
                }
            }else{
                UtsusemiWarning( _MessageTag+"ecm("+stools->UInt4ToString(i)+") has no key BANKID" );
            }
        }
        std::vector<Int4> set_bankIdList;
        std::vector<std::string> set_bankNameList;
        std::vector<Int4> set_bankSizeList;
        for (UInt4 i=0;i<bankIdList.size();i++){
            if (reqBank[ bankIdList[i] ]){
                set_bankIdList.push_back( bankIdList[i] );
                set_bankNameList.push_back( bankNameList[i] );
                set_bankSizeList.push_back( bankSizeList[i] );
            }
        }
        ecm_h->Add( UTSUSEMI_KEY_HEAD_BANKIDLIST, set_bankIdList );
        ecm_h->Add( UTSUSEMI_KEY_HEAD_BANKNAMELIST, set_bankNameList );
        ecm_h->Add( UTSUSEMI_KEY_HEAD_BANKSIZELIST, set_bankSizeList );
    }

    t2 = clock();
    UtsusemiMessage( _MessageTag+">> Cost of time="+stools->DoubleToString(t2-t1) );
    return 0;
}

//////////////////////////////////////////////////////////
void UtsusemiEventDataConverterNeunetWithPH::
LoadTrignetEventFile( UInt4 runno, std::string pathToData, std::string pathToT0data )
{
    SetDataPath( pathToData, pathToT0data, runno );
    if (_isReady){
        std::vector< std::vector<Int4>* >* caseInfoStore = _EventDecoder->_wirInfo->TrigInfoStore;
        if (caseInfoStore!=NULL){
            for (UInt4 i=0; i<caseInfoStore->size(); i++){
                if (caseInfoStore->at(i)!=NULL){
                    Int4 type = caseInfoStore->at(i)->at(0);
                    Int4 daq = caseInfoStore->at(i)->at(1);
                    Int4 mod = caseInfoStore->at(i)->at(2);

                    char key_c[30];
                    //std::snprintf( key_c, sizeof(key_c), "%3s%06d_%02d_%03d", _instCode.c_str(), _runNumber, daq, mod );
                    std::snprintf( key_c, sizeof(key_c), "%02d_%03d", daq, mod );
                    std::string key( key_c );
                    std::vector<std::string> dfiles = _dataFileList.Put( key );
                    std::vector<std::string> tfiles = _t0dataFileList.Put( key );
                    /*
                    std::cout << "@@@ LoadTrignetEventFile i=" << i << std::endl;
                    std::cout << "@@@ data files = ";
                    for (UInt4 j=0;j<dfiles.size();j++) std::cout << dfiles[j]+",";
                    std::cout << std::endl;
                    std::cout << "@@@ t0data files = ";
                    for (UInt4 j=0;j<tfiles.size();j++) std::cout << tfiles[j]+",";
                    std::cout << std::endl;
                    */
                    ReadCaseEvent( i, dfiles, tfiles );
                }
            }
        }else{
            UtsusemiError( _MessageTag+"LoadTrigEventFiles >>> caseInfoStore is NULL " );
        }
        //ReadCaseEvent();
            if (!(_isReady)){
                UtsusemiError( _MessageTag+"LoadTrigEventFiles >>> fails to read event data files " );
            return;
        }
    }else{
        UtsusemiError( _MessageTag+"LoadTrigEventFiles >>> Not Found Data Folder." );
    }
}
//////////////////////////////////////////////////////////
void UtsusemiEventDataConverterNeunetWithPH::
ReadTrignetEventFile( std::string pathToTrigData, UInt4 index ){
    //std::vector<std::string> files(index+1,"");
    //files[index] = pathToTrigData;
    //ReadCaseEventFiles( files );
    std::vector<std::string> tmp1(1,pathToTrigData);
    std::vector<std::string> tmp2;
    tmp2.clear();
    ReadCaseEventFiles( index, tmp1, tmp2 );
}
//////////////////////////////////////////////////////////
std::vector<UInt4> UtsusemiEventDataConverterNeunetWithPH::
DumpCaseTable(UInt4 i1, UInt4 i2, bool isI1Size, bool isI2Size ){
    std::vector<UInt4> ret;
    ret.clear();

    if (_CaseDecoder->PutCaseTable()==NULL){
        std::cout << "@@@@ NULL" << std::endl;
        return ret;
    }
    if (isI1Size){
        ret.push_back( (UInt4)(_CaseDecoder->PutCaseTable()->size()) );
    }else if (isI2Size){
        if (i1<(_CaseDecoder->PutCaseTable()->size())){
            ret.push_back( (UInt4)(_CaseDecoder->PutCaseTable()->at(i1)->size())/2 );
        }
    }else if (i1<(_CaseDecoder->PutCaseTable()->size())){
        if (i2<((_CaseDecoder->PutCaseTable()->at(i1)->size())/2)){
            ret.push_back( _CaseDecoder->PutCaseTable()->at(i1)->at(i2*2) );
            ret.push_back( _CaseDecoder->PutCaseTable()->at(i1)->at(i2*2+1) );
        }
    }
    return ret;
}

//////////////////////////////////////////////////////////
Int4 UtsusemiEventDataConverterNeunetWithPH::
SetElementContainerMatrixForPseudOnLineMon( ElementContainerMatrix* ecm, UInt4 caseId, UInt4 runNo ){
    _runNumber=runNo;
    return _SetElementContainerMatrix( ecm, caseId );
}
//////////////////////////////////////////////////////////
Int4 UtsusemiEventDataConverterNeunetWithPH::
SetDataPathTest( std::string dataPath, std::string t0Path, UInt4 runNo ){
    std::cout << "@@@ " << dataPath << "," << t0Path << "," << runNo << std::endl;
    SetDataPath( dataPath, t0Path, runNo );
    if (_isReady){
        return 0;
    }else{
        return -1;
    }
}
//////////////////////////////////////////////////////////
std::vector<Double> UtsusemiEventDataConverterNeunetWithPH::
PutListOfCounterConditions(){
    std::vector< std::pair<Double,Double> > cond_list =  _CaseDecoder->PutFilter()->PutListOfCounterConditions();
    std::vector<Double> ret;
    //std::cout << "### cond_list.size()=" << cond_list.size()<<std::endl;
    for (UInt4 i=0;i<cond_list.size();i++){
        ret.push_back( cond_list[i].first );
        ret.push_back( cond_list[i].second );
    }
    return ret;
}
//////////////////////////////////////////////////////////
ElementContainer UtsusemiEventDataConverterNeunetWithPH::
PutPulseHeightOfDet( ElementContainerMatrix* ecm, UInt4 OuterDetId, UInt4 binSize ){
    ElementContainer ret;
    if (PutPulseHeightOfDet(ecm, &ret, binSize)){
    }else{
    }
    return ret;
}
//////////////////////////////////////////////////////////
bool UtsusemiEventDataConverterNeunetWithPH::
PutPulseHeightOfDet(ElementContainerMatrix* ecm, ElementContainer* retec, UInt4 OuterDetId, UInt4 binSize){
    SearchInHeader *_SIH = new SearchInHeader( ecm );
    _SIH->SearchArray("DetId", OuterDetId );
    std::vector< std::vector<UInt4> > res = _SIH->PutResults();
    delete _SIH;
    if (res.empty()){
        return false;
    }else
        return PutPulseHeightOfDet(ecm->PutPointer(res[0][0]), retec, binSize);
}
//////////////////////////////////////////////////////////
ElementContainer UtsusemiEventDataConverterNeunetWithPH::
PutPulseHeightOfDet( ElementContainerArray* eca, UInt4 binSize ){
    ElementContainer ec;
    if (PutPulseHeightOfDet(eca, &ec, binSize)){
    }else{
        UtsusemiError(_MessageTag + "Failed PutPulseHeightOfDet");
    }
    return ec;
}
//////////////////////////////////////////////////////////
bool UtsusemiEventDataConverterNeunetWithPH::
PutPulseHeightOfDet(ElementContainerArray* eca, ElementContainer* retec, UInt4 binSize){

    std::vector<Int4> ph_vec = eca->PutHeaderPointer()->PutInt4Vector("PulseHeight");

    UInt4 ph_bin_val = 0;
    std::vector<Double> xv,yv,ev;
    while((ph_bin_val+binSize)<(ph_vec.size())){
        xv.push_back( (Double)(ph_bin_val) );
        if (binSize==1){
            yv.push_back( ph_vec[ph_bin_val] );
        }else{
            Int4 tmp = 0;
            for (UInt4 i=0; i<binSize; i++)
                tmp += ph_vec[ph_bin_val+i];
            yv.push_back( (Double)tmp );
        }
        ph_bin_val += binSize;
    }
    xv.push_back( ph_bin_val );
    ev.resize( yv.size(), 0.0 );
    for (UInt4 i=0; i<(yv.size()); i++) ev[i] = sqrt( yv[i] );

    retec->Add("PulseHeight", xv);
    retec->Add("Counts", yv, "Counts");
    retec->Add(UTSUSEMI_KEY_ERROR, ev, "Counts");
    retec->SetKeys("PulseHeight","Counts",UTSUSEMI_KEY_ERROR);
    HeaderBase *hh=retec->PutHeaderPointer();
    hh->Add("DetId", eca->PutHeaderPointer()->PutInt4(UTSUSEMI_KEY_HEAD_DETID) );
    std::string label = "DetId="+stools->Int4ToString(eca->PutHeaderPointer()->PutInt4(UTSUSEMI_KEY_HEAD_DETID));
    hh->Add(UTSUSEMI_KEY_HEAD_LABEL, label );
    return true;

}
//////////////////////////////////////////////////////////
ElementContainerArray UtsusemiEventDataConverterNeunetWithPH::
PutPulseHeightAll( ElementContainerMatrix* ecm, UInt4 binSize ){
    ElementContainerArray eca(ecm->PutHeader());
    if (PutPulseHeightAll(ecm, &eca, binSize))
        return eca;
    else{
        ElementContainerArray empty;
        return empty;
    }
}
//////////////////////////////////////////////////////////
bool UtsusemiEventDataConverterNeunetWithPH::
PutPulseHeightAll( ElementContainerMatrix* ecm, ElementContainerArray* reteca, UInt4 binSize ){
    reteca->InputHeader(ecm->PutHeader());
    UInt4 num_of_det= ecm->PutSize();
    if (num_of_det == 0) return false;
    std::vector<UInt4> list_detid;
    bool hasDetId = true;
    for (UInt4 i=0; i<num_of_det; i++){
        HeaderBase* hh=ecm->PutPointer(i)->PutHeaderPointer();
        if (hh->CheckKey("DetId")==0) {
            hasDetId = false;
            break;
        }
        list_detid.push_back( hh->PutInt4("DetId") );
    }

    if (hasDetId){
        sort( list_detid.begin(), list_detid.end() );
        for (UInt4 i=0; i<list_detid.size(); i++){
            ElementContainer ec;
            if (PutPulseHeightOfDet(ecm, &ec, list_detid[i], binSize))
                reteca->Add(ec);
        }
    }else{
        for (UInt4 i=0; i<(ecm->PutSize()); i++){
            ElementContainer ec;
            if (PutPulseHeightOfDet(ecm->PutPointer(i), &ec, binSize))
                reteca->Add(ec);
        }
    }

    return true;
}
