#include "WiringInfoEditorNeunet.hh"
//////////////////////////////////////////////////////////
WiringInfoDefineNeunet::
WiringInfoDefineNeunet(){
}
//////////////////////////////////////////////////////////
WiringInfoDefineNeunet::
~WiringInfoDefineNeunet(){
}
//////////////////////////////////////////////////////////
const std::string WiringInfoDefineNeunet::WINFO_PSDPARAM="psdParam";
const std::string WiringInfoDefineNeunet::WINFO_PSDPARAM_PARAM="parameter";
const std::string WiringInfoDefineNeunet::WINFO_PSDPARAM_PARAM_AT_ID="detId";

const std::string WiringInfoDefineNeunet::WINFO_PSDBININFO="psdBinInfo";
const std::string WiringInfoDefineNeunet::WINFO_PSDBININFO_AT_SETID="psdBinSetId";
const std::string WiringInfoDefineNeunet::WINFO_PSDBININFO_BIN="positionBin";
const std::string WiringInfoDefineNeunet::WINFO_PSDBININFO_BIN_AT_NUM="numPixel";
const std::string WiringInfoDefineNeunet::WINFO_PSDBININFO_BIN_AT_DELTA="deltaX";
const std::string WiringInfoDefineNeunet::WINFO_PSDBININFO_BIN_AT_OFFSET="offsetX";


//////////////////////////////////////////////////////////
UtsusemiPsdParam::
UtsusemiPsdParam(){
    detId = 0;
    valA = 0.0;
    valB = 0.0;
    valC = 0.0;
    upperPH = 0.0;
    lowerPH = 0.0;
}
//////////////////////////////////////////////////////////
UtsusemiPsdParam::
UtsusemiPsdParam( const UtsusemiPsdParam& obj ){
    detId = obj.detId;
    valA = obj.valA;
    valB = obj.valB;
    valC = obj.valC;
    upperPH = obj.upperPH;
    lowerPH = obj.lowerPH;
}
//////////////////////////////////////////////////////////
UtsusemiPsdParam::
~UtsusemiPsdParam(){
}

//////////////////////////////////////////////////////////
UtsusemiPsdBinInfo::
UtsusemiPsdBinInfo(){
    numPixel = 0;
    deltaX = 0.0;
    offsetX = 0.0;
    conts.clear();
}
//////////////////////////////////////////////////////////
UtsusemiPsdBinInfo::
UtsusemiPsdBinInfo( const UtsusemiPsdBinInfo& obj ){
    numPixel = obj.numPixel;
    deltaX = obj.deltaX;
    offsetX = obj.offsetX;
    conts.clear();
    for (UInt4 i=0; i<obj.conts.size(); i++)
        conts.push_back( obj.conts[i] );

}
//////////////////////////////////////////////////////////
UtsusemiPsdBinInfo::
~UtsusemiPsdBinInfo(){
}
//////////////////////////////////////////////////////////
bool UtsusemiPsdBinInfo::
SetConts( std::string _conts ){
    StringTools _st;
    std::vector<std::string> parts = _st.SplitString( _conts,"," );
    if (parts.empty()){
        UtsusemiError("UtsusemiPsdBinInfo::SetConts > params is empty.("+_conts+")");
        return false;
    }
    for (UInt4 i=0; i<parts.size(); i++){
        std::string pbody = parts[i];
        transform( pbody.begin(), pbody.end(), pbody.begin(), ::toupper);
        if (pbody.find("ALL")!=std::string::npos){
            conts.clear();
            return true;
        }else{
            std::pair<UInt4,UInt4> prange;
            prange.first=0;
            prange.second=0;
            std::vector<std::string> tmp = _st.SplitString( pbody, "-" );
            if (tmp.size()==1){
                prange.first = _st.StringToInt4( tmp[0] );
                prange.second = prange.first;
            }else if (tmp.size()==2){
                prange.first = _st.StringToInt4( tmp[0] );
                prange.second = _st.StringToInt4( tmp[1] );
            }else{
                UtsusemiError("UtsusemiPsdBinInfo::SetConts > Conts are invalid ="+_conts);
                return false;
            }
            conts.push_back( prange );
        }
    }
    return true;
}
//////////////////////////////////////////////////////////
bool UtsusemiPsdBinInfo::
SetNewNumOfPixel( UInt4 num_of_pixel ){
    if (num_of_pixel==numPixel) return true;
    if (num_of_pixel==0) return true;

    Double new_deltaX = (double)deltaX*((double)numPixel/(double)num_of_pixel);
    numPixel = num_of_pixel;
    deltaX = new_deltaX;
    return true;
}
//////////////////////////////////////////////////////////
std::string UtsusemiPsdBinInfo::
PutContsAsString(){
    //if (conts.empty()) std::cout << "--- conts is empty" << std::endl;
    //for (UInt4 i=0; i<conts.size(); i++){
    //    std::cout << "conts["<<i<<"]="<< conts[i].first <<","<<conts[i].second<<std::endl;
    //}
    std::string ret = "";
    StringTools _st;
    if (conts.empty()){
        ret = "ALL";
    }else{
        for (UInt4 i=0; i<(conts.size()-1); i++){
            //std::cout << "i=" << i << ":" << conts[i].first << "," << conts[i].second << std::endl;
            if (conts[i].first==conts[i].second){
                ret += _st.UInt4ToString( conts[i].first )+",";
            }else{
                ret += _st.UInt4ToString( conts[i].first )+"-";
                ret += _st.UInt4ToString( conts[i].second )+",";
            }
        }
        //std::cout << "last=" << conts.back().first << "," << conts.back().second << std::endl;
        if (conts.back().first==conts.back().second){
            ret += _st.UInt4ToString( conts.back().first );
        }else{
            ret += _st.UInt4ToString( conts.back().first )+"-";
            ret += _st.UInt4ToString( conts.back().second );
        }
    }
    return ret;
}
//////////////////////////////////////////////////////////
WiringInfoEditorNeunet::
WiringInfoEditorNeunet(){
    _MessageTag = "WiringInfoEditorNeunet::";
    PsdParamsList=NULL;
    _withPH = false;
}
//////////////////////////////////////////////////////////
WiringInfoEditorNeunet::
WiringInfoEditorNeunet(std::string wfile, bool workAsReader ){
    _MessageTag = "WiringInfoEditorNeunet::";
    _withPH = false;
    PsdParamsList=NULL;
    _Status = Read( wfile );
    if (_Status)
        _Status = SetInfoAsReader();

}
//////////////////////////////////////////////////////////
WiringInfoEditorNeunet::
~WiringInfoEditorNeunet(){
    Clear(0);
    ClearReader(0);
}
const std::string WiringInfoEditorNeunet::PSD_A="A";
const std::string WiringInfoEditorNeunet::PSD_B="B";
const std::string WiringInfoEditorNeunet::PSD_C="C";
const std::string WiringInfoEditorNeunet::PSD_LLD="LLD";
const std::string WiringInfoEditorNeunet::PSD_HLD="HLD";

const Int4 WiringInfoEditorNeunet::DUMP_PSDPARAMS=11;
const Int4 WiringInfoEditorNeunet::DUMP_PSDBININFO=12;

//////////////////////////////////////////////////////////
void WiringInfoEditorNeunet::
Clear( UInt4 index ){
    WiringInfoEditorBase::Clear( index );
    if ((index==0)||(index==7)){
        for (UInt4 i=0; i<PsdParams.size(); i++)
            if (PsdParams[i]!=NULL) delete PsdParams[i];
        PsdParams.clear();
    }
    if ((index==0)||(index==8)){
        for (UInt4 i=0; i<PsdBinInfo.size(); i++)
            if (PsdBinInfo[i]!=NULL) delete PsdBinInfo[i];
        PsdBinInfo.clear();
    }
}
//////////////////////////////////////////////////////////
void WiringInfoEditorNeunet::
ClearReader( UInt4 index ){
    WiringInfoEditorBase::ClearReader( index );
    if ((index==0)||(index==7)){
        if (PsdParamsList!=NULL){
            for (UInt4 i=0; i<(PsdParamsList->size()); i++){
                if (PsdParamsList->at(i)!=NULL) delete PsdParamsList->at(i);
            }
        }
        delete PsdParamsList;
        PsdParamsList=NULL;
    }
    if ((index==0)||(index==8)){
        for (UInt4 i=0; i<(PsdBinInfoList.size()); i++)
            if (PsdBinInfoList[i]!=NULL) delete PsdBinInfoList[i];
        PsdBinInfoList.clear();
    }
}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
Read( std::string arg ){
    if (WiringInfoEditorBase::Read( arg )){
        ImportPsdParams();
        ImportPsdInfo();
        return true;
    }
    return false;
}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
Write( std::string filepath ){

    if (_makeOutputXmlNeunet()){
        _parser->Save( KEY_WRITE_XML, filepath );
    }else{
        return false;
    }
    return true;
}
//////////////////////////////////////////////////////////
std::string WiringInfoEditorNeunet::
OutXml( bool withIndent ){
    if (_makeOutputXmlNeunet()){
        return _parser->OutToString( KEY_WRITE_XML, "", withIndent );
    }else{
        UtsusemiError( _MessageTag+"OutXml : false to make output XML from given information. " );
        return "";
    }
}
//////////////////////////////////////////////////////////
void WiringInfoEditorNeunet::
ImportPsdParams(){
    for (UInt4 i=0; i<PsdParams.size(); i++)
        if (PsdParams[i]!=NULL) delete PsdParams[i];
    PsdParams.clear();

    if (_parser->hasPath( KEY_READ_XML, TAG.WINFO )){
        std::string psdparam_path = TAG.WINFO+"/"+TAG.WINFO_PSDPARAM;
        if (_parser->hasPath( KEY_READ_XML, psdparam_path )){
            std::string psdparam_param_path = psdparam_path+"/"+TAG.WINFO_PSDPARAM_PARAM;
            std::vector<std::string> psdparam_list = _parser->PutAttValList( KEY_READ_XML, psdparam_param_path, TAG.WINFO_PSDPARAM_PARAM_AT_ID );
            std::vector<UInt4> param_list;
            param_list.reserve( psdparam_list.size() );
            for (std::vector<std::string>::iterator it=psdparam_list.begin(); it!=psdparam_list.end(); ++it)
                param_list.push_back( _st->StringToUInt4( *it ) );
            sort( param_list.begin(), param_list.end() );

            for (std::vector<UInt4>::iterator it=param_list.begin(); it!=param_list.end(); ++it){
                std::string a_psdparam_path = psdparam_param_path+","+TAG.WINFO_PSDPARAM_PARAM_AT_ID+"="+_st->UInt4ToString( *it );
                std::string conts = _parser->PutContent( KEY_READ_XML, a_psdparam_path, "" );
                if ((*it)>=PsdParams.size()) PsdParams.resize( (*it)+1, NULL );
                if (PsdParams[ (*it) ] == NULL) PsdParams[ (*it) ] = new UtsusemiPsdParam();
                UtsusemiPsdParam *psdp = PsdParams[ (*it) ];
                psdp->detId = (*it);
                std::vector<std::string> tmp = _st->SplitString( conts, "," );
                if (tmp.size()<5){
                    UtsusemiError(_MessageTag+"ImportPsdParams > PsdParam is invalid format ");
                    return;
                }
                psdp->valA = _st->StringToDouble( tmp[0] );
                psdp->valB = _st->StringToDouble( tmp[1] );
                psdp->valC = _st->StringToDouble( tmp[2] );
                psdp->lowerPH = _st->StringToDouble( tmp[3] );
                psdp->upperPH = _st->StringToDouble( tmp[4] );

            }
        }
    }
}
//////////////////////////////////////////////////////////
void WiringInfoEditorNeunet::
ImportPsdInfo(){
    for (UInt4 i=0; i<PsdBinInfo.size(); i++)
        if (PsdBinInfo[i]!=NULL) delete PsdBinInfo[i];
    //PsdBinInfo.clear();
    Clear(8);

    if (_parser->hasPath( KEY_READ_XML, TAG.WINFO )){
        std::string psdbininfo_path = TAG.WINFO+"/"+TAG.WINFO_PSDBININFO;
        if (_parser->hasPath( KEY_READ_XML, psdbininfo_path )){
            std::string posbin_path = psdbininfo_path+"/"+TAG.WINFO_PSDBININFO_BIN;
            std::vector<std::string> posbin_list = _parser->PutAttValList( KEY_READ_XML, posbin_path, "i" );
            for (std::vector<std::string>::iterator it=posbin_list.begin(); it!=posbin_list.end(); ++it){
                std::string a_posbin_path = posbin_path+",i="+(*it);

                UtsusemiPsdBinInfo* pbi = new UtsusemiPsdBinInfo();
                pbi->numPixel = _st->StringToUInt4( _parser->PutContent( KEY_READ_XML, a_posbin_path, TAG.WINFO_PSDBININFO_BIN_AT_NUM ) );
                pbi->deltaX = _st->StringToDouble( _parser->PutContent( KEY_READ_XML, a_posbin_path, TAG.WINFO_PSDBININFO_BIN_AT_DELTA ) );
                pbi->offsetX = _st->StringToDouble( _parser->PutContent( KEY_READ_XML, a_posbin_path, TAG.WINFO_PSDBININFO_BIN_AT_OFFSET ) );
                //pbi->conts = _parser->PutContent( KEY_READ_XML, a_posbin_path,"" );
                pbi->SetConts( _parser->PutContent( KEY_READ_XML, a_posbin_path,"" ) );
                PsdBinInfo.push_back( pbi );
            }
        }
    }
}
//////////////////////////////////////////////////////////
std::vector<Double> WiringInfoEditorNeunet::
PutPsdParams( UInt4 detId ){
    std::vector<Double> ret;
    if ((detId>=PsdParams.size())||(PsdParams[detId]==NULL)){
        UtsusemiError(_MessageTag+"PutPsdParams > No such detId in loaded PsdParam");
        return ret;
    }
    UtsusemiPsdParam* psdp = PsdParams[detId];
    ret.resize(5,0.0);
    ret[0] = psdp->valA;
    ret[1] = psdp->valB;
    ret[2] = psdp->valC;
    ret[3] = psdp->lowerPH;
    ret[4] = psdp->upperPH;
    return ret;
}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
SetPsdParams( UInt4 detId, Double Aval, Double Bval, Double Cval, Double PHlow, Double PHup ){
    if (detId>=PsdParams.size()) PsdParams.resize( detId+1, NULL );
    if (PsdParams[detId]==NULL) PsdParams[detId]=new UtsusemiPsdParam();
    UtsusemiPsdParam* psdp = PsdParams[detId];
    psdp->detId=detId;
    psdp->valA = Aval;
    psdp->valB = Bval;
    psdp->valC = Cval;
    psdp->lowerPH = PHlow;
    psdp->upperPH = PHup;

    return true;
}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
SetPsdParams( UInt4 detId, std::string tag, Double val ){
    if (detId>=PsdParams.size()) PsdParams.resize( detId+1, NULL );
    if (PsdParams[detId]==NULL) PsdParams[detId]=new UtsusemiPsdParam();
    UtsusemiPsdParam* psdp = PsdParams[detId];
    if (tag==PSD_A) psdp->valA = val;
    else if (tag==PSD_B) psdp->valB = val;
    else if (tag==PSD_C) psdp->valC = val;
    else if (tag==PSD_LLD) psdp->lowerPH = val;
    else if (tag==PSD_HLD) psdp->upperPH = val;
    else{
        UtsusemiError(_MessageTag+"SetPsdParams >> wrong tag="+tag);
        return false;
    }
    return true;

}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
SetAllPsdParams( std::string tag, Double val ){
    std::vector< UtsusemiPsdParam* >::iterator it = PsdParams.begin();
    bool isSet = true;
    while( it!=PsdParams.end() ){
        if ((*it)!=NULL){
            if (tag==PSD_A) (*it)->valA = val;
            else if (tag==PSD_B) (*it)->valB = val;
            else if (tag==PSD_C) (*it)->valC = val;
            else if (tag==PSD_LLD) (*it)->lowerPH = val;
            else if (tag==PSD_HLD) (*it)->upperPH = val;
            else isSet = false;
        }
        ++it;
    }

    return isSet;
}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
DeletePsdParams( UInt4 start_detId, UInt4 end_detId ){
    if (PsdParams.empty()) return false;
    if ((start_detId>=PsdParams.size())||(end_detId>=PsdParams.size()))
        return false;

    if ((start_detId==0)&&(end_detId==0)) {
        end_detId = (UInt4)(DetInfoList.size())-1;
    }else if ((start_detId!=0)&&(end_detId==0)) {
        end_detId = start_detId;
    }

    for (UInt4 i=start_detId; i<=end_detId; ++i){
        if (PsdParams[i]!=NULL) {
            delete PsdParams[i];
            PsdParams[i]=NULL;
        }
    }

    return true;
}
//////////////////////////////////////////////////////////
void WiringInfoEditorNeunet::
MakePsdInfo( UInt4 numPixel, Double deltaX, Double offsetX ){
    if (PixelInfo==NULL) return;

    std::vector< std::pair<UInt4,UInt4> > stock;
    std::pair<UInt4,UInt4>* numInfo = NULL;
    UInt4 cnt_no_match = 0;
    for (UInt4 i=0; i<DetInfoList.size(); ++i){
        if (DetInfoList[i]!=NULL){
            UInt4 num = PixelInfo->at(DetInfoList[i]->at(0))->ModList[DetInfoList[i]->at(1)]->DetList[DetInfoList[i]->at(2)]->numPixel;
            if (numPixel==num){
                if (numInfo==NULL){
                    numInfo = new std::pair<UInt4,UInt4>;
                    numInfo->first = i;
                    numInfo->second = i;
                }else{
                    numInfo->second = i;
                }
            }else{
                ++cnt_no_match;

                if (numInfo==NULL) continue;

                stock.push_back( *numInfo );
                delete numInfo;
                numInfo = NULL;
            }
        }
    }
    if (numInfo!=NULL) stock.push_back( *numInfo );
    if (stock.empty()) return;

    std::string conts="";
    if (cnt_no_match==0){
        conts = "All";
    }else{
        std::string cc = "";
        for (UInt4 i=0; i<stock.size(); i++){
            std::pair<UInt4,UInt4> t = stock[i];
            if (t.first==t.second) cc += _st->UInt4ToString( t.first );
            else{
                cc += _st->UInt4ToString( t.first ) + "-" + _st->UInt4ToString( t.second );
            }
            cc += ",";
        }

        conts = cc.substr( 0, (cc.size()-1) );
    }
    UtsusemiPsdBinInfo* pbi = new UtsusemiPsdBinInfo();
    pbi->numPixel = numPixel;
    pbi->deltaX = deltaX;
    pbi->offsetX = offsetX;
    //pbi->conts = conts;
    pbi->SetConts( conts );

    PsdBinInfo.push_back( pbi );
}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
SetPsdInfo( UInt4 numPixel, Double deltaX, Double offsetX ,std::string conts ){
    UtsusemiPsdBinInfo* pbi = new UtsusemiPsdBinInfo();
    pbi->numPixel = numPixel;
    pbi->deltaX = deltaX;
    pbi->offsetX = offsetX;
    //pbi->conts = conts;
    pbi->SetConts( conts );

    PsdBinInfo.push_back( pbi );

    return true;
}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
SetNumPixelOfPsdBin( UInt4 num_of_pixel, Int4 start_id, Int4 end_id ){
    bool isFound = false;
    for (UInt4 i=0; i<PsdBinInfo.size(); i++){
        if ((start_id==-1)&&(end_id==-1)){
            if (PsdBinInfo[i]->conts.empty()){
                PsdBinInfo[i]->SetNewNumOfPixel( num_of_pixel );
                return true;
            }
        }else{
            if (PsdBinInfo[i]->conts.empty()){
                PsdBinInfo[i]->SetNewNumOfPixel( num_of_pixel );
                isFound = true;
            }else{
                for (UInt4 j=0; j<PsdBinInfo[i]->conts.size(); j++){
                    std::pair<UInt4,UInt4> p = PsdBinInfo[i]->conts[j];
                    if ( (p.first<=(UInt4)start_id)&&((UInt4)start_id<=p.second) ){
                        PsdBinInfo[i]->SetNewNumOfPixel( num_of_pixel );
                        isFound = true;
                    }
                    if ( (p.first<=(UInt4)end_id)&&((UInt4)end_id<=p.second) ){
                        PsdBinInfo[i]->SetNewNumOfPixel( num_of_pixel );
                        isFound = true;
                    }
                }
            }
        }
    }
    return isFound;
}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
SetPsdInfo( Double deltaX, Double offsetX ,UInt4 start_detId, UInt4 end_detId ){
    if (PixelInfo==NULL) return false;
    if ((start_detId>=DetInfoList.size())||(end_detId>=DetInfoList.size()))
        return false;

    std::string conts = "";
    if ((start_detId==0)&&(end_detId==0)) {
        end_detId = (UInt4)(DetInfoList.size())-1;
        conts = "All";
    }else if ((start_detId!=0)&&(end_detId==0)) {
        end_detId = start_detId;
        conts = _st->UInt4ToString( start_detId );
    }else{
        conts = _st->UInt4ToString( start_detId ) + "-" + _st->UInt4ToString( end_detId );
    }


    //Check num of pixels of selected detectors are same
    UInt4 numPixel = 0;
    for (UInt4 i=start_detId; i<=end_detId; ++i){
        if (DetInfoList[i]!=NULL){
            UInt4 num = PixelInfo->at(DetInfoList[i]->at(0))->ModList[DetInfoList[i]->at(1)]->DetList[DetInfoList[i]->at(2)]->numPixel;
            if (numPixel==0) numPixel=num;
            if (numPixel!=num) return false;
        }
    }

    return SetPsdInfo( numPixel, deltaX, offsetX, conts );
}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
DeletePsdInfo( UInt4 index ){
    if (index==999999999){
        Clear(8);
    }else if (index>(PsdBinInfo.size()-1)) return false;
    else{
        std::vector< UtsusemiPsdBinInfo* >::iterator it =  PsdBinInfo.begin();
        it+=index;
        PsdBinInfo.erase( it );
    }
    return true;
}
//////////////////////////////////////////////////////////
void WiringInfoEditorNeunet::
Dump( Int4 index ){
    WiringInfoEditorBase::Dump( index );
    if  ((index==DUMP_ALL)||(index==DUMP_PSDPARAMS)){
        std::cout << "======== PsdParams ========" << std::endl;
        for (UInt4 i=0; i<PsdParams.size(); i++){
            if (PsdParams[i]!=NULL){
                std::cout << "DetID=" << PsdParams[i]->detId << " : ";
                std::cout << "A=" << PsdParams[i]->valA << ", B=" << PsdParams[i]->valB << ", C=" << PsdParams[i]->valC;
                std::cout << " [ " << PsdParams[i]->lowerPH << "," << PsdParams[i]->upperPH << " ]" << std::endl;
            }
        }
    }
    if  ((index==DUMP_ALL)||(index==DUMP_PSDBININFO)){
        std::cout << "======== PsdBinInfo ========" << std::endl;
        for (UInt4 i=0; i<PsdBinInfo.size(); i++){
            if (PsdBinInfo[i]!=NULL){
                std::cout << "i="<< i << ": numPixel=" << PsdBinInfo[i]->numPixel << ", deltaX=" << PsdBinInfo[i]->deltaX;
                std::cout << ", offsetX=" << PsdBinInfo[i]->offsetX << ", conts = ";
                for (UInt4 j=0; j<(PsdBinInfo[i]->conts.size()); j++){
                    std::cout << "(" << PsdBinInfo[i]->conts[j].first <<","<<PsdBinInfo[i]->conts[j].second<<")";
                }
                std::cout << std::endl;
            }
        }
    }
}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
_makeOutputXmlNeunet(){
    if (WiringInfoEditorBase::_makeOutputXml()){

        std::vector<std::string> att_v, val_v;
        if (DetInfoList.empty()){
        }else{
            for (UInt4 i=0; i<PsdParams.size(); i++){
                if (PsdParams[i]!=NULL){
                    UInt4 detId = PsdParams[i]->detId;
                    if (detId>( DetInfoList.size()-1 )) continue;

                    std::vector<UInt4> *d = DetInfoList[ detId ];
                    if (d==NULL) continue;
                    if ( (PixelInfo->at(d->at(0))->isAlive)&&(PixelInfo->at(d->at(0))->ModList[d->at(1)]->isAlive)
                         &&(PixelInfo->at(d->at(0))->ModList[d->at(1)]->DetList[d->at(2)]->isAlive) ){
                        std::string psdparams_path = TAG.WINFO+"/"+TAG.WINFO_PSDPARAM+"/"+TAG.WINFO_PSDPARAM_PARAM;
                        psdparams_path += ","+TAG.WINFO_PSDPARAM_PARAM_AT_ID+"="+_st->UInt4ToString( detId );
                        std::string conts = _st->DoubleToString( PsdParams[i]->valA )+","+_st->DoubleToString( PsdParams[i]->valB )+",";
                        conts += _st->DoubleToString( PsdParams[i]->valC )+","+_st->DoubleToString( PsdParams[i]->lowerPH )+",";
                        conts += _st->DoubleToString( PsdParams[i]->upperPH );

                        _parser->AddElement( KEY_WRITE_XML, psdparams_path, conts );
                    }
                }
            }
        }

        for (UInt4 i=0; i<PsdBinInfo.size(); i++){
            if (PsdBinInfo[i]!=NULL){
                std::string psdbininfo_path = TAG.WINFO+"/"+TAG.WINFO_PSDBININFO+"/"+TAG.WINFO_PSDBININFO_BIN+",i="+_st->UInt4ToString(i);
                //_parser->AddElement( KEY_WRITE_XML, psdbininfo_path, PsdBinInfo[i]->conts );
                _parser->AddElement( KEY_WRITE_XML, psdbininfo_path, PsdBinInfo[i]->PutContsAsString() );
                att_v.clear();
                val_v.clear();
                att_v.push_back( TAG.WINFO_PSDBININFO_BIN_AT_NUM );
                val_v.push_back( _st->UInt4ToString( PsdBinInfo[i]->numPixel ) );
                att_v.push_back( TAG.WINFO_PSDBININFO_BIN_AT_DELTA );
                //val_v.push_back( _st->UInt4ToString( PsdBinInfo[i]->deltaX ) );
                val_v.push_back( _st->DoubleToString( PsdBinInfo[i]->deltaX ) );
                att_v.push_back( TAG.WINFO_PSDBININFO_BIN_AT_OFFSET );
                //val_v.push_back( _st->UInt4ToString( PsdBinInfo[i]->offsetX ) );
                val_v.push_back( _st->DoubleToString( PsdBinInfo[i]->offsetX ) );
                _parser->AddElement( KEY_WRITE_XML, psdbininfo_path, att_v, val_v );
            }
        }

        att_v.clear();
        val_v.clear();
        att_v.push_back( TAG.WINFO_PSDBININFO_AT_SETID ); // obsolete attribute in near future
        val_v.push_back( "0" );
        _parser->AddElement( KEY_WRITE_XML, TAG.WINFO+"/"+TAG.WINFO_PSDBININFO, att_v, val_v );
    }else{
        UtsusemiError(_MessageTag+"_makeOutputXmlNeunet >> _makeOutputXml fails");
        return false;
    }
    return true;
}

//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
SetDetectorRange( std::vector<UInt4> list_of_num_pixels, std::vector< std::pair< Int4,Int4 > > list_of_det_range, std::string det_type ){
    if ((list_of_num_pixels.size())!=(list_of_det_range.size())){
        return false;
    }

    // All Detectors are OFF
    SetDetAlive( false, 0, (UInt4)(DetInfoList.size())-1 );

    // Make required Detectors ON
    for (UInt4 i=0; i<list_of_num_pixels.size(); i++){
        if ( (list_of_det_range[i].first==-1)&&(list_of_det_range[i].second==-1) ){
            if (list_of_num_pixels[i]!=0){
                SetAllPixelInfo( list_of_num_pixels[i], det_type );
            }
            for (UInt4 detId=0; detId<(DetInfoList.size()); detId++){
                std::vector<UInt4> *det_info = DetInfoList[ detId ];
                if (det_info!=NULL) SetDetAlive( true, detId );

            }
            SetNumPixelOfPsdBin( list_of_num_pixels[i] );
        }else{
            UInt4 first_detId = 0;
            UInt4 last_detId = (UInt4)(DetInfoList.size())-1;
            if ( (list_of_det_range[i].first!=-1)&&(list_of_det_range[i].second==-1) ){
                first_detId = list_of_det_range[i].first;
            }else if ( (list_of_det_range[i].first==-1)&&(list_of_det_range[i].second!=-1) ){
                last_detId = list_of_det_range[i].second;
            }else{
                first_detId = list_of_det_range[i].first;
                last_detId = list_of_det_range[i].second;
            }
            for (UInt4 detId=first_detId; detId<(last_detId+1); detId++){
                std::vector<UInt4> *det_info = DetInfoList[ detId ];
                if (det_info!=NULL){
                    UInt4 daqId = det_info->at(0);
                    UInt4 modNo = det_info->at(1);
                    UInt4 detNo = det_info->at(2);
                    if (list_of_num_pixels[i]!=0){
                        PixelInfo->at(daqId)->ModList[modNo]->DetList[detNo]->numPixel = list_of_num_pixels[i];
                        PixelInfo->at(daqId)->ModList[modNo]->DetList[detNo]->headPixelId = -1;
                    }
                    SetDetAlive( true, detId );
                }
            }
            SetNumPixelOfPsdBin( list_of_num_pixels[i], first_detId, last_detId );
        }
    }
    ResetHeadPixelId();

    return true;
}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
SetDetParam( std::string params ){
    if (!(_isReadXml)){
        UtsusemiError(_MessageTag+"SetDetParam >> SetRunNo must be done at first.");
        return false;
    }
    std::vector<std::string> det_list = _st->SplitString( params, "," );

    _detType = "";
    for (UInt4 i=0; i<det_list.size(); i++){
        std::string a_param = det_list[i];
        std::string a_detType = "";
        Int4 ind1 = (Int4)(a_param.find("["));
        if (ind1==std::string::npos) a_detType=a_param;
        else{
            Int4 ind2 = (Int4)(a_param.find("]"));
            std::string lld_range_st = a_param.substr( (ind1+1),(ind2-ind1-1) );
            std::vector<std::string> lld_range_list = _st->SplitString( lld_range_st, ":" );
            if (lld_range_list.size()==1){
                this->SetAllPsdParams( PSD_LLD, _st->StringToInt4( lld_range_list[0] ) );
            }else if (lld_range_list.size()==2){
                this->SetAllPsdParams( PSD_LLD, _st->StringToInt4( lld_range_list[0] ) );
                this->SetAllPsdParams( PSD_HLD, _st->StringToInt4( lld_range_list[1] ) );
            }
            a_detType=a_param.substr(0,ind1);
        }
        std::string tmp( a_detType );
        transform( tmp.begin(), tmp.end(), a_detType.begin(), ::toupper);
        if ( (a_detType.find(UTSUSEMI_KEY_HEAD_DETTYPE_PSD)==std::string::npos)&&(a_detType.find(UTSUSEMI_KEY_HEAD_DETTYPE_MON)==std::string::npos)
             &&(a_detType.find(UTSUSEMI_KEY_HEAD_DETTYPE_UPSD)==std::string::npos)&&(a_detType.find(UTSUSEMI_KEY_HEAD_DETTYPE_TRIGNET)==std::string::npos) ){
            UtsusemiError(_MessageTag+"SetDetparam params are invalid "+params);
            return false;
        }
        std::size_t ind3 = a_detType.find("-PH");
        if (ind3!=std::string::npos){
            a_detType = a_detType.substr(0,ind3);
            _withPH = true;
        }
        _detType+=(a_detType+",");
    }
    std::string tmp = _detType.erase( _detType.size()-1 );

    return this->SetUseDetectorType( _detType );
    /*
    std::pair<Double,Double> lld;
    lld.first = 0.0;
    lld.second = 10000.0;
    std::vector<std::string> tmp2 = _st->SplitString( tmp[0], "-" );
    _detType.resize( tmp2[0].size() );
    transform( tmp2[0].begin(), tmp2[0].end(), _detType.begin(), ::toupper);

    if ( (_detType.find(UTSUSEMI_KEY_HEAD_DETTYPE_PSD)==std::string::npos)&&(_detType.find(UTSUSEMI_KEY_HEAD_DETTYPE_MON)==std::string::npos)&&
         (_detType.find(UTSUSEMI_KEY_HEAD_DETTYPE_UPSD)==std::string::npos) ){
        std::cout << _MessageTag+"SetDetparam params are invalid "+params << std::endl;
        return false;
    }

    if (tmp2.size()==2){
        std::string ph_s( tmp2[1] );
        transform( ph_s.begin(), ph_s.end(), ph_s.begin(), ::toupper);
        if ( ph_s.find("PH")!=std::string::npos ) _withPH = true;
        else _withPH = false;
    }

    if (tmp.size()>1){
        if (tmp.size()==2) {
            std::vector<std::string> tmp3 = _st->SplitString( tmp[1], "-" );
            if (tmp3.size()==1)
                lld.first = _st->StringToUInt4( tmp3[0] );
            else if (tmp3.size()==2){
                lld.first = _st->StringToUInt4( tmp3[0] );
                lld.second = _st->StringToUInt4( tmp3[1] );
            }
        }else if (tmp.size()==3){
            lld.first = _st->StringToUInt4( tmp[1] );
            lld.second = _st->StringToUInt4( tmp[2] );
        }
        this->SetAllPsdParams( "LLD", lld.first );
        this->SetAllPsdParams( "HLD", lld.second );
    }
    return this->SetUseDetectorType( _detType );
    */

}
//////////////////////////////////////////////////////////
bool WiringInfoEditorNeunet::
SetInfoAsReader(){
    ClearReader();
    bool ret = WiringInfoEditorBase::SetInfoAsReader();
    if (ret){
    }else{
        return false;
    }

    PsdBinInfoList.resize( PsdParams.size(), NULL);

    for (UInt4 i=0; i<PsdBinInfo.size(); i++){
        UtsusemiPsdBinInfo* pbi = PsdBinInfo[i];
        if (pbi!=NULL){
            if (pbi->conts.empty()){ // means "ALL"
                for (UInt4 j=0; j<PsdParams.size(); j++){
                    if (PsdParams[j]!=NULL){
                        PsdBinInfoList[j] = new std::vector<Double>(3,0.);
                        PsdBinInfoList[j]->at(0) = pbi->numPixel;
                        PsdBinInfoList[j]->at(1) = pbi->deltaX;
                        PsdBinInfoList[j]->at(2) = pbi->offsetX;
                    }
                }
            }else{ // means psd's range like "aa-bb"
                for (UInt4 j=0;j<(pbi->conts.size());j++){
                    std::pair<Int4,Int4> prange = pbi->conts[j];
                    for (Int4 k=prange.first; k<(prange.second+1); k++){
                        if (k<PsdBinInfoList.size()){
                            if (PsdBinInfoList[k]==NULL) PsdBinInfoList[k] = new std::vector<Double>(3,0.);
                            PsdBinInfoList[k]->at(0) = pbi->numPixel;
                            PsdBinInfoList[k]->at(1) = pbi->deltaX;
                            PsdBinInfoList[k]->at(2) = pbi->offsetX;
                        }
                    }
                }
            }
        }
    }

    if (PsdParamsList==NULL) PsdParamsList = new std::vector< std::vector<Double>* >( PsdParams.size(), NULL );
    for (UInt4 i=0; i<PsdParams.size(); i++){
        if (PsdParams[i]!=NULL){
            PsdParamsList->at(i) = new std::vector<Double>( 5, 0.0 );
            PsdParamsList->at(i)->at(0) = PsdParams[i]->valA;
            PsdParamsList->at(i)->at(1) = PsdParams[i]->valB;
            PsdParamsList->at(i)->at(2) = PsdParams[i]->valC;
            PsdParamsList->at(i)->at(3) = PsdParams[i]->lowerPH;
            PsdParamsList->at(i)->at(4) = PsdParams[i]->upperPH;
        }
    }

    return true;
}
