#include "UtsusemiD4Matrix2.hh"
//////////////////////////////////////////////////////////////////////
D4MatOne::D4MatOne(){
    _Initialize();
}
D4MatOne::D4MatOne(const D4MatOne &p){
    _Initialize();
    _HH = new HeaderBase( *(p._HH) );
    NumOfPixels = p.NumOfPixels;
    Energy->resize(p.Energy->size());
    Intensity->resize(p.Intensity->size());
    Error->resize(p.Error->size());
    Vx->resize(p.Vx->size());
    Vy->resize(p.Vy->size());
    Vz->resize(p.Vz->size());
    Vw->resize(p.Vw->size());
    PolarAngles->resize(p.PolarAngles->size());
    PolarAnglesW->resize(p.PolarAnglesW->size());
    AzimAngles->resize(p.AzimAngles->size());
    AzimAnglesW->resize(p.AzimAnglesW->size());
    L2->resize(p.L2->size());
    EFs->resize(p.EFs->size());
    copy( p.Energy->begin(), p.Energy->end(), Energy->begin() );
    copy( p.Intensity->begin(), p.Intensity->end(), Intensity->begin() );
    copy( p.Error->begin(), p.Error->end(), Error->begin() );
    copy( p.Vx->begin(), p.Vx->end(), Vx->begin() );
    copy( p.Vy->begin(), p.Vy->end(), Vy->begin() );
    copy( p.Vz->begin(), p.Vz->end(), Vz->begin() );
    copy( p.Vw->begin(), p.Vw->end(), Vw->begin() );
    copy( p.PolarAngles->begin(), p.PolarAngles->end(), PolarAngles->begin() );
    copy( p.PolarAnglesW->begin(), p.PolarAnglesW->end(), PolarAnglesW->begin() );
    copy( p.AzimAngles->begin(), p.AzimAngles->end(), AzimAngles->begin() );
    copy( p.AzimAnglesW->begin(), p.AzimAnglesW->end(), AzimAnglesW->begin() );
    copy( p.L2->begin(), p.L2->end(), L2->begin() );
    copy( p.EFs->begin(), p.EFs->end(), EFs->begin() );
}
const std::string D4MatOne::D4MAT2LABEL = "D4mat2Label";
const std::string D4MatOne::D4MAT2NUMOFPIXELS = "D4mat2NumOfPixels";
const std::string D4MatOne::D4MAT2ANGLE = "D4mat2Ang";
D4MatOne::~D4MatOne(){
    delete _HH;
    delete Energy;
    delete Intensity;
    delete Error;
    delete Vx;
    delete Vy;
    delete Vz;
    delete Vw;
    delete PolarAngles;
    delete PolarAnglesW;
    delete AzimAngles;
    delete AzimAnglesW;
    delete L2;
    delete EFs;
    if (_compbuf1 != NULL) delete [] _compbuf1;
}
void D4MatOne::_Initialize(){
    _HH = new HeaderBase();
    NumOfPixels =0;
    Energy = new std::vector<float>;
    Intensity = new std::vector<float>;
    Error  = new std::vector<float>;
    Vx = new std::vector<float>;
    Vy = new std::vector<float>;
    Vz = new std::vector<float>;
    Vw = new std::vector<float>;
    PolarAngles = new std::vector<float>;
    PolarAnglesW = new std::vector<float>;
    AzimAngles = new std::vector<float>;
    AzimAnglesW = new std::vector<float>;
    L2 = new std::vector<float>;
    EFs = new std::vector<float>;
    _compbuf1 = NULL;
}
void D4MatOne::_Allocate( UInt4 bins_size){
    Energy->clear();
    Intensity->clear();
    Error->clear();
    PolarAngles->clear();
    PolarAnglesW->clear();
    AzimAngles->clear();
    AzimAnglesW->clear();
    L2->clear();
    EFs->clear();
    if (bins_size > 0){
        Energy->resize(bins_size,0.0);
        Intensity->resize(bins_size,0.0);
        Error->resize(bins_size,0.0);
    }
    if (NumOfPixels > 0 ){
        PolarAngles->resize(NumOfPixels,0.0);
        PolarAnglesW->resize(NumOfPixels,0.0);
        AzimAngles->resize(NumOfPixels,0.0);
        AzimAnglesW->resize(NumOfPixels,0.0);
        L2->resize(NumOfPixels,0.0);
        EFs->resize(NumOfPixels,0.0);
    }
}
bool D4MatOne::_compress1(UInt4 bins_size){
    UInt4 all_size = bins_size*3 + NumOfPixels*6;
    std::vector<float> buf(all_size,0.0);
    copy(Energy->begin(), Energy->end(), buf.begin());
    copy(Intensity->begin(), Intensity->end(), buf.begin()+bins_size*1);
    copy(Error->begin(), Error->end(), buf.begin()+bins_size*2);
    copy(PolarAngles->begin(), PolarAngles->end(), buf.begin()+bins_size*3+NumOfPixels*0);
    copy(PolarAnglesW->begin(), PolarAnglesW->end(), buf.begin()+bins_size*3+NumOfPixels*1);
    copy(AzimAngles->begin(), AzimAngles->end(), buf.begin()+bins_size*3+NumOfPixels*2);
    copy(AzimAnglesW->begin(), AzimAnglesW->end(), buf.begin()+bins_size*3+NumOfPixels*3);
    copy(L2->begin(), L2->end(), buf.begin()+bins_size*3+NumOfPixels*4);
    if (EFs->empty())
        EFs->resize( NumOfPixels, 0.0 );
    copy(EFs->begin(), EFs->end(), buf.begin()+bins_size*3+NumOfPixels*5);
    //_Allocate(0);
    // Do compress
    all_size *= sizeof(float);
    _compbuf1_size = (unsigned long)(all_size * 1.001 + 12);
    if (_compbuf1 != NULL) delete [] _compbuf1;
    _compbuf1 = new unsigned char[_compbuf1_size];
    UInt4 ret = compress(_compbuf1, &_compbuf1_size, (unsigned char *)buf.data(), all_size);
    if (ret != Z_OK){
        std::string msg = "ERROR on compress : ";
        if (ret == Z_STREAM_ERROR) msg += "STREAM_ERROR";
        if (ret == Z_BUF_ERROR) msg += "BUF_ERROR";
        if (ret == Z_NEED_DICT) msg += "NEED_DICT";
        if (ret == Z_DATA_ERROR) msg += "DATA_ERROR";
        if (ret == Z_MEM_ERROR) msg += "MEM_ERROR";
        if (ret == Z_VERSION_ERROR) msg += "VERSION_ERROR";
        UtsusemiError(msg);
        //UtsusemiError("Failes compress");
        return false;
    }
    return true;
}
bool D4MatOne::_uncompress1(UInt4 bins_size){
    long unsigned int all_size = bins_size*3 + NumOfPixels*6;
    std::vector<float> buf(all_size,0.0);
    all_size *=sizeof(float);
    if (_compbuf1 == NULL) return false;
    UInt4 ret = uncompress((unsigned char *)buf.data(), &all_size, _compbuf1, _compbuf1_size );
    if (ret != Z_OK){
        std::string msg = "ERROR on uncompress : ";
        if (ret == Z_STREAM_ERROR) msg += "STREAM_ERROR";
        if (ret == Z_BUF_ERROR) msg += "BUF_ERROR";
        if (ret == Z_NEED_DICT) msg += "NEED_DICT";
        if (ret == Z_DATA_ERROR) msg += "DATA_ERROR";
        if (ret == Z_MEM_ERROR) msg += "MEM_ERROR";
        if (ret == Z_VERSION_ERROR) msg += "VERSION_ERROR";
        UtsusemiError(msg);
        //std::cout << "ERROR on uncompress" << std::endl;
        return false;
    }else{
        _Allocate( bins_size );
        // Energy, Intensity, Error data
        copy(buf.begin()+bins_size*0, buf.begin()+bins_size*1, Energy->begin());
        copy(buf.begin()+bins_size*1, buf.begin()+bins_size*2, Intensity->begin());
        copy(buf.begin()+bins_size*2, buf.begin()+bins_size*3, Error->begin());
        UInt4 bsize = bins_size*3;
        // Areadngles and L2
        copy(buf.begin()+bsize+NumOfPixels*0, buf.begin()+bsize+NumOfPixels*1, PolarAngles->begin());
        copy(buf.begin()+bsize+NumOfPixels*1, buf.begin()+bsize+NumOfPixels*2, PolarAnglesW->begin());
        copy(buf.begin()+bsize+NumOfPixels*2, buf.begin()+bsize+NumOfPixels*3, AzimAngles->begin());
        copy(buf.begin()+bsize+NumOfPixels*3, buf.begin()+bsize+NumOfPixels*4, AzimAnglesW->begin());
        copy(buf.begin()+bsize+NumOfPixels*4, buf.begin()+bsize+NumOfPixels*5, L2->begin());
        copy(buf.begin()+bsize+NumOfPixels*5, buf.end(), EFs->begin());
    }
    //delete [] _compbuf1;
    return true;
}
bool D4MatOne::Save(std::string filepath){
    std::ofstream ofs(filepath,std::ios::binary|std::ios::out|std::ios::trunc);
    if (!ofs) return false;
    Save( ofs );
    ofs.close();
    return true;
}
bool D4MatOne::Save(std::ofstream &ofs){
    UInt4 version = 1;
    // Data Format version
    ofs.write( (char*)&version,sizeof(UInt4) );

    // Save Header Dump (size and contents)
    std::string hh = _HH->DumpToString();
    UInt4 size_hh = (UInt4)(hh.size() + 1);
    ofs.write( (char*)&size_hh,sizeof(UInt4) );
    ofs.write( hh.c_str(), size_hh );

    // Save NumOfPixel and Energy bin
    UInt4 bins_size = (UInt4)(Energy->size());
    ofs.write( (char*)&NumOfPixels, sizeof(UInt4) );
    ofs.write( (char*)&bins_size, sizeof(UInt4) );
    // Save Energy, Intensity, Error data
    ofs.write((char*)Energy->data(), bins_size*sizeof(float));
    ofs.write((char*)Intensity->data(), bins_size*sizeof(float));
    ofs.write((char*)Error->data(), bins_size*sizeof(float));
    // Save Angles and L2
    ofs.write((char*)PolarAngles->data(), NumOfPixels*sizeof(float));
    ofs.write((char*)PolarAnglesW->data(), NumOfPixels*sizeof(float));
    ofs.write((char*)AzimAngles->data(), NumOfPixels*sizeof(float));
    ofs.write((char*)AzimAnglesW->data(), NumOfPixels*sizeof(float));
    ofs.write((char*)L2->data(), NumOfPixels*sizeof(float));
    if (EFs->empty())
        EFs->resize( NumOfPixels, 0.0 );
    ofs.write((char*)EFs->data(), NumOfPixels*sizeof(float));
    return true;
}
bool D4MatOne::Savez(std::ofstream &ofs){
    UInt4 version = 2;
    // Data Format version
    ofs.write( (char*)&version,sizeof(UInt4) );

    // Save Header Dump (size and contents)
    std::string hh = _HH->DumpToString();
    UInt4 size_hh = (UInt4)(hh.size() + 1);
    ofs.write( (char*)&size_hh,sizeof(UInt4) );
    ofs.write( hh.c_str(), size_hh );

    // Save NumOfPixel and Energy bin
    UInt4 bins_size = (UInt4)(Energy->size());
    ofs.write( (char*)&NumOfPixels, sizeof(UInt4) );
    ofs.write( (char*)&bins_size, sizeof(UInt4) );
    // Make stream
    if (_compress1(bins_size)){
        ofs.write( (char*)&_compbuf1_size, UTSUSEMID4MATRIX2_CMP_COMFBUFSIZE );
        ofs.write( (char*)_compbuf1, _compbuf1_size*sizeof(unsigned char));
    }
    return true;
}
bool D4MatOne::Load(std::ifstream &ifs){
    // Format version
    UInt4 version = 0;
    ifs.read( (char*)&version, sizeof(UInt4) );
    if ((version==1)||(version==2)){
        UInt4 _size = 0;
        // Header Dump
        ifs.read( (char*)&_size, sizeof(UInt4) );
        char* bufs = new char[_size];
        ifs.read( bufs, _size );
        std::string hh(bufs);
        _HH->InputString( hh );
        delete [] bufs;
        // NumOfPixel, bin_size
        ifs.read( (char*)&NumOfPixels, sizeof(UInt4) );
        UInt4 bins_size = 0;
        ifs.read( (char*)&bins_size, sizeof(UInt4) );
        if (version==1){
            _Allocate( bins_size );
            // Energy, Intensity, Error data
            ifs.read( (char*)Energy->data(), bins_size*sizeof(float));
            ifs.read( (char*)Intensity->data(), bins_size*sizeof(float));
            ifs.read( (char*)Error->data(), bins_size*sizeof(float));
            // Areadngles and L2
            ifs.read( (char*)PolarAngles->data(), NumOfPixels*sizeof(float));
            ifs.read( (char*)PolarAnglesW->data(), NumOfPixels*sizeof(float));
            ifs.read( (char*)AzimAngles->data(), NumOfPixels*sizeof(float));
            ifs.read( (char*)AzimAnglesW->data(), NumOfPixels*sizeof(float));
            ifs.read( (char*)L2->data(), NumOfPixels*sizeof(float));
            ifs.read( (char*)EFs->data(), NumOfPixels*sizeof(float));
        }else if (version==2){
            _compbuf1_size = 0;
            ifs.read( (char*)&_compbuf1_size, UTSUSEMID4MATRIX2_CMP_COMFBUFSIZE );
            if (_compbuf1 != NULL) delete [] _compbuf1;
            _compbuf1 = new unsigned char[_compbuf1_size];
            ifs.read( (char*)_compbuf1, _compbuf1_size*sizeof(unsigned char) );
            if (_uncompress1(bins_size)){
                delete [] _compbuf1;
                _compbuf1 = NULL;
            }else{
                delete [] _compbuf1;
                _compbuf1 = NULL;
                return false;
            }
        }else{
            std::cout << "version is not 1 and 2" <<std::endl;
            return false;
        }
        return true;
    }else{
        UtsusemiError("Failed to load binary data (version invalid)");
        return false;
    }
}
bool D4MatOne::DumpSqeAsText(std::string filepath){
    FILE* fp;
    if ((fp=fopen(filepath.c_str(),"a"))==NULL){
        UtsusemiError("ERROR to open the given file path : "+filepath);
        return false;
    }
    bool ret = DumpSqeAsText(fp);
    fclose(fp);
    return ret;
}
bool D4MatOne::DumpSqeAsText(FILE* fp){
    UInt4 size_v = (UInt4)(Vx->size());
    UInt4 size_i = (UInt4)(Intensity->size());
    if (size_i != size_v){
        UtsusemiError("ERROR : Projection calculation does not done.");
        return false;
    }
    char line_c[200];
    for (UInt4 i=0; i<size_i; i++){
        std::snprintf( line_c, sizeof(line_c), "%g, %g, %g, %g, %g, %g", Vx->at(i), Vy->at(i), Vz->at(i), Energy->at(i), Intensity->at(i), Error->at(i));
        std::string a_line(line_c);
       std::fprintf( fp, "%s\n", a_line.c_str() );
    }
    return true;
}
D4MatGroup::D4MatGroup(){
    _HH = new HeaderBase();
    _initialize();
}
D4MatGroup::D4MatGroup(HeaderBase *hh){
    _HH = new HeaderBase(*hh);
    _initialize();
}
D4MatGroup::~D4MatGroup(){
    delete _HH;
    for (UInt4 i=0; i<(data->size()); i++)
        if (data->at(i)!=NULL) delete data->at(i);
    delete data;
}
void D4MatGroup::_initialize(){
    data = new std::vector< D4MatOne* >;
    data->clear();
    _XtalParam="";
    // Date
    time_t timer;
    time(&timer);
    struct tm *t_st = localtime( &timer );
    std::ios::fmtflags current_flag = std::cout.flags();
    std::ostringstream ss;
    ss << std::setw(4) << std::setfill('0') << (UInt4)(t_st->tm_year+1900);
    ss << "/";
    ss << std::setw(2) << std::setfill('0') << (UInt4)(t_st->tm_mon+1);
    ss << "/";
    ss << std::setw(2) << std::setfill('0') << (UInt4)(t_st->tm_mday);
    ss << " ";
    ss << std::setw(2) << std::setfill('0') << (UInt4)(t_st->tm_hour);
    ss << ":";
    ss << std::setw(2) << std::setfill('0') << (UInt4)(t_st->tm_min);
    ss << ":";
    ss << std::setw(2) << std::setfill('0') << (UInt4)(t_st->tm_sec);
    std::string sdate( ss.str() );
    std::cout.flags(current_flag);
    _savedDate = sdate;
}
const UInt4 D4MatGroup::D4MAT2BINARYVERSION = 1;
const std::string D4MatGroup::D4MAT2BINARYSIGNATURE = "D4MATBINARYINAMURA";
const UInt4 D4MatGroup::D4MAT2BINARYSIGNATURESIZE = 19;
const UInt4 D4MatGroup::D4MAT2BINARYDATESIZE = 20;
bool D4MatGroup::Save(std::string filepath, bool withComp){
    std::string hh = _HH->DumpToString();
    UInt4 data_size = (UInt4)(data->size());
    UInt4 version = D4MAT2BINARYVERSION;
    std::ofstream ofs(filepath,std::ios::binary|std::ios::out|std::ios::trunc);
    if (!ofs) return false;
    // Data signature
    ofs.write( D4MAT2BINARYSIGNATURE.c_str(), D4MAT2BINARYSIGNATURESIZE );
    // Data Format version
    ofs.write( (char*)&version,sizeof(UInt4) );
    // Date
    time_t timer;
    time(&timer);
    struct tm *t_st = localtime( &timer );
    //char cdate[20];
    //std::snprintf( cdate, sizeof(snprintf), "%4d%02d%02d",
    //         (UInt4)(t_st->tm_year+1900),
    //         (UInt4)(t_st->tm_mon+1),
    //         (UInt4)(t_st->tm_mday)
    //    );
    //std::string sdate(cdate);
    std::ios::fmtflags current_flag = std::cout.flags();
    std::ostringstream ss;
    ss << std::setw(4) << std::setfill('0') << (UInt4)(t_st->tm_year+1900);
    ss << "/";
    ss << std::setw(2) << std::setfill('0') << (UInt4)(t_st->tm_mon+1);
    ss << "/";
    ss << std::setw(2) << std::setfill('0') << (UInt4)(t_st->tm_mday);
    ss << " ";
    ss << std::setw(2) << std::setfill('0') << (UInt4)(t_st->tm_hour);
    ss << ":";
    ss << std::setw(2) << std::setfill('0') << (UInt4)(t_st->tm_min);
    ss << ":";
    ss << std::setw(2) << std::setfill('0') << (UInt4)(t_st->tm_sec);
    std::string sdate( ss.str() );
    std::cout.flags(current_flag);
    _savedDate = sdate;
    ofs.write( sdate.c_str(), D4MAT2BINARYDATESIZE );
    // Save XtalParam
    UInt4 size_xp = (UInt4)(_XtalParam.size() + 1);
    ofs.write( (char*)&size_xp,sizeof(UInt4) );
    ofs.write( _XtalParam.c_str(), size_xp );
    UInt4 size_hh = (UInt4)(hh.size() + 1);
    // Save Header Dump (size and contents)
    ofs.write( (char*)&size_hh,sizeof(UInt4) );
    ofs.write( hh.c_str(), size_hh );
    // Save Size of Data
    ofs.write( (char*)&data_size,sizeof(UInt4) );
    // Save each D4MatOne contents
    if (withComp){
        for (UInt4 i=0; i<data_size; i++) data->at(i)->Savez( ofs );
    }else{
        for (UInt4 i=0; i<data_size; i++) data->at(i)->Save( ofs );
    }
    ofs.close();
    return true;
}
bool D4MatGroup::Load(std::string filepath){
    // Delete D4MatOne data
    for (UInt4 i=0; i<(data->size()); i++)
        if (data->at(i)!=NULL) delete data->at(i);

    // Open File
    std::ifstream ifs(filepath,std::ios::binary);
    if (!ifs) return false;
    // Data signature
    char* bufs_sig = new Char[D4MAT2BINARYSIGNATURESIZE];
    ifs.read( bufs_sig, D4MAT2BINARYSIGNATURESIZE );
    std::string signature(bufs_sig);
    delete [] bufs_sig;
    if (signature!=D4MAT2BINARYSIGNATURE){
        UtsusemiError("This is not D4Mat2 Binary Data");
        return false;
    }
    // Read Data Format version
    UInt4 version=0;
    ifs.read( (char*)&version, sizeof(UInt4) );
    if (version==1){
        // Date
        char* bufs_t = new char[D4MAT2BINARYDATESIZE];
        ifs.read( bufs_t, D4MAT2BINARYDATESIZE );
        std::string saved_date(bufs_t);
        UtsusemiMessage("This data was saved at "+saved_date);
        _savedDate = saved_date;
        delete [] bufs_t;

        UInt4 _size = 0;
        // XtalParams
        ifs.read( (char*)&_size, sizeof(UInt4) );
        char* bufsx = new char[_size];
        ifs.read( bufsx, _size );
        std::string xtalparam(bufsx);
        _XtalParam = xtalparam;
        delete [] bufsx;
        // Header Dump
        ifs.read( (char*)&_size, sizeof(UInt4) );
        char* bufs = new char[_size];
        ifs.read( bufs, _size );
        std::string hh(bufs);
        _HH->InputString( hh );
        delete [] bufs;
        // Size of data
        ifs.read( (char*)&_size, sizeof(UInt4) );
        StringTools stt;
        bool isSucceeded = true;
        for(UInt4 i=0; i<_size; i++){
            std::string msg = "Loading " + stt.UInt4ToString(i+1) + "/" + stt.UInt4ToString(_size);
            UtsusemiMessage(msg);
            D4MatOne* d = new D4MatOne();
            if (d->Load(ifs)) data->push_back(d);
            else{
                UtsusemiError("Failed to load data : file may be broken.", true);
                isSucceeded = false;
                break;
            }
        }
        ifs.close();
        return isSucceeded;
    }else{
        UtsusemiError("ERROR to load binary data (the data file is invalid or broken)", true);
        return false;
    }
}
bool D4MatGroup::DumpSqeAsText(std::string filepath){
    FILE* fp;
    if ((fp=fopen(filepath.c_str(),"w"))==NULL){
        UtsusemiError("ERROR to open the given file path : "+filepath);
        return false;
    }
    UInt4 size_v = (UInt4)(data->at(0)->Vx->size());
    UInt4 size_i = (UInt4)(data->at(0)->Intensity->size());
    if (size_i != size_v){
        UtsusemiError("ERROR : Projection calculation does not done.");
        return false;
    }
    UInt4 size_data = (UInt4)(data->size());
    for (UInt4 i=0; i<size_data; i++){
        if (data->at(i)->DumpSqeAsText(fp)){
        }else{
            UtsusemiError("ERROR : Failed to dump");
            fclose(fp);
            return false;
        }
    }
    fclose(fp);
    return true;
}
//////////////////////////////////////////////////////////////////////
TreatD4Matrix2XmlParams::TreatD4Matrix2XmlParams(){
    _initialize();
    _BP = new BoostXmlParser();
}
//////////////////////////////////////////////////////////////////////
TreatD4Matrix2XmlParams::TreatD4Matrix2XmlParams(std::string xmlstring){
    _initialize();
    _BP = new BoostXmlParser();
    if (ImportXmlString( xmlstring )){
    }else{
        UtsusemiError("TreatD4Matrxi2XmlParams : ImportXmlString error");
    }
}
//////////////////////////////////////////////////////////////////////
TreatD4Matrix2XmlParams::~TreatD4Matrix2XmlParams(){
    delete _BP;
}
//////////////////////////////////////////////////////////////////////
void TreatD4Matrix2XmlParams::_initialize(){
    mode = 0;
    runNoAngleList.clear();
    ei = 0.0;
    energyBin = 0.0;
    energyMin = 0.0;
    energyMax = 0.0;
    maskFile = "default";
    normFactor = 1e6;
    timeIndepBack = "TOF:None";
    detEffi = "";
    angleMin = 0.0;
    angleMax = 0.0;
    angleStep = 0.0;
    timeSlice0 = 0.0;
    timeSlice1 = 0.0;
    anglePerEncode = 0.0;
    deviceEncode = "";
    deviceEncodeDic.Clear();
    deviceEncodeDic.Add("BL01-TL", -0.002866242038);
    deviceEncodeDic.Add("BL14-TL", 0.00366);
    dio = 1;
    SBS_gonioAtZero = 0.0;
    dataReductions[KEY_DRC_F] = "";

    std::string inst_code = UtsusemiEnvGetInstCode();
    if (inst_code == "SIK"){
        deviceEncode = "BL01-TL";
        anglePerEncode = deviceEncodeDic.Put(deviceEncode);
    }else if (inst_code == "AMR"){
        deviceEncode = "BL14-TL";
        anglePerEncode = deviceEncodeDic.Put(deviceEncode);
    }
}
//////////////////////////////////////////////////////////////////////
void TreatD4Matrix2XmlParams::AddRunNo( UInt4 _runNo, Double _startAngle){
    std::pair<UInt4,Double> tmp;
    tmp.first = _runNo;
    tmp.second = _startAngle;
    runNoAngleList.push_back(tmp);
}

const std::string TreatD4Matrix2XmlParams::KEY_ROOT = "/visualContParams";
const std::string TreatD4Matrix2XmlParams::KEY_D4MAT2 = "d4mat2slicer";
const std::string TreatD4Matrix2XmlParams::KEY_PARAMS = "/visualContParams/d4mat2slicer/params";
const std::string TreatD4Matrix2XmlParams::KEY_MODE = "mode";
const std::string TreatD4Matrix2XmlParams::KEY_RUNNO = "runNo";
const std::string TreatD4Matrix2XmlParams::KEY_EI = "ei";
const std::string TreatD4Matrix2XmlParams::KEY_EBIN = "energyBin";
const std::string TreatD4Matrix2XmlParams::KEY_EMIN = "energyMin";
const std::string TreatD4Matrix2XmlParams::KEY_EMAX = "energyMax";
const std::string TreatD4Matrix2XmlParams::KEY_MASK = "maskFile";
const std::string TreatD4Matrix2XmlParams::KEY_NORMFACT = "normFactor";
const std::string TreatD4Matrix2XmlParams::KEY_TIMEBACK = "timeIndepBack";
const std::string TreatD4Matrix2XmlParams::KEY_DETEFFI = "detectorEffiInfo";
const std::string TreatD4Matrix2XmlParams::KEY_ANGS = "angleStart";
const std::string TreatD4Matrix2XmlParams::KEY_ANGMIN = "angleMin";
const std::string TreatD4Matrix2XmlParams::KEY_ANGMAX = "angleMax";
const std::string TreatD4Matrix2XmlParams::KEY_ANGT = "angleStep";
const std::string TreatD4Matrix2XmlParams::KEY_TSLS = "timeSlice";
const std::string TreatD4Matrix2XmlParams::KEY_DEVICEENCODE = "deviceEncode";
const std::string TreatD4Matrix2XmlParams::KEY_ANGPERENCODE = "anglePerEncode";
const std::string TreatD4Matrix2XmlParams::KEY_DIO = "trignetDio";
const std::string TreatD4Matrix2XmlParams::KEY_DRC = "dataReductions";
const std::string TreatD4Matrix2XmlParams::KEY_DRC_F = "file";
const std::string TreatD4Matrix2XmlParams::KEY_SBS_GONIO = "SBSgonioAtZero";
const std::string TreatD4Matrix2XmlParams::KEY_RUNLIST = "runList";
const std::string TreatD4Matrix2XmlParams::KEY_RUNLIST_NUM = "num";
const std::string TreatD4Matrix2XmlParams::KEY_RUNLIST_RUN = "run";

//////////////////////////////////////////////////////////////////////
bool TreatD4Matrix2XmlParams::ImportXmlString(std::string xmlstring, bool withDR){
    StringTools ST;
    if (_BP->LoadFromString( xmlstring )){
    }else{
        UtsusemiError("TreatD4Matrxi2XmlParams : ImportXmlString > LoadFromString error");
        return false;
    }
    if (withDR){
        std::vector<UInt4> runList;
        std::vector<Double> startAngleList;

        std::string path = KEY_PARAMS + "/" + KEY_EI;
        if (_BP->hasPath(path)) ei = ST.StringToDouble(_BP->PutContent(path));
        path = KEY_PARAMS + "/" + KEY_EBIN;
        if (_BP->hasPath(path)) energyBin = ST.StringToDouble(_BP->PutContent(path));
        path = KEY_PARAMS + "/" + KEY_EMIN;
        if (_BP->hasPath(path)) energyMin = ST.StringToDouble(_BP->PutContent(path));
        path = KEY_PARAMS + "/" + KEY_EMAX;
        if (_BP->hasPath(path)) energyMax = ST.StringToDouble(_BP->PutContent(path));
        path = KEY_PARAMS + "/" + KEY_MASK;
        if (_BP->hasPath(path)) maskFile = _BP->PutContent(path);
        path = KEY_PARAMS + "/" + KEY_NORMFACT;
        if (_BP->hasPath(path)) normFactor = ST.StringToDouble(_BP->PutContent(path));
        path = KEY_PARAMS + "/" + KEY_TIMEBACK;
        if (_BP->hasPath(path)) timeIndepBack = _BP->PutContent(path);
        path = KEY_PARAMS + "/" + KEY_DETEFFI;
        if (_BP->hasPath(path)) detEffi = _BP->PutContent(path);
        path = KEY_PARAMS + "/" + KEY_DRC;
        if (_BP->hasPath(path)){
            std::string tmp = _BP->PutContent(path, KEY_DRC_F);
            if (tmp!="") dataReductions[KEY_DRC_F] = tmp;
        }

        path = KEY_ROOT+"/"+KEY_D4MAT2+"/"+KEY_MODE;
        if (_BP->hasPath(path))
            mode = ST.StringToUInt4(_BP->PutContent(path));
        if (mode==0){
            path = KEY_PARAMS + "/" + KEY_RUNNO;
            if (_BP->hasPath(path)){
                std::vector<std::string> tmp = ST.SplitString((_BP->PutContent(path)), ",");
                for (UInt4 i=0; i<tmp.size(); i++) runList.push_back(ST.StringToUInt4(tmp[i]));
            }
            path = KEY_PARAMS + "/" + KEY_ANGS;
            if (_BP->hasPath(path)){
                std::vector<std::string> tmp = ST.SplitString((_BP->PutContent(path)), ",");
                for (UInt4 i=0; i<tmp.size(); i++) startAngleList.push_back(ST.StringToUInt4(tmp[i]));
            }
            path = KEY_PARAMS + "/" + KEY_ANGMIN;
            if (_BP->hasPath(path)) angleMin = ST.StringToDouble(_BP->PutContent(path));
            path = KEY_PARAMS + "/" + KEY_ANGMAX;
            if (_BP->hasPath(path)) angleMax = ST.StringToDouble(_BP->PutContent(path));
            path = KEY_PARAMS + "/" + KEY_ANGT;
            if (_BP->hasPath(path)) angleStep = ST.StringToDouble(_BP->PutContent(path));
            path = KEY_PARAMS + "/" + KEY_TSLS;
            if (_BP->hasPath(path)){
                std::vector<std::string> tmp = ST.SplitString((_BP->PutContent(path)), ",");
                if (tmp.size()==2){
                    timeSlice0 = ST.StringToDouble(tmp[0]);
                    timeSlice1 = ST.StringToDouble(tmp[1]);
                }else{
                    timeSlice0 = -1;
                    timeSlice1 = -1;
                }
            }
            path = KEY_PARAMS + "/" + KEY_DEVICEENCODE;
            if (_BP->hasPath(path)) deviceEncode = _BP->PutContent(path);
            path = KEY_PARAMS + "/" + KEY_ANGPERENCODE;
            if (_BP->hasPath(path)) anglePerEncode = ST.StringToDouble(_BP->PutContent(path));
            if (deviceEncodeDic.Check(deviceEncode) == 1) anglePerEncode = deviceEncodeDic.Put(deviceEncode);
            path = KEY_PARAMS + "/" + KEY_DIO;
            if (_BP->hasPath(path)) dio = ST.StringToUInt4(_BP->PutContent(path));

            UInt4 lenRunNo = (UInt4)(runList.size());
            UInt4 lenAngle = (UInt4)(startAngleList.size());
            UInt4 length = 0;
            if (lenRunNo < lenAngle) length = lenRunNo;
            else length = lenAngle;
            runNoAngleList.clear();
            for (UInt4 i=0; i<length; i++){
                std::pair<UInt4,Double> tmp;
                tmp.first = runList[i];
                tmp.second = startAngleList[i];
                runNoAngleList.push_back(tmp);
            }
        }else if (mode==1){
            path = KEY_PARAMS + "/" + KEY_SBS_GONIO;
            if (_BP->hasPath(path)) SBS_gonioAtZero = ST.StringToDouble(_BP->PutContent(path));
            path = KEY_PARAMS + "/" + KEY_RUNLIST;
            if (_BP->hasPath(path)){
                RunList.Clear();
                std::string path2 = path + "/" + KEY_RUNLIST_NUM;
                // If Old version as "runList/runList/num"
                if (_BP->hasPath(path2)){
                }else{
                    if (_BP->hasPath(KEY_PARAMS + "/" + KEY_RUNLIST + "/" + KEY_RUNLIST + "/" + KEY_RUNLIST_NUM)){
                        path = KEY_PARAMS + "/" + KEY_RUNLIST + "/" + KEY_RUNLIST;
                        path2 = path + "/" + KEY_RUNLIST_NUM;
                    }
                }
                if (_BP->hasPath(path2)){
                    UInt4 num_runs = ST.StringToUInt4(_BP->PutContent(path2));
                    for (UInt4 i=0; i<num_runs; i++){
                        std::string path3 = path + "/" + KEY_RUNLIST_RUN + ",i=" + ST.UInt4ToString(i);
                        if (_BP->hasPath(path3)){
                            std::string tmp = _BP->PutContent(path3);
                            std::vector<std::string> tmp_v = ST.SplitString(tmp, ":");
                            if (tmp_v.size()==5){
                                char key_c[10];
                                std::snprintf(key_c, sizeof(key_c), "%08.3f", ST.StringToDouble(tmp_v[0]));
                                std::string key_s(key_c);
                                RunList[key_s] = tmp;
                            }
                        }
                    }
                }
            }
        }else{
            UtsusemiError("TreatD4Matrxi2XmlParams : ImportXmlString > read mode value is invalid.");
            return false;
        }
    }
    return true;
}
//////////////////////////////////////////////////////////////////////
std::string TreatD4Matrix2XmlParams::PutXmlString(){
    StringTools S;
    Clear(true);
    if (_BP->hasPath(KEY_ROOT)){
        _BP->AddElement(KEY_ROOT+"/"+KEY_D4MAT2+"/"+KEY_MODE, S.UInt4ToString(mode));

        _BP->AddElement(KEY_PARAMS+"/"+KEY_EI, S.DoubleToString(ei));
        _BP->AddElement(KEY_PARAMS+"/"+KEY_EBIN, S.DoubleToString(energyBin));
        _BP->AddElement(KEY_PARAMS+"/"+KEY_EMIN, S.DoubleToString(energyMin));
        _BP->AddElement(KEY_PARAMS+"/"+KEY_EMAX, S.DoubleToString(energyMax));
        _BP->AddElement(KEY_PARAMS+"/"+KEY_MASK, maskFile);
        _BP->AddElement(KEY_PARAMS+"/"+KEY_NORMFACT, S.DoubleToString(normFactor));
        _BP->AddElement(KEY_PARAMS+"/"+KEY_TIMEBACK, timeIndepBack);
        _BP->AddElement(KEY_PARAMS+"/"+KEY_DETEFFI, detEffi);

        if (mode == 0){
            std::string runNos = "";
            std::string angleList = "";
            if (runNoAngleList.empty()){
                UtsusemiWarning("PutXmlString >> List of runNos and Angles is empty.");
            }else{
                runNos = S.UInt4ToString(runNoAngleList[0].first);
                angleList = S.DoubleToString(runNoAngleList[0].second);
                for (UInt4 i=1; i<runNoAngleList.size(); i++){
                    runNos += ("," + S.UInt4ToString(runNoAngleList[i].first));
                    angleList += ("," + S.DoubleToString(runNoAngleList[i].second));
                }
            }
            _BP->AddElement(KEY_PARAMS+"/"+KEY_RUNNO, runNos);
            _BP->AddElement(KEY_PARAMS+"/"+KEY_ANGS, angleList);
            _BP->AddElement(KEY_PARAMS+"/"+KEY_ANGMIN, S.DoubleToString(angleMin));
            _BP->AddElement(KEY_PARAMS+"/"+KEY_ANGMAX, S.DoubleToString(angleMax));
            _BP->AddElement(KEY_PARAMS+"/"+KEY_ANGT, S.DoubleToString(angleStep));

            std::string c = S.DoubleToString(timeSlice0) + "," + S.DoubleToString(timeSlice1);
            _BP->AddElement(KEY_PARAMS+"/"+KEY_TSLS, c);
            _BP->AddElement(KEY_PARAMS+"/"+KEY_DEVICEENCODE, deviceEncode);
            _BP->AddElement(KEY_PARAMS+"/"+KEY_ANGPERENCODE, S.DoubleToString(anglePerEncode));
            _BP->AddElement(KEY_PARAMS+"/"+KEY_DIO, S.UInt4ToString(dio));
        }else if (mode == 1){
            _BP->AddElement(KEY_PARAMS+"/"+KEY_SBS_GONIO, S.DoubleToString(SBS_gonioAtZero));
            _BP->AddElement(KEY_PARAMS+"/"+KEY_RUNLIST+"/"+KEY_RUNLIST_NUM, S.UInt4ToString(RunList.Size()));
            for (UInt4 i=0; i<RunList.Size(); i++){
                char cc[20];
                std::snprintf(cc, sizeof(cc), ",i=%d", i);
                std::string ind(cc);
                std::string key = KEY_PARAMS+"/"+KEY_RUNLIST+"/"+KEY_RUNLIST_RUN+ind;
                _BP->AddElement(key, RunList.Put(i));
            }
        }else{
            UtsusemiError("TreatD4Matrix2XmlParams::PutXmlString() mode value is invalid.");
            return "";
        }

        std::vector<std::string> keys;
        std::vector<std::string> args;
        UInt4 m_size = dataReductions.Size();
        for (UInt4 i=0; i<m_size; i++) keys.push_back( dataReductions.PutKey(i) );
        for (UInt4 i=0; i<m_size; i++) args.push_back( dataReductions[keys[i]] );
        _BP->AddElement(KEY_PARAMS+"/"+KEY_DRC, keys, args);
    }
    return _BP->OutToString(true);
}
//////////////////////////////////////////////////////////////////////
void TreatD4Matrix2XmlParams::Clear(bool onlyD4Mat2){
    if (onlyD4Mat2){
        if (_BP->hasPath(KEY_ROOT+"/"+KEY_D4MAT2+"/"+KEY_MODE)){
            bool ret1 = _BP->RemoveElement(KEY_ROOT+"/"+KEY_D4MAT2+"/"+KEY_MODE, "");
            bool ret2 = _BP->RemoveElement(KEY_PARAMS, "");
            if ((ret1)&&(ret2)){
            }else{
                UtsusemiError("TreatD4Matrix2XmlParams::Clear() Failed.");
            }
        }else{
            //std::cout << _BP->OutToString(true) << std::endl;
        }
    }else{
        delete _BP;
        _BP = new BoostXmlParser();
    }
    return;
}


//////////////////////////////////////////////////////////////////////
UtsusemiD4Matrix2::
UtsusemiD4Matrix2(){
    _Initialize();
}
//////////////////////////////////////////////////////////////////////
UtsusemiD4Matrix2::
~UtsusemiD4Matrix2(){
    _Clear();
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4Matrix2::
_Initialize(){
    MessageTag = "UtsusemiD4Matrix2::";

    MASKVALUE = UTSUSEMIMASKVALUE64;
    _D4mat = new D4MatGroup();
    _HH = new HeaderBase();

    _NumOfMulTh = UtsusemiGetNumOfMulTh();
    _stools = new StringTools();
    isDirectGeometry = true;

    _XP = new UtsusemiSqeCalcXtalParams();
    _useAveOnSlice = true;

    _TP = new TreatD4Matrix2XmlParams();

    _vbinFileComponents.clear();
    dArray4 = NULL;
    eArray4 = NULL;
    cArray4 = NULL;
    _n_XArray4 = 0;
    _n_YArray4 = 0;
    _n_ZArray4 = 0;
    _n_TArray4 = 0;
    _viewAxis.clear();
    AxLimit.clear();
    isMemSaveMode = true;
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4Matrix2::
_Clear(){
    delete _D4mat;
    delete _HH;
    delete _stools;
    delete _XP;
    delete _TP;
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4Matrix2::
ResetD4mat(){

    _Clear();
    _D4mat = new D4MatGroup();
    _HH = new HeaderBase();
    _stools = new StringTools();
    _XP = new UtsusemiSqeCalcXtalParams();
    _TP = new TreatD4Matrix2XmlParams();
}

//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetCrystalParametersFromInnerHead( ElementContainerMatrix* ecm, Double phi ){
    HeaderBase* hh = ecm->PutHeaderPointer();
    if (_HH->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS)==1){
        if (hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS)==1)
            hh->OverWrite(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS,_HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS));
        else
            hh->Add(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS,_HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS));
    }else if (_HH->CheckKey("SimpleLatticeConsts")==1){
        if (hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS)==1)
            hh->OverWrite(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS,_HH->PutDoubleVector("SimpleLatticeConsts"));
        else
            hh->Add(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS,_HH->PutDoubleVector("SimpleLatticeConsts"));
    }else{
        UtsusemiError( MessageTag+"SetCrystalParametersFromInnerHead >> InnerHeader has no SampleLattciConsts." );
        return false;
    }
    if (_HH->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT)==1){
        if (hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT)==1)
            hh->OverWrite(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT,_HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT));
        else
            hh->Add(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT,_HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT));
    }else{
        UtsusemiError( MessageTag+"SetCrystalParametersFromInnerHead >> InnerHeader has no SampleUvect." );
        return false;
    }
    if (_HH->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT)==1){
        if (hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT)==1)
            hh->OverWrite(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT,_HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT));
        else
            hh->Add(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT,_HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT));
    }else{
        UtsusemiError( MessageTag+"SetCrystalParametersFromInnerHead >> InnerHeader has no SampleVvect." );
        return false;
    }
    if (_HH->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS)==1){
        std::vector<Double> RV = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS);
        if (phi!=0.0){
            RV.push_back(1.0);
            RV.push_back(phi);
        }
        if (hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS)==1)
            hh->OverWrite(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS, RV);
        else
            hh->Add(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS, RV);
    }else{
        UtsusemiError( MessageTag+"SetCrystalParametersFromInnerHead >> InnerHeader has no SampleRotateSteps." );
        return false;
    }
    return true;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
SetCrystalParametersToHeader( HeaderBase* head, std::vector<Double> LatticeConsts, std::vector<Double> Uvec, std::vector<Double> Vvec, std::vector<Double> Rvec ){
    if (head->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS)==1){
        head->OverWrite(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS,LatticeConsts);
    }else{
        head->Add(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS,LatticeConsts);
    }
    if (head->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT)==1){
        head->OverWrite(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT,Uvec);
    }else{
        head->Add(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT,Uvec);
    }
    if (head->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT)==1){
        head->OverWrite(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT,Vvec);
    }else{
        head->Add(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT,Vvec);
    }
    if (head->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS)==1){
        head->OverWrite(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS,Rvec);
    }else{
        head->Add(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS,Rvec);
    }

    return 0;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatSampleInfo( std::vector<Double> LatticeConsts, std::vector<Double> Uvec, std::vector<Double> Vvec, std::vector<Double> Rvec ){
    UInt4 ret = SetCrystalParametersToHeader( _HH, LatticeConsts, Uvec, Vvec, Rvec );
    if (ret==0) return true;
    else return false;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatSampleInfo(PyObject* LatticeConsts, PyObject* Uvec, PyObject* Vvec, PyObject* Rvec){
    if ((!PyList_Check(LatticeConsts))||(!PyList_Check(Uvec))||(!PyList_Check(Vvec))||(!PyList_Check(Rvec))){
        UtsusemiError( MessageTag + "SetD4MatSampleInfo >> arguments must be python-list" );
        return false;
    }
    std::vector<Double> lcv = __gCppToPython.ListToDoubleVector( LatticeConsts );
    if ((lcv.empty())||(lcv.size()!=6)){
        UtsusemiError( MessageTag + "SetD4MatSampleInfo >> Arguments LatticeConstants must be list with size of 6" );
        return false;
    }
    std::vector<Double> uvv = __gCppToPython.ListToDoubleVector( Uvec );
    if ((uvv.empty())||(uvv.size()!=3)){
        UtsusemiError( MessageTag + "SetD4MatSampleInfo >> Arguments Uvec must be list with size of 3" );
        return false;
    }
    std::vector<Double> vvv = __gCppToPython.ListToDoubleVector( Vvec );
    if ((vvv.empty())||(vvv.size()!=3)){
        UtsusemiError( MessageTag + "SetD4MatSampleInfo >> Arguments Vvec must be list with size of 3" );
        return false;
    }
    std::vector<Double> rvv = __gCppToPython.ListToDoubleVector( Rvec );

    return SetD4MatSampleInfo( lcv, uvv, vvv, rvv );
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::SetD4MatMode(UInt4 mode){
    if ((mode!=0)&&(mode!=1)) return false;
    if (_HH->CheckKey("D4MAT2MODE")==1)
        _HH->OverWrite("D4MAT2MODE",(Int4)mode);
    else
        _HH->Add("D4MAT2MODE",(Int4)mode);
    _TP->mode = mode;
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatDataReductionInfo( std::vector<Double> dataRedParam ){
    if (dataRedParam.size()!=9){
        UtsusemiError( MessageTag + " SetD4MatDataReductionInfo >> data reductio parameter is invalid." );
        return false;
    }

    if (_HH->CheckKey("DATAREDPARAM")==1)
        _HH->OverWrite("DATAREDPARAM",dataRedParam);
    else
        _HH->Add("DATAREDPARAM",dataRedParam);

    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatDataReductionInfo( PyObject* dataRedParam ){
    return SetD4MatDataReductionInfo( __gCppToPython.ListToDoubleVector( dataRedParam ) );
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatDataReductionOptions( std::string maskInfo, Double normFactor,  std::string timeIndepBack, std::string detEffi, std::string script){
    if (maskInfo != ""){
        if (_HH->CheckKey("D4MAT2MASKINFO")==1)
            _HH->OverWrite("D4MAT2MASKINFO", maskInfo);
        else
            _HH->Add("D4MAT2MASKINFO", maskInfo);
    }
    _TP->maskFile = maskInfo;

    if (_HH->CheckKey("D4MAT2NORMFACT")==1)
        _HH->OverWrite("D4MAT2NORMFACT", normFactor);
    else
        _HH->Add("D4MAT2NORMFACT", normFactor);
    _TP->normFactor = normFactor;

    if (timeIndepBack != ""){
        if (_HH->CheckKey("D4MAT2TIMEINDEPBK")==1)
            _HH->OverWrite("D4MAT2TIMEINDEPBK", timeIndepBack);
        else
            _HH->Add("D4MAT2TIMEINDEPBK", timeIndepBack);
    }
    _TP->timeIndepBack = timeIndepBack;

    if (detEffi != ""){
        if (_HH->CheckKey("D4MAT2DETEFFI")==1)
            _HH->OverWrite("D4MAT2DETEFFI", detEffi);
        else
            _HH->Add("D4MAT2DETEFFI", detEffi);
    }
    _TP->detEffi = detEffi;

    if (script != ""){
        if (_HH->CheckKey("D4MAT2DRSCRIPT")==1)
            _HH->OverWrite("D4MAT2DRSCRIPT", script);
        else
            _HH->Add("D4MAT2DRSCRIPT", script);
    }
    _TP->dataReductions[_TP->KEY_DRC_F] = script;

    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatDataReductionContinuosAddRunNo(UInt4 runNo, Double startAngle){
    _TP->AddRunNo( runNo, startAngle );
    return true;
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4Matrix2::
SetD4MatDataReductionContinuosClearRunNo(){
    _TP->ClearRunNo();
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatDataReductionContinuosSetDeviceEncode(std::string device){
    if (_TP->deviceEncodeDic.Check(device) == 1){
        _TP->deviceEncode = device;
        _TP->anglePerEncode = _TP->deviceEncodeDic.Put(device);
        return true;
    }else{
        UtsusemiError(MessageTag+"SetD4MatDataReductionContinuousSetDeviceEncode >> given device name "+device+" is invalid." );
        return false;
    }
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatDataReductionContinuosSetAnglePerEncode(Double ape){
    _TP->deviceEncode = "";
    _TP->anglePerEncode = ape;
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatDataReductionContinuosSetTrigNETDIO(UInt4 dio){
    _TP->dio = dio;
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatDataReductionStepByStepGonioAtZero(Double gaz){
    _TP->SBS_gonioAtZero = gaz;
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatProjectionAxesInfo( std::vector<Double> PA ){
    if (PA.size()!=16){
        UtsusemiError( MessageTag+"SetD4MatProjectionAxesInfo >> Projection Axes is invalid." );
        return false;
    }
    if (_HH->CheckKey("ProjectionAxes")==1)
        _HH->OverWrite("ProjectionAxes", PA);
    else
        _HH->Add("ProjectionAxes", PA);

    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatProjectionAxesInfo( PyObject* PA ){
    return SetD4MatProjectionAxesInfo( __gCppToPython.ListToDoubleVector( PA ) );
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatProjectionAxesInfo( std::vector<Double> PA, std::vector<std::string> titles, std::vector<std::string> units ){
    if (PA.size()!=16){
        UtsusemiError( MessageTag+"SetD4MatProjectionAxesInfo >> Projection Axes is invalid." );
        return false;
    }
    if (titles.size()!=4){
        UtsusemiError( MessageTag+"SetD4MatProjectionAxesInfo >> Projection Axes titles are invalid." );
        return false;
    }
    if (units.size()!=4){
        UtsusemiError( MessageTag+"SetD4MatProjectionAxesInfo >> Projection Axes titles are invalid." );
        return false;
    }
    if (_HH->CheckKey("ProjectionAxes")==1)
        _HH->OverWrite("ProjectionAxes", PA);
    else
        _HH->Add("ProjectionAxes", PA);

    for (UInt4 i=0; i<4; i++){
        std::string key = _stools->UInt4ToString(i);
        UInt4 ind = 4 * i;
        _XP->SetProjectionAxis(key, PA[ind + 0], PA[ind + 1], PA[ind + 2], PA[ind + 3], titles[i], units[i]);
    }
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatProjectionAxesInfo( PyObject* PA, PyObject* titles, PyObject* units  ){
    return SetD4MatProjectionAxesInfo(
        __gCppToPython.ListToDoubleVector( PA ),
        __gCppToPython.ListToStringVector( titles ),
        __gCppToPython.ListToStringVector( units ) );
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatSliceAxis(std::string _id, std::string _type, double _min, double _max, double _width, double _folding){
    return _XP->SetSliceAxis(_id, _type, _min, _max, _width, _folding);
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatRunNo( Int4 runNo ){
    if (_HH->CheckKey(UTSUSEMI_KEY_HEAD_RUNNUMBER)==1)
        _HH->OverWrite(UTSUSEMI_KEY_HEAD_RUNNUMBER,runNo);
    else
        _HH->Add(UTSUSEMI_KEY_HEAD_RUNNUMBER,runNo);
    return true;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
SetD4MatParameters( Int4 runNo, std::vector<Double> dataRedParam,std::vector<Double> LatticeConsts, std::vector<Double> Uvec, std::vector<Double> Vvec, std::vector<Double> Rvec){
    bool ret = SetD4MatRunNo( runNo );
    if ( SetD4MatDataReductionInfo( dataRedParam ) ){
    }else{
        UtsusemiError( MessageTag + " SetD4MatParameters >> data reductio parameter is invalid." );
        return -1;
    }

    if ( SetCrystalParametersToHeader( _HH, LatticeConsts, Uvec, Vvec, Rvec ) ){
    }else{
        return -2;
    }

    delete _D4mat->_HH;
    _D4mat->_HH = new HeaderBase( *_HH );

    return 0;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SetD4MatParameters( Int4 runNo, PyObject* dataRedParam, PyObject* LatticeConsts, PyObject* Uvec, PyObject* Vvec, PyObject* Rvec){
    if ( SetD4MatSampleInfo( LatticeConsts, Uvec, Vvec, Rvec ) ){
    }else return false;

    if ( SetD4MatDataReductionInfo( dataRedParam ) ){
    }else return false;

    if ( SetD4MatRunNo( runNo ) ){
    }else return false;

    delete _D4mat->_HH;
    _D4mat->_HH = new HeaderBase( *_HH );
    if (_D4mat->_XtalParam==""){
        _D4mat->_XtalParam = MakeXmlStringFromHeader( _HH );
    }
    return true;
}
//////////////////////////////////////////////////////////////////////
std::string UtsusemiD4Matrix2::
MakeXmlStringFromHeader(HeaderBase* hh){
    if (hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS)==1){
        std::vector<Double> LC = hh->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS);
        if (_XP->SetLatticeConstants(LC[0],LC[1],LC[2],LC[3],LC[4],LC[5])){
        }else{
            UtsusemiError("D4Matrix2::MakeXmlStringFromHeader >> Failed to set LatticeConstants");
            return "";
        }
    }else if (hh->CheckKey("SimpleLatticeConsts")==1){
        std::vector<Double> LC = hh->PutDoubleVector("SimpleLatticeConsts");
        if (_XP->SetLatticeConstants(LC[0],LC[1],LC[2],LC[3],LC[4],LC[5])){
        }else{
            UtsusemiError("D4Matrix2::MakeXmlStringFromHeader >> Failed to set LatticeConstants");
            return "";
        }
    }

    if ((hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT)==1)&&(hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT)==1)){
        std::vector<Double> UV = hh->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT);
        std::vector<Double> VV = hh->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT);
        if (_XP->SetUVvector(UV[0],UV[1],UV[2],VV[0],VV[1],VV[2])){
        }else{
            UtsusemiError("D4Matrix2::MakeXmlStringFromHeader >> Failed to set U-vec and V-vec");
            return "";
        }
    }
    if (hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS)==1){
        std::vector<Double> R = hh->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS);
        if (_XP->ClearRotationStep()){
            for (UInt4 i=0; i<R.size(); i+=2){
                std::string axis = "";
                if (R[i]==0) axis = "X";
                else if (R[i]==1) axis = "Y";
                else axis = "Z";
                if (_XP->AddRotationStep(axis, R[i+1])){
                }else{
                    UtsusemiError("D4Matrix2::MakeXmlStringFromHeader >> Failed to set Rotation Step");
                    return "";
                }
            }
        }
    }

    std::string xmlstring = _XP->PutXmlString();
    std::vector<Double> p = PutD4MatDataRedParams(false);
    for (UInt4 i =0; i<p.size(); i++) std::cout << p[i] << std::endl;
    if (p.size()!=9){
        UtsusemiWarning("D4Matrix2:: DATA reduction params is invalid.");
        return xmlstring;
    }

    _TP->ImportXmlString(xmlstring, false);
    if (hh->CheckKey("D4MAT2MODE")==1)
        _TP->mode = hh->PutInt4("D4MAT2MODE");
    _TP->timeSlice0 = p[0];
    _TP->timeSlice1 = p[1];
    _TP->ei = p[2];
    _TP->energyBin = p[3];
    _TP->energyMin = p[4];
    _TP->energyMax = p[5];
    _TP->angleMin = p[6];
    _TP->angleMax = p[7];
    _TP->angleStep = p[8];

    std::string ret = _TP->PutXmlString();
    return ret;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
PutD4MatRunNo(){
    HeaderBase* hh = _D4mat->PutHeaderPointer();
    if (hh->CheckKey(UTSUSEMI_KEY_HEAD_RUNNUMBER)==1)
        return hh->PutInt4(UTSUSEMI_KEY_HEAD_RUNNUMBER);
    else
        return -1;
}
//////////////////////////////////////////////////////////////////////
std::vector<Double> UtsusemiD4Matrix2::
PutD4MatDataRedParams(bool fromData){
    HeaderBase* hh = NULL;
    if (fromData) hh = _D4mat->PutHeaderPointer();
    else hh = _HH;
    if (hh->CheckKey("DATAREDPARAM")==1)
        return hh->PutDoubleVector("DATAREDPARAM");
    else{
        std::vector<Double> ret;
        return ret;
    }
}
//////////////////////////////////////////////////////////////////////
std::vector<Double> UtsusemiD4Matrix2::
PutD4MatLatticeConsts(){
    HeaderBase* hh = _D4mat->PutHeaderPointer();
    if (hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS)==1)
        return hh->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS);
    else{
        std::vector<Double> ret;
        return ret;
    }
}
//////////////////////////////////////////////////////////////////////
std::vector<Double> UtsusemiD4Matrix2::
PutD4MatUVvects(){
    HeaderBase* hh = _D4mat->PutHeaderPointer();
    std::vector<Double> ret;
    if ( (hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT)==1)&&(hh->CheckKey(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT)==1) ){
        std::vector<Double> retU = hh->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT);
        std::vector<Double> retV = hh->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT);
        for (UInt4 i=0; i<3; i++) ret.push_back( retU[i] );
        for (UInt4 i=0; i<3; i++) ret.push_back( retV[i] );
    }
    return ret;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
ImportEcmsContRot( UtsusemiEventDataConverterNeunet* EDC,
                   const std::vector<UInt4> CaseId, const std::vector<Double> Phi,const std::vector<Double> Kickers,
                   const std::string maskfile, const Double dOmega, const Double normFactor,const std::string detEffi,
                   const UInt4 reductCase ){

    UInt4 num_multh = UtsusemiGetNumOfMulTh();
    /*
    if (_HH->CheckKey("ProjectionAxes")==0){
        UtsusemiError( MessageTag+"ImportEcmsContRot >> ProjectionAxes is not set.");
        return -1;
    }
    std::vector<Double> VA = _HH->PutDoubleVector("ProjectionAxes");
    */
    delete _D4mat;
    _D4mat = new D4MatGroup(_HH);
    _D4mat->_XtalParam = MakeXmlStringFromHeader( _HH );
    _D4mat->data->resize( Phi.size(), NULL );

    UInt4 csize=(UInt4)(CaseId.size());

#ifdef MULTH
    omp_set_num_threads( num_multh );
#endif

#pragma omp parallel for
#if (_OPENMP >= 200805)  // OpenMP 3.0 and later
    for (UInt4 ind=0;ind<csize;ind++){
#else
    for (Int4 ind=0;ind<(Int4)csize;ind++){
#endif
        ElementContainerMatrix* ecm = new ElementContainerMatrix();
        //UInt4 p=omp_get_thread_num();
        //std::cout << "#"<<"("<< p <<")";

        UInt4 caseid=CaseId[ind];
        EDC->SetElementContainerMatrix( ecm, caseid );

        if ((caseid!=0)&&( caseid<Kickers.size()))
            ecm->PutHeaderPointer()->OverWrite( UTSUSEMI_KEY_HEAD_KICKERCOUNT, Kickers[caseid] );

        if (maskfile!=""){
            UtsusemiSetMask *MSK = new UtsusemiSetMask(ecm, maskfile);
            MSK->Execute();
            delete MSK;
        }
        //if (normFactor>0) ecm->MulMySelf(normFactor);
        //else if (normFactor<0) ecm->MulMySelf(1.0/abs(normFactor));
        UtsusemiDetectorEfficiencyCorrection* DEC = new UtsusemiDetectorEfficiencyCorrection();
        if (DEC->LoadDataFile(detEffi)) DEC->Execute(ecm);
        else UtsusemiWarning( MessageTag+"ImportEcmsContRot >> Detector Efficiency correction is not done.");
        delete DEC;

        UtsusemiReductionInEla* URI = new UtsusemiReductionInEla( ecm );
        URI->CalcPhi();
        if ((((reductCase)>>3)&0x1)==1) URI->dHWCorrect();       // 4th bit is 1
        if ((((reductCase)>>2)&0x1)==1) URI->NormBySolidAngle(); // 3rd bit is 1
        if ((((reductCase)>>1)&0x1)==1) URI->KiKfCorrect();      // 2nd bit is 1
        if (((reductCase)&0x1)==1)      URI->NormByKickers(normFactor);    // 1st bit is 1
        delete URI;

        //ImportEcmContRot( ecm, ind+1, Phi[ind], reductCase );
        std::string label = _stools->UInt4ToString( ind+1 );
        ImportEcmStepByStep( ecm, Phi[ind], label, false );
        delete ecm;
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
ImportEcmsContRot( UtsusemiEventDataConverterNeunet* EDC,
                   PyObject* CaseId, PyObject* Phi, PyObject* Kickers,
                   const std::string maskfile, const Double dOmega, const Double normFactor, const std::string detEffi,
                   const UInt4 reductCase  ){
    if ((!PyList_Check(CaseId))||(!PyList_Check(Phi))||(!PyList_Check(Kickers))){
        UtsusemiError( MessageTag + "ImportEcms >> arguments must be python-list" );
        return false;
    }
    std::vector<UInt4> civ = __gCppToPython.ListToUInt4Vector( CaseId );
    std::vector<Double> phv = __gCppToPython.ListToDoubleVector( Phi );
    std::vector<Double> kic = __gCppToPython.ListToDoubleVector( Kickers );
    Int4 ret = ImportEcmsContRot( EDC, civ, phv, kic, maskfile, dOmega, normFactor, detEffi );
    if (ret==0) return true;
    else return false;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
ImportEcmContRot( ElementContainerMatrix* ecm, const UInt4 caseId, const double phi, const UInt4 reductCase ){
    SetCrystalParametersFromInnerHead( ecm, phi );
    if ((((reductCase)>>3)&0x1)==1){
        UtsusemiReductionInEla* URI = new UtsusemiReductionInEla( ecm );
        URI->dHWCorrect();
        delete URI;
    }
    std::vector<Double> VA = _HH->PutDoubleVector("ProjectionAxes");
    UtsusemiSqeCalc2* vc = new UtsusemiSqeCalc2();
    vc->SetTarget( ecm );
    vc->Projection( VA );
    delete vc;

    std::vector<Double> tmp_vx;
    std::vector<Double> tmp_vy;
    std::vector<Double> tmp_vz;
    std::vector<Double> tmp_vw;
    std::vector<Double> tmp_ii;
    std::vector<Double> tmp_ee;
    tmp_vx.clear();
    tmp_vy.clear();
    tmp_vz.clear();
    tmp_vw.clear();
    tmp_ii.clear();
    tmp_ee.clear();

    UInt4 n_all = 0;
    UInt4 n_eca = ecm->PutSize();
    for (UInt4 i=0;i<n_eca;i++){
        UInt4 n_ec = ecm->PutPointer(i)->PutSize();
        for (UInt4 j=0;j<n_ec;j++){
            std::vector<Double>  v_ec = ecm->PutPointer(i)->PutPointer(j)->Put(UTSUSEMI_KEY_VIEWX);
            UInt4 n_ii = (UInt4)(v_ec.size());
            n_all += n_ii;
        }
    }
    tmp_vx.resize( n_all, 0.0 );
    tmp_vy.resize( n_all, 0.0 );
    tmp_vz.resize( n_all, 0.0 );
    tmp_vw.resize( n_all, 0.0 );
    tmp_ii.resize( n_all, 0.0 );
    tmp_ee.resize( n_all, 0.0 );

    UInt4 cnt = 0;
    for (UInt4 i=0;i<ecm->PutSize();i++){
        //std::cout << "i=" << i << std::endl;
        ElementContainerArray* eca=ecm->PutPointer(i);
        if (eca->PutHeaderPointer()->PutInt4(UTSUSEMI_KEY_HEAD_MASKED)==0){
            for (UInt4 j=0;j<eca->PutSize();j++){
                ElementContainer* ec = eca->PutPointer(j);
                if (ec->PutHeaderPointer()->PutInt4(UTSUSEMI_KEY_HEAD_MASKED)==0){
                    std::vector<Double>* vx = (*ec)(UTSUSEMI_KEY_VIEWX);
                    std::vector<Double>* vy = (*ec)(UTSUSEMI_KEY_VIEWY);
                    std::vector<Double>* vz = (*ec)(UTSUSEMI_KEY_VIEWZ);
                    std::vector<Double>* vw = (*ec)(UTSUSEMI_KEY_VIEWW);

                    std::vector<Double>* ii = (*ec)(UTSUSEMI_KEY_INTENSITY);
                    std::vector<Double>* ee = (*ec)(UTSUSEMI_KEY_ERROR);

                    for (UInt4 k=0;k<(ii->size());k++){
                        tmp_vx[cnt]=(vx->at(k));
                        tmp_vy[cnt]=(vy->at(k));
                        tmp_vz[cnt]=(vz->at(k));
                        tmp_vw[cnt]=(vw->at(k));
                        tmp_ii[cnt]=(ii->at(k));
                        tmp_ee[cnt]=(ee->at(k));
                        cnt++;
                    }
                }else{
                    //std::cout << "i,j=" << i << "," << j << " is MASKED." <<  std::endl;
                }
            }
        }else{
            //std::cout << "i=" << i << " is MASKED." <<  std::endl;
        }
    }
    //std::cout << "cnt,tmp_ii.size()=" << cnt << "," << tmp_ii.size() << std::endl;
    std::string label = _stools->UInt4ToString( caseId );
    D4MatOne* One = new D4MatOne();
    delete One->_HH;
    One->_HH = new HeaderBase( ecm->PutHeader() );
    if (One->PutHeaderPointer()->CheckKey(One->D4MAT2LABEL)==1){
        One->PutHeaderPointer()->OverWrite(One->D4MAT2LABEL,label);
    }else{
        One->PutHeaderPointer()->Add(One->D4MAT2LABEL,label);
    }
    One->Vx->resize( tmp_vx.size(), 0.0 );
    One->Vy->resize( tmp_vx.size(), 0.0 );
    One->Vz->resize( tmp_vx.size(), 0.0 );
    One->Vw->resize( tmp_vx.size(), 0.0 );
    One->Intensity->resize( tmp_vx.size(), 0.0 );
    One->Error->resize( tmp_vx.size(), 0.0 );
    One->Energy->resize( tmp_vx.size(), 0.0 );
    for (UInt4 i=0; i<tmp_vx.size(); i++){
        One->Vx->at(i) = (float)tmp_vx[i];
        One->Vy->at(i) = (float)tmp_vy[i];
        One->Vz->at(i) = (float)tmp_vz[i];
        One->Vw->at(i) = (float)tmp_vw[i];
        One->Intensity->at(i) = (float)tmp_ii[i];
        One->Error->at(i) = (float)tmp_ee[i];
    }
    if (_D4mat->PutPointer( caseId-1 )!=NULL)
        delete _D4mat->PutPointer( caseId-1 );
    _D4mat->data->at( caseId-1 ) = One;
    return true;
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4Matrix2::
AllocateD4MatPseudoOnLine( UInt4 num_of_cases ){
    //_D4mat->Allocate( num_of_cases );
    delete _D4mat;
    _D4mat = new D4MatGroup(_HH);
    _D4mat->_XtalParam = MakeXmlStringFromHeader( _HH );
    _D4mat->data->resize( num_of_cases, NULL );
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
ImportEcmsContRotPseudoOnLine( UtsusemiEventDataMonitorNeunet* EDC,
                       const std::vector<UInt4> CaseId, const std::vector<Double> Phi,
                       const std::string maskfile, const Double dOmega,
                       const Double normFactor, const std::string detEffi,
                       const bool isRefresh, const UInt4 reductCase ){

    UInt4 num_multh = UtsusemiGetNumOfMulTh();
    if (_HH->CheckKey("ProjectionAxes")==0){
        UtsusemiError( MessageTag+"ImportEcmsContRot >> ProjectionAxes is not set.");
        return -1;
    }
    std::vector<Double> VA = _HH->PutDoubleVector("ProjectionAxes");

    if (isRefresh){
        delete _D4mat;
        _D4mat = new D4MatGroup(_HH);
        _D4mat->_XtalParam = MakeXmlStringFromHeader( _HH );
        _D4mat->data->resize( Phi.size(), NULL );
    }
    UInt4 csize=(UInt4)(CaseId.size());

#ifdef MULTH
    omp_set_num_threads( num_multh );
#endif

#pragma omp parallel for
#if (_OPENMP >= 200805)  // OpenMP 3.0 and later
    for (UInt4 ind=0;ind<csize;ind++){
#else
    for (Int4 ind=0;ind<(Int4)csize;ind++){
#endif
        ElementContainerMatrix* ecm = new ElementContainerMatrix();
        //UInt4 p=omp_get_thread_num();
        //std::cout << "#"<<"("<< p <<")";

        EDC->Output( ecm, CaseId[ind] );

        UtsusemiSetMask *MSK = new UtsusemiSetMask(ecm, maskfile);
        MSK->Execute();
        delete MSK;

        UtsusemiDetectorEfficiencyCorrection* DEC = new UtsusemiDetectorEfficiencyCorrection();
        if (DEC->LoadDataFile(detEffi)) DEC->Execute(ecm);
        else UtsusemiWarning( MessageTag+"ImportEcmsContRot >> Detector Efficiency correction is not done.");
        delete DEC;

        UtsusemiReductionInEla* URI = new UtsusemiReductionInEla( ecm );
        URI->CalcPhi();
        if ((((reductCase)>>3)&0x1)==1) URI->dHWCorrect();       // 4th bit is 1
        if ((((reductCase)>>2)&0x1)==1) URI->NormBySolidAngle(); // 3rd bit is 1
        if ((((reductCase)>>1)&0x1)==1) URI->KiKfCorrect();      // 2nd bit is 1
        if (((reductCase)&0x1)==1)      URI->NormByKickers(normFactor);    // 1st bit is 1
        delete URI;

        /*
        UtsusemiReductionInEla* URI = new UtsusemiReductionInEla( ecm );
        URI->CalcPhi();
        URI->dHWCorrect();
        URI->NormBySolidAngle();
        URI->KiKfCorrect();
        URI->NormByKickers();
        delete URI;
        */

        ImportEcmContRot( ecm, CaseId[ind], Phi[ind] );
        delete ecm;
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
RemoveEcm( UInt4 runNO ){
    StringTools ST;
    UInt4 num_of_ec = _D4mat->PutSize();
    for (UInt4 i=0;i<num_of_ec;i++){
        HeaderBase* hh = _D4mat->PutPointer(i)->PutHeaderPointer();
        if (runNO == ST.StringToUInt4( hh->PutString(UTSUSEMI_KEY_HEAD_RUNNUMBER) ) ){
            _D4mat->data->erase( _D4mat->data->begin() + i);
            num_of_ec -= 1;
        }
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
RemoveEcm( std::string label ){
    StringTools ST;
    UInt4 num_of_ec = _D4mat->PutSize();
    for (UInt4 i=0;i<num_of_ec;i++){
        HeaderBase* hh = _D4mat->PutPointer(i)->PutHeaderPointer();
        if (label == hh->PutString(_D4mat->PutPointer(i)->D4MAT2LABEL) ){
            _D4mat->data->erase( _D4mat->data->begin() + i);
            num_of_ec -= 1;
        }
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4Matrix2::
ClearAll(){
    delete _D4mat;
    _D4mat = new D4MatGroup(_HH);
    _D4mat->_XtalParam = MakeXmlStringFromHeader( _HH );
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4Matrix2::
_putQvectorsFromData(D4MatOne* ec, std::vector<float> *Vx, std::vector<float> *Vy, std::vector<float> *Vz, std::vector<float> *Vw){
    std::vector<Double> LatticeConsts = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS);
    std::vector<Double> Uvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT);
    std::vector<Double> Vvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT);
    std::vector<Double> Rvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS);
    UtsusemiSqeCalc2* vc = new UtsusemiSqeCalc2();
    UtsusemiUnitConverter* UCC = new UtsusemiUnitConverter();
    Double Ei = 0.0;
    Double ki = 0.0;
    Double kf = 0.0;

    HeaderBase* hh = ec->PutHeaderPointer();
    std::vector<Double> rv( Rvec.size() );
    copy( Rvec.begin(), Rvec.end(), rv.begin() );
    rv.push_back(1);
    rv.push_back(hh->PutDouble( ec->D4MAT2ANGLE ));
    std::vector<Double> A = vc->MakeProjectionMatrix( LatticeConsts, Uvec, Vvec, rv, _viewAxis );

    if (isDirectGeometry){
        Ei = hh->PutDouble(UTSUSEMI_KEY_HEAD_EI);
        ki = sqrt( UCC->EtoK2( Ei ) );
    }
    std::vector<float>* vhw = ec->Energy;
    std::vector<float>* PA = ec->PolarAngles;
    std::vector<float>* AA = ec->AzimAngles;
    std::vector<float>* Ef = ec->EFs;

    UInt4 nPix = hh->PutInt4( ec->D4MAT2NUMOFPIXELS );
    UInt4 cnt = 0;
    UInt4 numOfhw = (UInt4)(vhw->size())/nPix;
    for (UInt4 iPix=0; iPix<nPix; iPix++){
        Double px = sin(PA->at(iPix))*cos(AA->at(iPix));
        Double py = sin(PA->at(iPix))*sin(AA->at(iPix));
        Double pz = cos(PA->at(iPix));
        Double ef = 0;
        if ((!Ef->empty())&&(Ef->at(0)!=0.0)) ef=Ef->at(iPix);
        for (UInt4 j=0; j<numOfhw; j++){
            Double hw = vhw->at(numOfhw*iPix+j);
            if (isDirectGeometry){
                kf = sqrt( UCC->EtoK2( Ei-hw ) );
            }else{
                ki = sqrt( UCC->EtoK2( ef+hw ) );
                kf = sqrt( UCC->EtoK2( ef ));
            }
            Double qx = -kf*px;
            Double qy = -kf*py;
            Double qz = ki-kf*pz;

            Vx->at(cnt) = (float)(qx*A[0] + qy*A[1] + qz*A[2] + hw*A[3]);
            Vy->at(cnt) = (float)(qx*A[4] + qy*A[5] + qz*A[6] + hw*A[7]);
            Vz->at(cnt) = (float)(qx*A[8] + qy*A[9] + qz*A[10] + hw*A[11]);
            Vw->at(cnt) = (float)(qx*A[12] + qy*A[13] + qz*A[14] + hw*A[15]);
            cnt++;
        }
    }
    delete vc;
    delete UCC;
}

//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
_Slice2D( ElementContainerArray* eca, std::vector<Double> ax1range, std::vector<Double> ax2range, std::vector<Double> ax3range, std::vector<Double> ax4range, std::vector<std::string> type, std::vector<Double> folding, std::vector<std::string> axunits )
{
    std::vector<Int4> v_type;
    v_type.resize(4,-1);

    std::vector< std::vector<Double> > ranges;
    ranges.push_back( ax1range );
    ranges.push_back( ax2range );
    ranges.push_back( ax3range );
    ranges.push_back( ax4range );

    for (UInt4 i=0;i<type.size();i++){
        if ((type[i]=="X")||(type[i]=="x")){
            v_type[0] = i;
        }
        if ((type[i]=="Y")||(type[i]=="y")){
            v_type[1] = i;
        }
        if ((type[i]=="T")||(type[i]=="t")){
            if (v_type[2]==-1){
                v_type[2] = i;
            }else{
                v_type[3] = i;
            }
        }
    }

    // Folding preperation
    bool isFoldingFYminusFX = false; // Y=X line
    bool isFoldingFYplusFX = false;  // Y=-X line
    UInt4 indFX=0;
    UInt4 indFY=0;
    if ((folding.size()==7)&&(folding[4]>0.0)){
        if (folding[4]==1){
            isFoldingFYminusFX = true;
        }else if (folding[4]==2){
            isFoldingFYplusFX = true;
        }else if (folding[4]==3){
            isFoldingFYminusFX = true;
            isFoldingFYplusFX = true;
        }else{
        }

        /*std::vector<UInt4> dam;
        for (UInt4 i = 5; i < 7; i++){
            if ((UInt4)folding[i] == v_type[0]) indFX = (UInt4)folding[i];
            else if ((UInt4)folding[i] == v_type[1]) indFY = (UInt4)folding[i];
            else dam.push_back(i);
        }
        for (UInt4 i = 0; i < dam.size(); i++){
            if (indFX == 9) indFX = dam[i];
            else if (indFY == 9) indFY = dam[i];
        }*/
        indFX = (UInt4)folding[5];
        indFY = (UInt4)folding[6];
    }

    Double xbin_width = ranges[v_type[0]][2];
    Double ybin_width = ranges[v_type[1]][2];
    if ((xbin_width <= 0.0) || (ybin_width <= 0.0)){
        UtsusemiError("UtsusemiD4Matrix2::_Slice2D Step of Xbin or Ybin is zero.");
        return false;
    }
    std::vector<Double> xrange = CalcRangeAsBinCenterZero( ranges[v_type[0]][0],ranges[v_type[0]][1], xbin_width );
    std::vector<Double> yrange = CalcRangeAsBinCenterZero( ranges[v_type[1]][0],ranges[v_type[1]][1], ybin_width );
    std::vector<Double> xbin;
    std::vector<Double> ybin;
    for (Double x=xrange[0];x<=xrange[1];x+=xbin_width) xbin.push_back( x );
    for (Double y=yrange[0];y<=yrange[1];y+=ybin_width) ybin.push_back( y );
    UInt4 n_X = (UInt4)( xrange[2] );
    UInt4 n_Y = (UInt4)( yrange[2] );
    //std::cout << "yrange=" << yrange[0] << "," << yrange[1] << "," << yrange[2] << std::endl;

    float ***dArray, ***eArray, ***cArray;
    dArray = new float**[ _NumOfMulTh ];
    eArray = new float**[ _NumOfMulTh ];
    cArray = new float**[ _NumOfMulTh ];
    for (UInt4 i=0;i<_NumOfMulTh;i++){
        dArray[i] = new float*[ n_X ];
        eArray[i] = new float*[ n_X ];
        cArray[i] = new float*[ n_X ];

        for (UInt4 j=0;j<n_X;j++){
            dArray[i][j] = new float[ n_Y ];
            eArray[i][j] = new float[ n_Y ];
            cArray[i][j] = new float[ n_Y ];
        }
    }

    for (UInt4 k=0;k<_NumOfMulTh;k++){
        for (UInt4 i=0;i<n_X;i++){
            for (UInt4 j=0;j<n_Y;j++){
                dArray[k][i][j]=eArray[k][i][j]=cArray[k][i][j]=0.0;
            }
        }
    }

    Double *T1range = new Double[2];
    if (ranges[v_type[2]].size()>=2){
        T1range[0] = ranges[v_type[2]][0];
        T1range[1] = ranges[v_type[2]][1];
    }else{
        UtsusemiError( " ERROR on T1 range " );
        return false;
    }

    Double *T2range = new Double[2];
    if (ranges[v_type[3]].size()>=2){
        T2range[0] = ranges[v_type[3]][0];
        T2range[1] = ranges[v_type[3]][1];
    }else{
        UtsusemiError( " ERROR on T2 range " );
        return false;
    }
    for (UInt4 runId=0;runId<_D4mat->PutSize();runId++){
        D4MatOne* ec_D4mat = _D4mat->data->at(runId);
        if (ec_D4mat==NULL) continue;
        std::vector<std::vector<float>*> ax(4);

        if (isMemSaveMode){
            ax[0] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            ax[1] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            ax[2] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            ax[3] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            _putQvectorsFromData(ec_D4mat, ax[0], ax[1], ax[2], ax[3]);
        }else{
            ax[0] = ec_D4mat->Vx;
            ax[1] = ec_D4mat->Vy;
            ax[2] = ec_D4mat->Vz;
            ax[3] = ec_D4mat->Vw;
        }
        std::vector<float>* ii = ec_D4mat->Intensity;
        std::vector<float>* ee = ec_D4mat->Error;
        //std::cout << "@@@ runId=" << runId << std::endl;
#ifdef MULTH
        omp_set_num_threads( _NumOfMulTh );

        if ((isFoldingFYplusFX) || (isFoldingFYminusFX)){
#pragma omp parallel for
#if (_OPENMP >= 200805)  // OpenMP 3.0 and later
            for (UInt4 ind=0;ind<ax[0]->size();ind++){
#else
            for (Int4 ind=0;ind<ax[0]->size();ind++){
#endif
                UInt4 multh = omp_get_thread_num();

                std::vector<Double> AX(4,0.0); // X=AX[indX],Y=AX[indY],T1=AX[indT1],T2=AX[indT2]
                AX[0] = ax[0]->at(ind);
                AX[1] = ax[1]->at(ind);
                AX[2] = ax[2]->at(ind);
                AX[3] = ax[3]->at(ind);

                // Folding along diagonal line
                if ((isFoldingFYminusFX)&&(AX[indFY]<AX[indFX])){
                    Double tmp = AX[indFX];
                    AX[indFX] = AX[indFY];
                    AX[indFY] = tmp;
                }
                if ((isFoldingFYplusFX)&&(AX[indFY]<(-AX[indFX]))){
                    Double tmp = -AX[indFX];
                    AX[indFX] = -AX[indFY];
                    AX[indFY] = tmp;
                }

                Double X = AX[ v_type[0] ];
                Double Y = AX[ v_type[1] ];
                Double T1 = AX[ v_type[2] ];
                Double T2 = AX[ v_type[3] ];

                if (folding[ v_type[0] ]==0.0) X = fabs(X);
                if (folding[ v_type[0] ]>0.0) X = fabs(X) - (floor(fabs(X)/folding[v_type[0]])*folding[v_type[0]]);

                if (folding[ v_type[1] ]==0.0) Y = fabs(Y);
                if (folding[ v_type[1] ]>0.0) Y = fabs(Y) - (floor(fabs(Y)/folding[v_type[1]])*folding[v_type[1]]);

                if (folding[ v_type[2] ]==0.0) T1 = fabs(T1);
                if (folding[ v_type[2] ]>0.0) T1 = fabs(T1) - (floor(fabs(T1)/folding[v_type[2]])*folding[v_type[2]]);

                if (folding[ v_type[3] ]==0.0) T2 = fabs(T2);
                if (folding[ v_type[3] ]>0.0) T2 = fabs(T2) - (floor(fabs(T2)/folding[v_type[3]])*folding[v_type[3]]);

                if ((T1range[0]<=T1)&&(T1<T1range[1])){
                    if ((T2range[0]<=T2)&&(T2<T2range[1])){
                        if ((xrange[0]<=X)&&(X<xrange[1])){
                            if ((yrange[0]<=Y)&&(Y<yrange[1])){
                                UInt4 i_X = (UInt4)( (X-xrange[0])/xbin_width );
                                UInt4 i_Y = (UInt4)( (Y-yrange[0])/ybin_width );

                                if ((ee->at(ind))>=0.0){
                                    dArray[multh][i_X][i_Y] += (ii->at(ind));
                                    eArray[multh][i_X][i_Y] += (ee->at(ind))*(ee->at(ind));
                                    cArray[multh][i_X][i_Y] += 1.0;
                                }
                            }
                        }
                    }
                }
            }
            if (isMemSaveMode){
                delete ax[0];
                delete ax[1];
                delete ax[2];
                delete ax[3];
            }
        }else if ((folding[0] >= 0.0) || (folding[1] >= 0.0) || (folding[2] >= 0.0) || (folding[3] >= 0.0)  ){
#pragma omp parallel for
#if (_OPENMP >= 200805)  // OpenMP 3.0 and later
            for (UInt4 ind=0;ind<ax[0]->size();ind++){
#else
            for (Int4 ind=0;ind<ax[0]->size();ind++){
#endif
                UInt4 multh = omp_get_thread_num();
                Double X = ax[ v_type[0] ]->at(ind);
                if (folding[ v_type[0] ]==0.0) X = fabs(X);
                if (folding[ v_type[0] ]>0.0) X = fabs(X) - (floor(fabs(X)/folding[v_type[0]])*folding[v_type[0]]);
                Double Y = ax[ v_type[1] ]->at(ind);
                if (folding[ v_type[1] ]==0.0) Y = fabs(Y);
                if (folding[ v_type[1] ]>0.0) Y = fabs(Y) - (floor(fabs(Y)/folding[v_type[1]])*folding[v_type[1]]);
                Double T1 = ax[ v_type[2] ]->at(ind);
                if (folding[ v_type[2] ]==0.0) T1 = fabs(T1);
                if (folding[ v_type[2] ]>0.0) T1 = fabs(T1) - (floor(fabs(T1)/folding[v_type[2]])*folding[v_type[2]]);
                Double T2 = ax[ v_type[3] ]->at(ind);
                if (folding[ v_type[3] ]==0.0) T2 = fabs(T2);
                if (folding[ v_type[3] ]>0.0) T2 = fabs(T2) - (floor(fabs(T2)/folding[v_type[3]])*folding[v_type[3]]);

                if ((T1range[0]<=T1)&&(T1<T1range[1])){
                    if ((T2range[0]<=T2)&&(T2<T2range[1])){
                        if ((xrange[0]<=X)&&(X<xrange[1])){
                            if ((yrange[0]<=Y)&&(Y<yrange[1])){
                                UInt4 i_X = (UInt4)( (X-xrange[0])/xbin_width );
                                UInt4 i_Y = (UInt4)( (Y-yrange[0])/ybin_width );

                                if ((ee->at(ind))>=0.0){
                                    dArray[multh][i_X][i_Y] += (ii->at(ind));
                                    eArray[multh][i_X][i_Y] += (ee->at(ind))*(ee->at(ind));
                                    cArray[multh][i_X][i_Y] += 1.0;
                                }
                            }
                        }
                    }
                }
            }
            if (isMemSaveMode){
                delete ax[0];
                delete ax[1];
                delete ax[2];
                delete ax[3];
            }
        }else{
#pragma omp parallel for
#if (_OPENMP >= 200805)  // OpenMP 3.0 and later
            for (UInt4 ind=0;ind<ax[0]->size();ind++){
#else
            for (Int4 ind=0;ind<ax[0]->size();ind++){
#endif
                UInt4 multh = omp_get_thread_num();
                Double X = ax[ v_type[0] ]->at(ind);
                Double Y = ax[ v_type[1] ]->at(ind);
                Double T1 = ax[ v_type[2] ]->at(ind);
                Double T2 = ax[ v_type[3] ]->at(ind);
                if ((T1range[0]<=T1)&&(T1<T1range[1])){
                    if ((T2range[0]<=T2)&&(T2<T2range[1])){
                        if ((xrange[0]<=X)&&(X<xrange[1])){
                            if ((yrange[0]<=Y)&&(Y<yrange[1])){
                                UInt4 i_X = (UInt4)( (X-xrange[0])/xbin_width );
                                UInt4 i_Y = (UInt4)( (Y-yrange[0])/ybin_width );

                                if ((ee->at(ind))>=0.0){
                                    dArray[multh][i_X][i_Y] += (ii->at(ind));
                                    eArray[multh][i_X][i_Y] += (ee->at(ind))*(ee->at(ind));
                                    cArray[multh][i_X][i_Y] += 1.0;
                                }
                            }
                        }
                    }
                }
            }
            if (isMemSaveMode){
                delete ax[0];
                delete ax[1];
                delete ax[2];
                delete ax[3];
            }
        }

#else
        for (UInt4 ind=0;ind<ax[0]->size();ind++){
            std::vector<Double> AX(4,0.0); // X=AX[indX],Y=AX[indY],T1=AX[indT1],T2=AX[indT2]
            AX[0] = ax[0]->at(ind);
            AX[1] = ax[1]->at(ind);
            AX[2] = ax[2]->at(ind);
            AX[3] = ax[3]->at(ind);
            // Folding along diagonal line
            if ((isFoldingFYminusFX)&&(AX[indFY]<AX[indFX])){
                Double tmp = AX[indFX];
                AX[indFX] = AX[indFY];
                AX[indFY] = tmp;
            }
            if ((isFoldingFYplusFX)&&(AX[indFY]<(-AX[indFX]))){
                Double tmp = -AX[indFX];
                AX[indFX] = -AX[indFY];
                AX[indFY] = tmp;
            }

            Double X = AX[ v_type[0] ];
            Double Y = AX[ v_type[1] ];
            Double T1 = AX[ v_type[2] ];
            Double T2 = AX[ v_type[3] ];

            if (folding[ v_type[0] ]==0.0) X = fabs(X);
            if (folding[ v_type[0] ]>0.0) X = fabs(X) - (floor(fabs(X)/folding[v_type[0]])*folding[v_type[0]]);

            if (folding[ v_type[1] ]==0.0) Y = fabs(Y);
            if (folding[ v_type[1] ]>0.0) Y = fabs(Y) - (floor(fabs(Y)/folding[v_type[1]])*folding[v_type[1]]);

            if (folding[ v_type[2] ]==0.0) T1 = fabs(T1);
            if (folding[ v_type[2] ]>0.0) T1 = fabs(T1) - (floor(fabs(T1)/folding[v_type[2]])*folding[v_type[2]]);

            if (folding[ v_type[3] ]==0.0) T2 = fabs(T2);
            if (folding[ v_type[3] ]>0.0) T2 = fabs(T2) - (floor(fabs(T2)/folding[v_type[3]])*folding[v_type[3]]);

            if ((T1range[0]<=T1)&&(T1<T1range[1])){
                if ((T2range[0]<=T2)&&(T2<T2range[1])){
                    if ((xrange[0]<=X)&&(X<=xrange[1])){
                        if ((yrange[0]<=Y)&&(Y<=yrange[1])){
                            UInt4 i_X = (UInt4)( (X-xrange[0])/xbin_width );
                            UInt4 i_Y = (UInt4)( (Y-yrange[0])/ybin_width );

                            if ((ee->at(ind))>=0.0){
                                dArray[0][i_X][i_Y] += (ii->at(ind));
                                eArray[0][i_X][i_Y] += (ee->at(ind))*(ee->at(ind));
                                cArray[0][i_X][i_Y] += 1.0;
                            }
                        }
                    }
                }
            }
        }
        if (isMemSaveMode){
            delete ax[0];
            delete ax[1];
            delete ax[2];
            delete ax[3];
        }
#endif
    }

        //std::cout << "n_X,n_y=" << n_X << "," << n_Y << std::endl;
        //std::cout << "xbin.size()=" << xbin.size() << std::endl;
        //std::cout << "ybin.size()=" << ybin.size() << std::endl;

    std::string XKEY = "ax"+ std::to_string( v_type[0] + 1);
    std::string YKEY = "ax"+ std::to_string( v_type[1] + 1);

    for (UInt4 x=0;x<n_X;x++){
        std::vector<Double> xr;
        xr.push_back( xbin[x] );
        xr.push_back( xbin[x+1] );
        HeaderBase hh;
        hh.Add( UTSUSEMI_KEY_HEAD_XRANGE, xr);
        hh.Add(MLF_KEY_HEAD_XUNIT,axunits[v_type[0]]);
        hh.Add( XKEY, (xbin[x]+xbin[x+1])/2.0 );
        hh.Add(MLF_KEY_HEAD_UNIT_PRE+XKEY,axunits[v_type[0]]);

        ElementContainer ec(hh);
        ec.Add(YKEY,ybin, axunits[v_type[1]] );
        std::vector<Double> Int;
        std::vector<Double> Err;
        Int.resize( n_Y, 0.0 );
        Err.resize( n_Y, 0.0 );
        for (UInt4 y=0;y<n_Y;y++){
            Double ii = 0.;
            Double ee = 0.;
            Double cc = 0.;
            for (UInt4 i=0;i<_NumOfMulTh;i++){
                ii += dArray[i][x][y];
                ee += eArray[i][x][y];
                cc += cArray[i][x][y];
            }
            if (cc!=0){
                if (_useAveOnSlice){
                    Int[y] = ii/cc;
                    Err[y] = sqrt(ee)/cc;
                }else{
                    Int[y] = ii;
                    Err[y] = sqrt(ee);
                }
            }else{
                Int[y] = MASKVALUE;
                Err[y] = 0.0;
            }
        }
        ec.Add( UTSUSEMI_KEY_INTENSITY, Int, UTSUSEMI_KEY_ARB_UNIT );
        ec.Add( UTSUSEMI_KEY_ERROR, Err, UTSUSEMI_KEY_ARB_UNIT );
        ec.SetKeys( YKEY, UTSUSEMI_KEY_INTENSITY, UTSUSEMI_KEY_ERROR );

        eca->Add(ec);
    }

    // Default axes for M2Plot+
    HeaderBase* hh_eca = eca->PutHeaderPointer();
    hh_eca->Add("M2PP_X_KEY", XKEY);
    hh_eca->Add("M2PP_Y_KEY", YKEY);

    for (UInt4 i=0;i<_NumOfMulTh;i++){
        for (UInt4 j=0;j<n_X;j++){
            delete [] dArray[i][j];
            delete [] eArray[i][j];
            delete [] cArray[i][j];
        }
        delete [] dArray[i];
        delete [] eArray[i];
        delete [] cArray[i];
    }
    delete [] dArray;
    delete [] eArray;
    delete [] cArray;

    delete [] T1range;
    delete [] T2range;
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
Slice2d( ElementContainerArray* eca, std::vector<Double> ax1range, std::vector<Double> ax2range, std::vector<Double> ax3range, std::vector<Double> ax4range, std::vector<std::string> axType, std::vector<Double> folding, std::vector<std::string> axunits ){
    return _Slice2D( eca, ax1range, ax2range, ax3range, ax4range, axType, folding, axunits );
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
Slice2d( ElementContainerArray* eca, PyObject* Ax1, PyObject* Ax2, PyObject* Ax3, PyObject* Ax4, PyObject* DiagFolding, PyObject* AxUnits ){
    if (!(_XP->SetSliceAxes( Ax1, Ax2, Ax3, Ax4 )))
        return false;
    if (!(_XP->SetDiagFolding(  DiagFolding )))
        return false;
    std::vector<Double> ax1range = _XP->PutAxRange(0);
    std::vector<Double> ax2range = _XP->PutAxRange(1);
    std::vector<Double> ax3range = _XP->PutAxRange(2);
    std::vector<Double> ax4range = _XP->PutAxRange(3);
    std::vector<std::string> axType = _XP->PutAxType();
    std::vector<Double> Folding = _XP->PutFolding();
    std::vector<UInt4> DFold = _XP->PutDiagFolding();
    std::vector<std::string> axuv = __gCppToPython.ListToStringVector( AxUnits );
    if ((axuv.empty())||(axuv.size()!=4)){
        UtsusemiError( MessageTag + "Slice2d >> Arguments AxUnits must be list with size of 4" );
        return false;
    }

    for (UInt4 i=0; i<DFold.size(); i++) Folding.push_back( Double(DFold[i]) );
    return _Slice2D( eca, ax1range, ax2range, ax3range, ax4range, axType, Folding, axuv );
}
//////////////////////////////////////////////////////////////////////
ElementContainerArray UtsusemiD4Matrix2::
Slice2d( std::vector<Double> ax1range, std::vector<Double> ax2range, std::vector<Double> ax3range, std::vector<Double> ax4range, std::vector<std::string> type, std::vector<Double> folding, std::vector<std::string> axunits )
{
    ElementContainerArray eca;
    if (_Slice2D( &eca, ax1range, ax2range, ax3range, ax4range, type, folding, axunits ))
        return eca;

    ElementContainerArray eca_empty;
    return eca_empty;
}
//////////////////////////////////////////////////////////////////////
ElementContainerArray UtsusemiD4Matrix2::
Slice2d( PyObject* ax1range, PyObject* ax2range, PyObject* ax3range, PyObject* ax4range, PyObject* axistype, PyObject* folding, PyObject* axunits ){
    ElementContainerArray empty_ret;
    if ((!PyList_Check(ax1range))||(!PyList_Check(ax2range))||(!PyList_Check(ax3range))||(!PyList_Check(ax4range))||(!PyList_Check(axistype))||(!PyList_Check(folding))||(!PyList_Check(axunits))){
        UtsusemiError( MessageTag + "Slice2d >> arguments must be python-list" );
        return empty_ret;
    }
    std::vector<Double> ax1v = __gCppToPython.ListToDoubleVector( ax1range );
    if ((ax1v.empty())||(ax1v.size()!=2)||(ax1v.size()!=3)){
        UtsusemiError( MessageTag + "Slice2d >> Arguments ax1range must be list with size of 2 or 3" );
        return empty_ret;
    }
    std::vector<Double> ax2v = __gCppToPython.ListToDoubleVector( ax2range );
    if ((ax2v.empty())||(ax2v.size()!=2)||(ax2v.size()!=3)){
        UtsusemiError( MessageTag + "Slice2d >> Arguments ax2range must be list with size of 2 or 3" );
        return empty_ret;
    }
    std::vector<Double> ax3v = __gCppToPython.ListToDoubleVector( ax3range );
    if ((ax3v.empty())||(ax3v.size()!=2)||(ax3v.size()!=3)){
        UtsusemiError( MessageTag + "Slice2d >> Arguments ax3range must be list with size of 2 or 3" );
        return empty_ret;
    }
    std::vector<Double> ax4v = __gCppToPython.ListToDoubleVector( ax4range );
    if ((ax4v.empty())||(ax4v.size()!=2)||(ax4v.size()!=3)){
        UtsusemiError( MessageTag + "Slice2d >> Arguments ax4range must be list with size of 2 or 3" );
        return empty_ret;
    }
    std::vector<std::string> axtv = __gCppToPython.ListToStringVector( axistype );
    if ((axtv.empty())||(ax4v.size()!=4)){
        UtsusemiError( MessageTag + "Slice2d >> Arguments type must be list with size of 4" );
        return empty_ret;
    }
    std::vector<Double> fldv = __gCppToPython.ListToDoubleVector( folding );
    if ((fldv.empty())||(fldv.size()!=4)||(fldv.size()!=7)){
        UtsusemiError( MessageTag + "Slice2d >> Arguments folding must be list with size of 4" );
        return empty_ret;
    }
    std::vector<std::string> axuv = __gCppToPython.ListToStringVector( axunits );
    if ((axuv.empty())||(axuv.size()!=4)){
        UtsusemiError( MessageTag + "Slice2d >> Arguments units must be list with size of 4" );
        return empty_ret;
    }
    ElementContainerArray* eca = new ElementContainerArray();
    if (_Slice2D( eca, ax1v, ax2v, ax3v, ax4v, axtv, fldv, axuv )) return *eca;
    else{
        UtsusemiError( MessageTag + "Slice2d >> Failed. Empty ElementContainerArray returns" );
        return empty_ret;
    }
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
_Slice3D( ElementContainerMatrix* ecm, std::vector<Double> ax1range, std::vector<Double> ax2range, std::vector<Double> ax3range, std::vector<Double> ax4range, std::vector<std::string> type, std::vector<Double> folding )
{
    std::vector<Int4> v_type;
    v_type.resize(4,-1);

    std::vector< std::vector<Double> > ranges;
    ranges.push_back( ax1range );
    ranges.push_back( ax2range );
    ranges.push_back( ax3range );
    ranges.push_back( ax4range );

    for (UInt4 i=0;i<type.size();i++){
        if ((type[i]=="X")||(type[i]=="x")) v_type[0] = i;
        if ((type[i]=="Y")||(type[i]=="y")) v_type[1] = i;
        if ((type[i]=="Z")||(type[i]=="z")) v_type[2] = i;
        if ((type[i]=="T")||(type[i]=="t")) v_type[3] = i;
    }
    for (UInt4 i=0;i<4;i++){
        if (v_type[i]==-1) {
            UtsusemiError( MessageTag + "UtsusemiD4Matrix2::Slice3d >> type is invalid." );
            return false;
        }
    }

    std::vector<Double> xrange = CalcRangeAsBinCenterZero( ranges[v_type[0]][0],ranges[v_type[0]][1],ranges[v_type[0]][2] );
    std::vector<Double> yrange = CalcRangeAsBinCenterZero( ranges[v_type[1]][0],ranges[v_type[1]][1],ranges[v_type[1]][2] );
    std::vector<Double> zrange = CalcRangeAsBinCenterZero( ranges[v_type[2]][0],ranges[v_type[2]][1],ranges[v_type[2]][2] );
    std::vector<Double> xbin;
    std::vector<Double> ybin;
    std::vector<Double> zbin;
    Double xbin_width = ranges[v_type[0]][2];
    Double ybin_width = ranges[v_type[1]][2];
    Double zbin_width = ranges[v_type[2]][2];
    for (Double x=xrange[0];x<=xrange[1];x+=ranges[v_type[0]][2]) xbin.push_back( x );
    for (Double y=yrange[0];y<=yrange[1];y+=ranges[v_type[1]][2]) ybin.push_back( y );
    for (Double z=zrange[0];z<=zrange[1];z+=ranges[v_type[2]][2]) zbin.push_back( z );
    UInt4 n_X = (UInt4)( xrange[2] );
    UInt4 n_Y = (UInt4)( yrange[2] );
    UInt4 n_Z = (UInt4)( zrange[2] );
    //std::cout << "yrange=" << yrange[0] << "," << yrange[1] << "," << yrange[2] << std::endl;

    float ****dArray, ****eArray, ****cArray;
    dArray = new float***[ _NumOfMulTh ];
    eArray = new float***[ _NumOfMulTh ];
    cArray = new float***[ _NumOfMulTh ];
    for (UInt4 i=0;i<_NumOfMulTh;i++){
        dArray[i] = new float**[ n_X ];
        eArray[i] = new float**[ n_X ];
        cArray[i] = new float**[ n_X ];

        for (UInt4 j=0;j<n_X;j++){
            dArray[i][j] = new float*[ n_Y ];
            eArray[i][j] = new float*[ n_Y ];
            cArray[i][j] = new float*[ n_Y ];

            for (UInt4 k=0;k<n_Y;k++){
                dArray[i][j][k] = new float[ n_Z ];
                eArray[i][j][k] = new float[ n_Z ];
                cArray[i][j][k] = new float[ n_Z ];
            }
        }
    }

    for (UInt4 i=0;i<_NumOfMulTh;i++){
        for (UInt4 j=0;j<n_X;j++){
            for (UInt4 k=0;k<n_Y;k++){
                for (UInt4 l=0;l<n_Z;l++){
                    dArray[i][j][k][l]=eArray[i][j][k][l]=cArray[i][j][k][l]=0.0;
                }
            }
        }
    }

    Double *Trange = new Double[2];
    Trange[0] = ranges[v_type[3]][0];
    Trange[1] = ranges[v_type[3]][1];

    for (UInt4 runId=0;runId<_D4mat->PutSize();runId++){
        D4MatOne* ec_D4mat = _D4mat->data->at(runId);
        std::vector<std::vector<float>*> ax(4);
        //ax[0] = ec_D4mat->Vx;
        //ax[1] = ec_D4mat->Vy;
        //ax[2] = ec_D4mat->Vz;
        //ax[3] = ec_D4mat->Vw;
        if (isMemSaveMode){
            ax[0] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            ax[1] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            ax[2] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            ax[3] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            _putQvectorsFromData(ec_D4mat, ax[0], ax[1], ax[2], ax[3]);
        }else{
            ax[0] = ec_D4mat->Vx;
            ax[1] = ec_D4mat->Vy;
            ax[2] = ec_D4mat->Vz;
            ax[3] = ec_D4mat->Vw;
        }
        std::vector<float>* ii = ec_D4mat->Intensity;
        std::vector<float>* ee = ec_D4mat->Error;
        //std::cout << "@@@ runId=" << runId << std::endl;
#ifdef MULTH
        omp_set_num_threads( _NumOfMulTh );
#pragma omp parallel for
#if (_OPENMP >= 200805)  // OpenMP 3.0 and later
        for (UInt4 ind=0;ind<ax[0]->size();ind++){
#else
        for (Int4 ind=0;ind<ax[0]->size();ind++){
#endif
            UInt4 multh = omp_get_thread_num();
            Double X = ax[ v_type[0] ]->at(ind);
            if (folding[ v_type[0] ]==0.0) X = fabs(X);
            if (folding[ v_type[0] ]>0.0) X = fabs(X) - (floor(fabs(X)/folding[v_type[0]])*folding[v_type[0]]);
            Double Y = ax[ v_type[1] ]->at(ind);
            if (folding[ v_type[1] ]==0.0) Y = fabs(Y);
            if (folding[ v_type[1] ]>0.0) Y = fabs(Y) - (floor(fabs(Y)/folding[v_type[1]])*folding[v_type[1]]);
            Double Z = ax[ v_type[2] ]->at(ind);
            if (folding[ v_type[2] ]==0.0) Z = fabs(Z);
            if (folding[ v_type[2] ]>0.0) Z = fabs(Z) - (floor(fabs(Z)/folding[v_type[2]])*folding[v_type[2]]);
            Double T = ax[ v_type[3] ]->at(ind);
            if (folding[ v_type[3] ]==0.0) T = fabs(T);
            if (folding[ v_type[3] ]>0.0) T = fabs(T) - (floor(fabs(T)/folding[v_type[3]])*folding[v_type[3]]);

            if ((Trange[0]<=T)&&(T<Trange[1])){
                if ((xrange[0]<=X)&&(X<=xrange[1])){
                    if ((yrange[0]<=Y)&&(Y<=yrange[1])){
                        if ((zrange[0]<=Z)&&(Z<=zrange[1])){
                            UInt4 i_X = (UInt4)( (X-xrange[0])/xbin_width );
                            UInt4 i_Y = (UInt4)( (Y-yrange[0])/ybin_width );
                            UInt4 i_Z = (UInt4)( (Z-zrange[0])/zbin_width );

                            if ((ee->at(ind))>=0.0){
                                dArray[multh][i_X][i_Y][i_Z] += (ii->at(ind));
                                eArray[multh][i_X][i_Y][i_Z] += (ee->at(ind))*(ee->at(ind));
                                cArray[multh][i_X][i_Y][i_Z] += 1.0;
                            }
                        }
                    }
                }
            }
        }
        if (isMemSaveMode){
            delete ax[0];
            delete ax[1];
            delete ax[2];
            delete ax[3];
        }
#else
        for (UInt4 ind=0;ind<ax[0]->size();ind++){
            Double X = ax[ v_type[0] ]->at(ind);
            if (folding[ v_type[0] ]==0.0) X = fabs(X);
            if (folding[ v_type[0] ]>0.0) X = fabs(X) - (floor(fabs(X)/folding[v_type[0]])*folding[v_type[0]]);
            Double Y = ax[ v_type[1] ]->at(ind);
            if (folding[ v_type[1] ]==0.0) Y = fabs(Y);
            if (folding[ v_type[1] ]>0.0) Y = fabs(Y) - (floor(fabs(Y)/folding[v_type[1]])*folding[v_type[1]]);
            Double Z = ax[ v_type[2] ]->at(ind);
            if (folding[ v_type[2] ]==0.0) Z = fabs(Z);
            if (folding[ v_type[2] ]>0.0) Z = fabs(Z) - (floor(fabs(Z)/folding[v_type[2]])*folding[v_type[2]]);
            Double T = ax[ v_type[3] ]->at(ind);
            if (folding[ v_type[3] ]==0.0) T = fabs(T);
            if (folding[ v_type[3] ]>0.0) T = fabs(T) - (floor(fabs(T)/folding[v_type[3]])*folding[v_type[3]]);

            if ((Trange[0]<=T)&&(T<Trange[1])){
                if ((xrange[0]<=X)&&(X<=xrange[1])){
                    if ((yrange[0]<=Y)&&(Y<=yrange[1])){
                        if ((zrange[0]<=Z)&&(Z<=zrange[1])){
                            UInt4 i_X = (UInt4)( (X-xrange[0])/xbin_width );
                            UInt4 i_Y = (UInt4)( (Y-yrange[0])/ybin_width );
                            UInt4 i_Z = (UInt4)( (Z-yrange[0])/zbin_width );

                            if ((ee->at(ind))>=0.0){
                                dArray[0][i_X][i_Y][i_Z] += (ii->at(ind));
                                eArray[0][i_X][i_Y][i_Z] += (ee->at(ind))*(ee->at(ind));
                                cArray[0][i_X][i_Y][i_Z] += 1.0;
                            }
                        }
                    }
                }
            }
        }
        if (isMemSaveMode){
            delete ax[0];
            delete ax[1];
            delete ax[2];
            delete ax[3];
        }
#endif
    }

    ecm->Allocate( n_X );

    Double xval=0.0;
    Double yval=0.0;
    Double zval=0.0;
    for (UInt4 x=0;x<n_X;x++){
        std::vector<Double> xr;
        xr.push_back( xbin[x] );
        xr.push_back( xbin[x+1] );
        HeaderBase hh;
        hh.Add( UTSUSEMI_KEY_HEAD_XRANGE, xr );
        xval = (xr[0]+xr[1])/2.0;

        ElementContainerArray *eca = new ElementContainerArray(hh);
        eca->Allocate( n_Y );
        for (UInt4 y=0;y<n_Y;y++){
            std::vector<Double> yr(2,0.0);
            yr[0]=ybin[y];
            yr[1]=ybin[y+1];
            HeaderBase hh_e;
            hh_e.Add( "YRANGE", yr );
            yval = (yr[0]+yr[1])/2.0;
            ElementContainer* ec = new ElementContainer(hh_e);

            std::vector<Double> Int( n_Z, 0.0 );
            std::vector<Double> Err( n_Z, 0.0 );
            std::vector<Double> xval_vec( n_Z, xval );
            std::vector<Double> yval_vec( n_Z, yval );
            std::vector<Double> zval_vec( n_Z,0.0 );
            for (UInt4 z=0;z<n_Z;z++){
                Double ii = 0.;
                Double ee = 0.;
                Double cc = 0.;
                zval_vec[z]= (zbin[z]+zbin[z+1])/2.0;
                for (UInt4 i=0;i<_NumOfMulTh;i++){
                    ii += dArray[i][x][y][z];
                    ee += eArray[i][x][y][z];
                    cc += cArray[i][x][y][z];
                }
                if (cc!=0){
                    if (_useAveOnSlice){
                        Int[z] = ii/cc;
                        Err[z] = sqrt(ee)/cc;
                    }else{
                        Int[z] = ii;
                        Err[z] = sqrt(ee);
                    }
                }else{
                    //Int[z] = MASKVALUE;
                    //Err[z] = 0.0;
                    Int[z] = 0.0;
                    Err[z] = -1.0;
                }
            }
            ec->Add( "Zbin", zbin );
            ec->Add( UTSUSEMI_KEY_INTENSITY, Int );
            ec->Add( UTSUSEMI_KEY_ERROR, Err );
            ec->SetKeys( "Zbin", UTSUSEMI_KEY_INTENSITY, UTSUSEMI_KEY_ERROR );
            ec->Add( UTSUSEMI_KEY_VIEWX, xval_vec );
            ec->Add( UTSUSEMI_KEY_VIEWY, yval_vec );
            ec->Add( UTSUSEMI_KEY_VIEWZ, zval_vec );
            eca->Set( y, ec );
        }
        ecm->Set( x, eca );
    }

    //[inamura 170228]-->
    std::vector<std::string> keys(3);
    keys[0]=UTSUSEMI_KEY_VIEWX;
    keys[1]=UTSUSEMI_KEY_VIEWY;
    keys[2]=UTSUSEMI_KEY_VIEWZ;
    ecm->PutHeaderPointer()->Add("SLICE3DKEYS",keys);
    //<--[inamura 170228]

    delete [] Trange;
    for (UInt4 i=0;i<_NumOfMulTh;i++){
        for (UInt4 j=0;j<n_X;j++){
            for (UInt4 k=0;k<n_Y;k++){
                delete [] dArray[i][j][k];
                delete [] eArray[i][j][k];
                delete [] cArray[i][j][k];
            }
            delete [] dArray[i][j];
            delete [] eArray[i][j];
            delete [] cArray[i][j];
        }
        delete [] dArray[i];
        delete [] eArray[i];
        delete [] cArray[i];
    }
    delete [] dArray;
    delete [] eArray;
    delete [] cArray;

    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
Slice3d( ElementContainerMatrix* ecm, PyObject* Ax1, PyObject* Ax2, PyObject* Ax3, PyObject* Ax4, PyObject* DiagFolding )
{
    if (!(_XP->SetSliceAxes( Ax1, Ax2, Ax3, Ax4 )))
        return false;
    if (!(_XP->SetDiagFolding(  DiagFolding )))
        return false;
    std::vector<Double> ax1range = _XP->PutAxRange(0);
    std::vector<Double> ax2range = _XP->PutAxRange(1);
    std::vector<Double> ax3range = _XP->PutAxRange(2);
    std::vector<Double> ax4range = _XP->PutAxRange(3);
    std::vector<std::string> axType = _XP->PutAxType();
    std::vector<Double> Folding = _XP->PutFolding();
    std::vector<UInt4> DFold = _XP->PutDiagFolding();
    for (UInt4 i=0; i<DFold.size(); i++) Folding.push_back( Double(DFold[i]) );
    return _Slice3D( ecm, ax1range, ax2range, ax3range, ax4range, axType, Folding );
}
//////////////////////////////////////////////////////////////////////
ElementContainerMatrix UtsusemiD4Matrix2::
Slice3d( std::vector<Double> ax1range, std::vector<Double> ax2range, std::vector<Double> ax3range, std::vector<Double> ax4range, std::vector<std::string> type, std::vector<Double> folding )
{
    ElementContainerMatrix ecm;
    if ( _Slice3D( &ecm, ax1range, ax2range, ax3range, ax4range, type, folding ) )
        return ecm;
    ElementContainerMatrix ecm_empty;
    return ecm_empty;
}
//////////////////////////////////////////////////////////////////////
ElementContainerMatrix UtsusemiD4Matrix2::
Slice3d( PyObject* ax1range, PyObject* ax2range, PyObject* ax3range, PyObject* ax4range, PyObject* axistype, PyObject* folding ){
    ElementContainerMatrix empty_ret;
    if ((!PyList_Check(ax1range))||(!PyList_Check(ax2range))||(!PyList_Check(ax3range))||(!PyList_Check(ax4range))
        ||(!PyList_Check(axistype))||(!PyList_Check(folding))){
        UtsusemiError( MessageTag + "Slice3d >> arguments must be python-list" );
        return empty_ret;
    }
    std::vector<Double> ax1v = __gCppToPython.ListToDoubleVector( ax1range );
    if ((ax1v.empty())||(ax1v.size()!=2)||(ax1v.size()!=3)){
        UtsusemiError( MessageTag + "Slice3d >> Arguments ax1range must be list with size of 2 or 3" );
        return empty_ret;
    }
    std::vector<Double> ax2v = __gCppToPython.ListToDoubleVector( ax2range );
    if ((ax2v.empty())||(ax2v.size()!=2)||(ax2v.size()!=3)){
        UtsusemiError( MessageTag + "Slice3d >> Arguments ax2range must be list with size of 2 or 3" );
        return empty_ret;
    }
    std::vector<Double> ax3v = __gCppToPython.ListToDoubleVector( ax3range );
    if ((ax3v.empty())||(ax3v.size()!=2)||(ax3v.size()!=3)){
        UtsusemiError( MessageTag + "Slice3d >> Arguments ax3range must be list with size of 2 or 3" );
        return empty_ret;
    }
    std::vector<Double> ax4v = __gCppToPython.ListToDoubleVector( ax4range );
    if ((ax4v.empty())||(ax4v.size()!=2)||(ax4v.size()!=3)){
        UtsusemiError( MessageTag + "Slice3d >> Arguments ax4range must be list with size of 2 or 3" );
        return empty_ret;
    }
    std::vector<std::string> axtv = __gCppToPython.ListToStringVector( axistype );
    if ((axtv.empty())||(ax4v.size()!=4)){
        UtsusemiError( MessageTag + "Slice3d >> Arguments type must be list with size of 4" );
        return empty_ret;
    }
    std::vector<Double> fldv = __gCppToPython.ListToDoubleVector( folding );
    if ((fldv.empty())||(fldv.size()!=4)){
        UtsusemiError( MessageTag + "Slice3d >> Arguments folding must be list with size of 4" );
        return empty_ret;
    }
    ElementContainerMatrix* ecm = new ElementContainerMatrix();
    if ( _Slice3D( ecm, ax1v, ax2v, ax3v, ax4v, axtv, fldv ) ) return *ecm;
    else{
        UtsusemiError( MessageTag + "Slice3d >> Failed. Empty ElementContainerMatrix returns" );
        return empty_ret;
    }
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
WriteData( std::string filepath ){

    //WriteSerializationFile<boost::archive::binary_oarchive>  WS( filepath.c_str() );

    //WS.Save( (*_D4mat) );

    return 0;

}

//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
ReadData( std::string filepath ){
    //delete _D4mat;
    //_D4mat = new ElementContainerArray();
    //ReadSerializationFile<boost::archive::binary_iarchive>  RS( filepath.c_str() );

    //RS.Load( (*_D4mat) );

    return 0;
}

//////////////////////////////////////////////////////////////////////
std::vector<Double> UtsusemiD4Matrix2::
GetAxLimit2(){
    if (AxLimit.empty()){
    }else{
        return AxLimit;
    }
    AxLimit.resize(8);
    AxLimit[0] = 1.0e30; // min of Vx
    AxLimit[1] = -1.0e30;// max of Vx
    AxLimit[2] = 1.0e30; // min of Vy
    AxLimit[3] = -1.0e30;// max of Vy
    AxLimit[4] = 1.0e30; // min of Vz
    AxLimit[5] = -1.0e30;// max of Vz
    AxLimit[6] = 1.0e30; // min of Vw
    AxLimit[7] = -1.0e30;// max of Vw
    for (UInt4 i=0;i<_D4mat->PutSize();i++){
        D4MatOne* ec = _D4mat->data->at(i);
        std::vector<float>* Vx = NULL;
        std::vector<float>* Vy = NULL;
        std::vector<float>* Vz = NULL;
        std::vector<float>* Vw = NULL;
        if (isMemSaveMode){
            std::vector<Double> LatticeConsts = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS);
            std::vector<Double> Uvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT);
            std::vector<Double> Vvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT);
            std::vector<Double> Rvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS);
            UtsusemiSqeCalc2* vc = new UtsusemiSqeCalc2();
            UtsusemiUnitConverter* UCC = new UtsusemiUnitConverter();
            Double Ei = 0.0;
            Double ki = 0.0;
            Double kf = 0.0;

            Vx = new std::vector<float>(ec->Energy->size(), 0.0);
            Vy = new std::vector<float>(ec->Energy->size(), 0.0);
            Vz = new std::vector<float>(ec->Energy->size(), 0.0);
            Vw = new std::vector<float>(ec->Energy->size(), 0.0);
            HeaderBase* hh = ec->PutHeaderPointer();
            std::vector<Double> rv( Rvec.size() );
            copy( Rvec.begin(), Rvec.end(), rv.begin() );
            rv.push_back(1);
            rv.push_back(hh->PutDouble( ec->D4MAT2ANGLE ));
            std::vector<Double> A = vc->MakeProjectionMatrix( LatticeConsts, Uvec, Vvec, rv, _viewAxis );

            if (isDirectGeometry){
                Ei = hh->PutDouble(UTSUSEMI_KEY_HEAD_EI);
                ki = sqrt( UCC->EtoK2( Ei ) );
            }
            std::vector<float>* vhw = ec->Energy;
            std::vector<float>* PA = ec->PolarAngles;
            std::vector<float>* AA = ec->AzimAngles;
            std::vector<float>* Ef = ec->EFs;

            UInt4 nPix = hh->PutInt4( ec->D4MAT2NUMOFPIXELS );
            UInt4 cnt = 0;
            UInt4 numOfhw = (UInt4)(vhw->size())/nPix;
            for (UInt4 iPix=0; iPix<nPix; iPix++){
                Double px = sin(PA->at(iPix))*cos(AA->at(iPix));
                Double py = sin(PA->at(iPix))*sin(AA->at(iPix));
                Double pz = cos(PA->at(iPix));
                Double ef = 0;
                if ((!Ef->empty()) && (Ef->at(0) != 0.0)) ef = Ef->at(iPix);
                for (UInt4 j=0; j<numOfhw; j++){
                    Double hw = vhw->at(numOfhw*iPix+j);
                    if (isDirectGeometry){
                        kf = sqrt( UCC->EtoK2( Ei-hw ) );
                    }else{
                        ki = sqrt( UCC->EtoK2( ef+hw ) );
                        kf = sqrt( UCC->EtoK2( ef ));
                    }
                    Double qx = -kf*px;
                    Double qy = -kf*py;
                    Double qz = ki-kf*pz;

                    Vx->at(cnt) = (float)(qx*A[0] + qy*A[1] + qz*A[2] + hw*A[3]);
                    Vy->at(cnt) = (float)(qx*A[4] + qy*A[5] + qz*A[6] + hw*A[7]);
                    Vz->at(cnt) = (float)(qx*A[8] + qy*A[9] + qz*A[10] + hw*A[11]);
                    Vw->at(cnt) = (float)(qx*A[12] + qy*A[13] + qz*A[14] + hw*A[15]);
                    cnt++;
                }
            }
            delete vc;
            delete UCC;
        }else{
            Vx = ec->Vx;
            Vy = ec->Vy;
            Vz = ec->Vz;
            Vw = ec->Vw;
        }
        std::vector<float>::iterator minVx = min_element(Vx->begin(), Vx->end());
        std::vector<float>::iterator maxVx = max_element(Vx->begin(), Vx->end());
        std::vector<float>::iterator minVy = min_element(Vy->begin(), Vy->end());
        std::vector<float>::iterator maxVy = max_element(Vy->begin(), Vy->end());
        std::vector<float>::iterator minVz = min_element(Vz->begin(), Vz->end());
        std::vector<float>::iterator maxVz = max_element(Vz->begin(), Vz->end());
        std::vector<float>::iterator minVw = min_element(Vw->begin(), Vw->end());
        std::vector<float>::iterator maxVw = max_element(Vw->begin(), Vw->end());

        if (AxLimit[0] > (*minVx)) AxLimit[0] = (*minVx);
        if (AxLimit[1] < (*maxVx)) AxLimit[1] = (*maxVx);
        if (AxLimit[2] > (*minVy)) AxLimit[2] = (*minVy);
        if (AxLimit[3] < (*maxVy)) AxLimit[3] = (*maxVy);
        if (AxLimit[4] > (*minVz)) AxLimit[4] = (*minVz);
        if (AxLimit[5] < (*maxVz)) AxLimit[5] = (*maxVz);
        if (AxLimit[6] > (*minVw)) AxLimit[6] = (*minVw);
        if (AxLimit[7] < (*maxVw)) AxLimit[7] = (*maxVw);

        if (isMemSaveMode){
            delete Vx;
            delete Vy;
            delete Vz;
            delete Vw;
        }
    }
    return AxLimit;
}
//////////////////////////////////////////////////////////////////////
std::vector<Double> UtsusemiD4Matrix2::
GetAxLimit(){
    if (AxLimit.empty()){
    }else{
        return AxLimit;
    }
    AxLimit.clear();
    Double **Ax1, **Ax2, **Ax3, **Ax4;
    Ax1 = new Double*[ _NumOfMulTh ];
    Ax2 = new Double*[ _NumOfMulTh ];
    Ax3 = new Double*[ _NumOfMulTh ];
    Ax4 = new Double*[ _NumOfMulTh ];

    for (UInt4 i=0;i<_NumOfMulTh;i++){
        Ax1[i] = new Double[ 2 ];
        Ax2[i] = new Double[ 2 ];
        Ax3[i] = new Double[ 2 ];
        Ax4[i] = new Double[ 2 ];
    }
    D4MatOne* ec = _D4mat->data->at(0);
    //std::vector<float>* v1 = ec->Vx;
    //std::vector<float>* v2 = ec->Vy;
    //std::vector<float>* v3 = ec->Vz;
    //std::vector<float>* v4 = ec->Vw;
    for (UInt4 i=0;i<_NumOfMulTh;i++){
        Ax1[i][0]=1.0e30;
        Ax1[i][1]=-1.0e30;
        Ax2[i][0]=1.0e30;
        Ax2[i][1]=-1.0e30;
        Ax3[i][0]=1.0e30;
        Ax3[i][1]=-1.0e30;
        Ax4[i][0]=1.0e30;
        Ax4[i][1]=-1.0e30;
        //for (UInt4 j=0;j<2;j++){
            //Ax1[i][j]=v1->at(0);
            //Ax2[i][j]=v2->at(0);
            //Ax3[i][j]=v3->at(0);
            //Ax4[i][j]=v4->at(0);
        //}
    }

#ifdef MULTH
    omp_set_num_threads( _NumOfMulTh );
#endif
    for (UInt4 i=0;i<_D4mat->PutSize();i++){
        D4MatOne* ec = _D4mat->data->at(i);
        //std::vector<float>* Vx = ec->Vx;
        //std::vector<float>* Vy = ec->Vy;
        //std::vector<float>* Vz = ec->Vz;
        //std::vector<float>* Vw = ec->Vw;
        std::vector<float>* Vx = NULL;
        std::vector<float>* Vy = NULL;
        std::vector<float>* Vz = NULL;
        std::vector<float>* Vw = NULL;

        if (isMemSaveMode){
            Vx = new std::vector<float>(ec->Energy->size(), 0.0);
            Vy = new std::vector<float>(ec->Energy->size(), 0.0);
            Vz = new std::vector<float>(ec->Energy->size(), 0.0);
            Vw = new std::vector<float>(ec->Energy->size(), 0.0);
            _putQvectorsFromData(ec, Vx, Vy, Vz, Vw);
        }else{
            Vx = ec->Vx;
            Vy = ec->Vy;
            Vz = ec->Vz;
            Vw = ec->Vw;
        }

        UInt4 n_v = (UInt4)(Vx->size());

#pragma omp parallel for
#if (_OPENMP >= 200805)  // OpenMP 3.0 and later
        for (UInt4 j=0;j<n_v;j++){
#else
        for (Int4 j=0;j<(Int4)n_v;j++){
#endif
            UInt4 multh = omp_get_thread_num();
            if ((Vx->at(j))<Ax1[multh][0]) Ax1[multh][0]=(Vx->at(j));
            if ((Vx->at(j))>Ax1[multh][1]) Ax1[multh][1]=(Vx->at(j));
            if ((Vy->at(j))<Ax2[multh][0]) Ax2[multh][0]=(Vy->at(j));
            if ((Vy->at(j))>Ax2[multh][1]) Ax2[multh][1]=(Vy->at(j));
            if ((Vz->at(j))<Ax3[multh][0]) Ax3[multh][0]=(Vz->at(j));
            if ((Vz->at(j))>Ax3[multh][1]) Ax3[multh][1]=(Vz->at(j));
            if ((Vw->at(j))<Ax4[multh][0]) Ax4[multh][0]=(Vw->at(j));
            if ((Vw->at(j))>Ax4[multh][1]) Ax4[multh][1]=(Vw->at(j));
        }
        if (isMemSaveMode){
            delete Vx;
            delete Vy;
            delete Vz;
            delete Vw;
        }
    }

    std::vector<Double> ret;
    ret.clear();
    ret.resize(8,0.0);
    ret[0] = Ax1[0][0];
    ret[1] = Ax1[0][1];
    ret[2] = Ax2[0][0];
    ret[3] = Ax2[0][1];
    ret[4] = Ax3[0][0];
    ret[5] = Ax3[0][1];
    ret[6] = Ax4[0][0];
    ret[7] = Ax4[0][1];
    for (UInt4 i=0;i<_NumOfMulTh;i++){
        if (Ax1[i][0]<ret[0]) ret[0]=Ax1[i][0];
        if (Ax1[i][1]>ret[1]) ret[1]=Ax1[i][1];
        if (Ax2[i][0]<ret[2]) ret[2]=Ax2[i][0];
        if (Ax2[i][1]>ret[3]) ret[3]=Ax2[i][1];
        if (Ax3[i][0]<ret[4]) ret[4]=Ax3[i][0];
        if (Ax3[i][1]>ret[5]) ret[5]=Ax3[i][1];
        if (Ax4[i][0]<ret[6]) ret[6]=Ax4[i][0];
        if (Ax4[i][1]>ret[7]) ret[7]=Ax4[i][1];
    }

    for (UInt4 i=0;i<_NumOfMulTh;i++){
        delete [] Ax1[i];
        delete [] Ax2[i];
        delete [] Ax3[i];
        delete [] Ax4[i];
    }
    delete [] Ax1;
    delete [] Ax2;
    delete [] Ax3;
    delete [] Ax4;

    AxLimit.resize(ret.size());
    copy(ret.begin(), ret.end(), AxLimit.begin());
    return ret;
}

//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
AllocateD4MatOnDisk(std::vector<Double> vx_range, std::vector<Double> vy_range, std::vector<Double> vz_range, std::vector<Double> vw_range,
                    std::vector<std::string> titles, std::vector<std::string> units, std::string data_dir, std::string paramfile ){

    // Make D4Matrix Data
    Double vx_step;
    if (vx_range.size()==2) vx_step = vx_range[1]-vx_range[0];
    else if (vx_range.size()>2) vx_step = vx_range[2];
    else{
        UtsusemiError(MessageTag +"AllocateD4MatOnDisk vx_range is invalid.");
        return false;
    }
    Double vy_step;
    if (vy_range.size()==2) vy_step = vy_range[1]-vy_range[0];
    else if (vy_range.size()>2) vy_step = vy_range[2];
    else{
        UtsusemiError(MessageTag +"AllocateD4MatOnDisk vy_range is invalid.");
        return false;
    }
    Double vz_step;
    if (vz_range.size()==2) vz_step = vz_range[1]-vz_range[0];
    else if (vz_range.size()>2) vz_step = vz_range[2];
    else{
        UtsusemiError(MessageTag +"AllocateD4MatOnDisk vz_range is invalid.");
        return false;
    }
    Double vw_step;
    if (vw_range.size()==2) vw_step = vw_range[1]-vw_range[0];
    else if (vw_range.size()>2) vw_step = vw_range[2];
    else{
        UtsusemiError(MessageTag +"AllocateD4MatOnDisk vw_range is invalid.");
        return false;
    }
    std::vector<Double> Vxrange = CalcRangeAsBinCenterZero( vx_range[0],vx_range[1],vx_step );
    std::vector<Double> Vyrange = CalcRangeAsBinCenterZero( vy_range[0],vy_range[1],vy_step );
    std::vector<Double> Vzrange = CalcRangeAsBinCenterZero( vz_range[0],vz_range[1],vz_step );
    std::vector<Double> Vwrange = CalcRangeAsBinCenterZero( vw_range[0],vw_range[1],vw_step );

    UInt4 n_Vx = (UInt4)( Vxrange[2] );
    UInt4 n_Vy = (UInt4)( Vyrange[2] );
    UInt4 n_Vz = (UInt4)( Vzrange[2] );
    UInt4 n_Vw = (UInt4)( Vwrange[2] );

    std::vector<UInt4> size_of_Ax(4,0);
    size_of_Ax[3] = n_Vx*n_Vy*n_Vz*sizeof(float)*3;
    size_of_Ax[0] = n_Vy*n_Vz*sizeof(float)*3;
    size_of_Ax[1] = n_Vz*sizeof(float)*3;
    size_of_Ax[2] = sizeof(float)*3;

    // Check and Make Files Names
    std::string data_name_base( paramfile );
    std::string d4mat_param_file;
    std::string d4mat_data_dir;
    std::string::size_type ind = paramfile.find_last_of(".xml");
    if (ind == std::string::npos) {
        d4mat_param_file = paramfile+".xml";
    }else{
        d4mat_param_file = paramfile;
        data_name_base.erase( ind-3 );
    }
    if (data_dir.substr( data_dir.size()-1 )!=std::string("/")){
        d4mat_data_dir = data_dir+"/";
    }else{
        d4mat_data_dir = std::string( data_dir );
    }

    UInt4 num_of_blocks_in_a_file = 0;
    float one_plane_size = (float)((size_of_Ax[3])/1024./1024.);

    if ( one_plane_size> 1000.0 ) num_of_blocks_in_a_file = 1;
    else num_of_blocks_in_a_file = (UInt4)( 1000.0/one_plane_size );

    std::vector<UInt4> index_of_blocks;
    std::vector<std::string> name_of_blocks;
    for (UInt4 i=0;i<n_Vw;i+=num_of_blocks_in_a_file){
        index_of_blocks.push_back(i);
        char ff[10];
        std::snprintf( ff, sizeof(ff), "%05d", i );
        std::string fst = ff;
        std::string fname = data_name_base+"_"+fst+".bin";
        //std::cout << MessageTag << "fname=" << fname<< std::endl;
        name_of_blocks.push_back(fname);
    }
    index_of_blocks.push_back(n_Vw);

    std::vector< std::vector<Double> > ranges(4);
    vx_range[0] = Vxrange[0];
    vx_range[1] = Vxrange[1];
    vy_range[0] = Vyrange[0];
    vy_range[1] = Vyrange[1];
    vz_range[0] = Vzrange[0];
    vz_range[1] = Vzrange[1];
    vw_range[0] = Vwrange[0];
    vw_range[1] = Vwrange[1];

    ranges[0] = vx_range;
    ranges[1] = vy_range;
    ranges[2] = vz_range;
    ranges[3] = vw_range;

    //std::cout << "--- index_of_blocks : ";
    //for (UInt4 i=0; i<index_of_blocks.size(); i++) std::cout << index_of_blocks[i] << ",";
    //std::cout << std::endl;
    //for (UInt4 i=0; i<4; i++){
    //    std::cout << "--- range : ";
    //    for (UInt4 j=0; j<3; j++) std::cout << ranges[i][j] << ",";
    //    std::cout << std::endl;
    //}
    // Save Parameter XML file for D4MatOnDisk
    Int4 ret = SaveParamXmlD4MatOnDisk( d4mat_data_dir, d4mat_param_file, name_of_blocks, index_of_blocks, ranges, titles, units,  _vbinFileComponents );
    if (ret==-1){
        UtsusemiError( MessageTag + "Fail to make new param.xml." );
        return false;
    }

    // Create Container for Sliced D4Matrix on Mem
    float ****dArray, ****eArray, ****cArray;
    dArray = new float***[ n_Vx ];
    eArray = new float***[ n_Vx ];
    cArray = new float***[ n_Vx ];
    for (UInt4 i=0;i<n_Vx;i++){
        dArray[i] = new float**[ n_Vy ];
        eArray[i] = new float**[ n_Vy ];
        cArray[i] = new float**[ n_Vy ];

        for (UInt4 j=0;j<n_Vy;j++){
            dArray[i][j] = new float*[ n_Vz ];
            eArray[i][j] = new float*[ n_Vz ];
            cArray[i][j] = new float*[ n_Vz ];

            for (UInt4 k=0;k<n_Vz;k++){
                dArray[i][j][k] = new float[ num_of_blocks_in_a_file ];
                eArray[i][j][k] = new float[ num_of_blocks_in_a_file ];
                cArray[i][j][k] = new float[ num_of_blocks_in_a_file ];

                for (UInt4 l=0;l<num_of_blocks_in_a_file;l++){
                    dArray[i][j][k][l] = 0.0;
                    eArray[i][j][k][l] = 0.0;
                    cArray[i][j][k][l] = 0.0;
                }
            }
        }
    }

    // Write Container for Sliced D4Matrix on Mem as D4Matrix binary
    FILE* fp;
    float data[3];
    //std::cout << MessageTag << "Size of data="<< sizeof(data) << std::endl;

    for (UInt4 i=0;i<(index_of_blocks.size()-1);i++){
        std::string datapath = d4mat_data_dir + name_of_blocks[i];
        if ((fp=fopen(datapath.c_str(),"wb"))==NULL){
            UtsusemiError( MessageTag+"Cannot open file="+datapath);
            return false;
        }

        for (UInt4 j=0;j<_D4mat->PutSize();j++){
            D4MatOne *ec = _D4mat->PutPointer(j);
            std::vector<float> *Vx = ec->Vx;
            std::vector<float> *Vy = ec->Vy;
            std::vector<float> *Vz = ec->Vz;
            std::vector<float> *Vw = ec->Vw;
            std::vector<float> *ii = ec->Intensity;
            std::vector<float> *ee = ec->Error;

            UInt4 n_v = (UInt4)(Vx->size());

            for (UInt4 k=0;k<n_v;k++){
                // bins that its error values is under 0 are masked.
                if (ee->at(k) <= 0.0) continue;

                Double vw = (Vw->at(k));
                if ((vw<Vwrange[0])||(vw>Vwrange[1])) continue;
                UInt4 i_vw = (UInt4)( (vw-Vwrange[0])/vw_step );
                if ((i_vw<index_of_blocks[i])||(i_vw>=index_of_blocks[i+1])) continue;
                i_vw -= index_of_blocks[i];

                Double vx = (Vx->at(k));
                Double vy = (Vy->at(k));
                Double vz = (Vz->at(k));

                if ((vx<Vxrange[0])||(vx>=Vxrange[1])) continue;
                if ((vy<Vyrange[0])||(vy>=Vyrange[1])) continue;
                if ((vz<Vzrange[0])||(vz>=Vzrange[1])) continue;

                UInt4 i_vx = (UInt4)( (vx-Vxrange[0])/vx_step );
                UInt4 i_vy = (UInt4)( (vy-Vyrange[0])/vy_step );
                UInt4 i_vz = (UInt4)( (vz-Vzrange[0])/vz_step );

                dArray[i_vx][i_vy][i_vz][i_vw] += float((ii->at(k)));
                eArray[i_vx][i_vy][i_vz][i_vw] += float((ee->at(k))*(ee->at(k)));
                cArray[i_vx][i_vy][i_vz][i_vw] += float(1.0);
            }
        }

        for (UInt4 i_Vw=0;i_Vw<(index_of_blocks[i+1]-index_of_blocks[i]);i_Vw++){
            UtsusemiMessage( MessageTag + "step = "+_stools->UInt4ToString(index_of_blocks[i]+i_Vw+1)+"/"+_stools->UInt4ToString(n_Vw));
            for (UInt4 i_Vx=0;i_Vx<n_Vx;i_Vx++){
                for (UInt4 i_Vy=0;i_Vy<n_Vy;i_Vy++){
                    for (UInt4 i_Vz=0;i_Vz<n_Vz;i_Vz++){
                        data[0] = dArray[i_Vx][i_Vy][i_Vz][i_Vw];
                        data[1] = sqrt( eArray[i_Vx][i_Vy][i_Vz][i_Vw] );
                        data[2] = cArray[i_Vx][i_Vy][i_Vz][i_Vw];
                        if ((int)std::fwrite( data, sizeof(data), 1, fp ) !=1){
                            //usleep(50000);
                            std::this_thread::sleep_for(std::chrono::milliseconds(50));
                            if ((int)std::fwrite( data, sizeof(data), 1, fp ) !=1){
                                UtsusemiError( MessageTag+"Failed to write" );
                                return false;
                            }
                        }
                        dArray[i_Vx][i_Vy][i_Vz][i_Vw] = 0.0;
                        eArray[i_Vx][i_Vy][i_Vz][i_Vw] = 0.0;
                        cArray[i_Vx][i_Vy][i_Vz][i_Vw] = 0.0;
                    }
                }
            }
        }
        fclose( fp );
    }

    // Delete Container for Sliced D4Matrix on Mem
    for (UInt4 i=0;i<n_Vx;i++){
        for (UInt4 j=0;j<n_Vy;j++){
            for (UInt4 k=0;k<n_Vz;k++){
                delete [] dArray[i][j][k];
                delete [] eArray[i][j][k];
                delete [] cArray[i][j][k];
            }
            delete [] dArray[i][j];
            delete [] eArray[i][j];
            delete [] cArray[i][j];
        }
        delete [] dArray[i];
        delete [] eArray[i];
        delete [] cArray[i];
    }
    delete [] dArray;
    delete [] eArray;
    delete [] cArray;

    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
AllocateD4MatOnDisk(PyObject* a1range, PyObject* a2range, PyObject* a3range, PyObject* a4range,
                    PyObject* titles, PyObject* units, std::string data_dir, std::string paramfile ){
    if ((!PyList_Check(a1range))||(!PyList_Check(a2range))||(!PyList_Check(a3range))||(!PyList_Check(a4range))
        ||(!PyList_Check(titles))||(!PyList_Check(units))){
        UtsusemiError( MessageTag + "AllocateD4MatOnDisk >> arguments must be python-list" );
        return false;
    }
    std::vector<Double> ax1v = __gCppToPython.ListToDoubleVector( a1range );
    if ((ax1v.empty())&&(ax1v.size()!=2)&&(ax1v.size()!=3)){
        UtsusemiError( MessageTag + "AllocateD4MatOnDisk >> Arguments a1range must be list with size of 2 or 3" );
        return false;
    }
    std::vector<Double> ax2v = __gCppToPython.ListToDoubleVector( a2range );
    if ((ax2v.empty())&&(ax2v.size()!=2)&&(ax2v.size()!=3)){
        UtsusemiError( MessageTag + "AllocateD4MatOnDisk >> Arguments a2range must be list with size of 2 or 3" );
        return false;
    }
    std::vector<Double> ax3v = __gCppToPython.ListToDoubleVector( a3range );
    if ((ax3v.empty())&&(ax3v.size()!=2)&&(ax3v.size()!=3)){
        UtsusemiError( MessageTag + "AllocateD4MatOnDisk >> Arguments a3range must be list with size of 2 or 3" );
        return false;
    }
    std::vector<Double> ax4v = __gCppToPython.ListToDoubleVector( a4range );
    if ((ax4v.empty())&&(ax4v.size()!=2)&&(ax4v.size()!=3)){
        UtsusemiError( MessageTag + "AllocateD4MatOnDisk >> Arguments a4range must be list with size of 2 or 3" );
        return false;
    }
    std::vector<std::string> axtv = __gCppToPython.ListToStringVector( titles );
    if ((axtv.empty())&&(axtv.size()!=4)){
        UtsusemiError( MessageTag + "AllocateD4MatOnDisk >> Arguments titles must be list with size of 4" );
        return false;
    }
    std::vector<std::string> axuv = __gCppToPython.ListToStringVector( units );
    if ((axuv.empty())&&(axuv.size()!=4)){
        UtsusemiError( MessageTag + "AllocateD4MatOnDisk >> Arguments units must be list with size of 4" );
        return false;
    }
    return AllocateD4MatOnDisk( ax1v, ax2v, ax3v, ax4v, axtv, axuv, data_dir, paramfile );
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
SaveParamXmlD4MatOnDisk( std::string d4mat_datadir, std::string d4mat_param_file, std::vector<std::string> name_of_blocks, std::vector<UInt4> index_of_blocks, std::vector< std::vector<Double> > ranges, std::vector<std::string> axtitles, std::vector<std::string> axunits, std::vector<std::string> pathbinfiles ){
    BoostXmlParser *bxml = new BoostXmlParser();
    bxml->SetQuiet( !(UtsusemiEnvGetDebugMode()) );

    if ( bxml->CreateNewTree() ){
        std::string xml_base = "D4Matrix";
        std::string xml_numOfFileBlocks = xml_base + "/numOfFileBlocks";
        bxml->AddElement( xml_numOfFileBlocks, _stools->UInt4ToString( (UInt4)(name_of_blocks.size()) ) );

        std::string xml_blocks = xml_base + "/blocks";
        std::string xml_block = xml_blocks + "/block";
        for (Int4 i=0; i<name_of_blocks.size(); i++){
            std::string xml_file_i = xml_block + ",i=" + _stools->Int4ToString(i);
            bxml->AddElement( xml_file_i, "" );
            std::string xml_file = xml_file_i+"/filename";
            bxml->AddElement( xml_file, name_of_blocks[i] );
            for (Int4 j=0; j<3; j++){
                std::string xml_ax = xml_file_i+"/ax"+_stools->Int4ToString(j+1);
                std::string conts = _stools->DoubleToString( ranges[j][0] )+",";
                conts += _stools->DoubleToString( ranges[j][1] )+",";
                conts += _stools->DoubleToString( ranges[j][2] );
                bxml->AddElement( xml_ax, conts );
            }
            std::string conts = _stools->DoubleToString( ranges[3][0]+ranges[3][2]*(Double)(index_of_blocks[i]) )+",";
            conts += _stools->DoubleToString( ranges[3][0]+ranges[3][2]*(Double)(index_of_blocks[i+1]) )+",";
            conts += _stools->DoubleToString( ranges[3][2] );
            std::string xml_ax = xml_file_i+"/ax4";
            bxml->AddElement( xml_ax, conts );
        }
        std::string xml_axTitle = xml_base + "/axisTitle";
        for (UInt4 i=0; i<4; i++){
            std::string xml_ax = xml_axTitle+"/ax"+_stools->Int4ToString(i+1);
            bxml->AddElement( xml_ax, axtitles[i] );
        }
        std::string xml_axUnit = xml_base + "/axisUnit";
        for (UInt4 i=0; i<4; i++){
            std::string xml_ax = xml_axTitle+"/ax"+_stools->Int4ToString(i+1);
            bxml->AddElement( xml_ax, axunits[i] );
        }
        std::string xml_numoffile = xml_base+"/numOfFileComponents";
        bxml->AddElement( xml_numoffile, _stools->UInt4ToString( (UInt4)(pathbinfiles.size()) ) );

        for (UInt4 i=0;i<pathbinfiles.size();i++){
            std::string xml_filecomp = xml_base+"/fileComponents";
            bxml->AddElement( xml_filecomp, "" );
            std::string xml_filepath = xml_filecomp+"/filepath,i="+_stools->Int4ToString(i);
            bxml->AddElement( xml_filepath, pathbinfiles[i] );
        }


        if (d4mat_datadir.substr( d4mat_datadir.size()-1 )!=std::string("/"))
            d4mat_datadir = d4mat_datadir+"/";
        bxml->Save( d4mat_datadir+d4mat_param_file );

    }else{
        UtsusemiError( MessageTag+"SaveParamXmlD4MatOnDisk > Cannot Make new xml" );
        return -1;
    }
    delete bxml;

    return 0;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
SaveParamXmlD4MatOnDisk( std::string d4mat_datadir, std::string d4mat_param_file, std::vector<std::string> name_of_blocks, std::vector<UInt4> index_of_blocks, std::vector<Double> ax1range, std::vector<Double> ax2range, std::vector<Double> ax3range, std::vector<Double> ax4range, std::vector<std::string> axtitles, std::vector<std::string> axunits, std::vector<std::string> pathbinfiles ){
    std::vector< std::vector<Double> > ranges;
    ranges.push_back( ax1range );
    ranges.push_back( ax2range );
    ranges.push_back( ax3range );
    ranges.push_back( ax4range );
    return SaveParamXmlD4MatOnDisk( d4mat_datadir, d4mat_param_file, name_of_blocks, index_of_blocks, ranges, axtitles, axunits, pathbinfiles );
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4Matrix2::
SetD4MatDataReductionStepByStepAddRunAngles(std::string runNos, double ang, double norm, double normFactor ){
    // Make RunList
    // Protons/ normFactor *-1
    Double protons = 0.0;
    if ((normFactor>0.0) && (norm<0.0))
        protons = norm * normFactor * (-1.0);
    else
        protons = norm;
    if (UtsusemiEnvGetDebugMode()){
        std::cout << "#[inamura 230224] SetD4MatDataReductionStepByStepAddRunAngles norm  = "<< norm << std::endl;
        std::cout << "#[inamura 230224] SetD4MatDataReductionStepByStepAddRunAngles normF = "<< normFactor << std::endl;
    }
    // Calculate origina gonio value : ang = gonio_original_value - gonio_atZero -> gonio_original_value = ang + gonio_atZero
    Double gonio_org = ang + (_TP->SBS_gonioAtZero);

    char cont_c[256];
    std::snprintf(cont_c, sizeof(cont_c), "%08.3f:%s:%8.3f:%g:%d", gonio_org, runNos.c_str(), ang, protons, 3);
    std::string cont(cont_c);
    // Add RunList
    char key_c[20];
    std::snprintf(key_c, sizeof(key_c), "%08.3f", gonio_org);
    std::string key(key_c);
    _TP->RunList[key] = cont;
    return;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
ImportEcmStepByStep(ElementContainerMatrix* ecm, double ang, double norm, double normFactor){
    std::string runNos = ecm->PutHeaderPointer()->PutString(UTSUSEMI_KEY_HEAD_RUNNUMBER);
    SetD4MatDataReductionStepByStepAddRunAngles(runNos, ang, norm, normFactor);

    char label_c[20];
    std::snprintf(label_c, sizeof(label_c), "%08.3f", ang);
    std::string label(label_c);
    std::cout << "#[inamura 230224] ImportEcmStepByStep _TP->mode = " << _TP->mode << std::endl;
    bool isStepByStep = false;
    if (_TP->mode == 1) isStepByStep = true;
    return ImportEcmStepByStep( ecm, ang, label, isStepByStep);
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4Matrix2::
ImportEcmStepByStep( ElementContainerMatrix* ecm, double ang, std::string label, bool isStepByStep ){
    //ElementContainer ec_D4mat( ecm->PutHeader() );
    D4MatOne* ec_D4mat = new D4MatOne();
    delete ec_D4mat->_HH;
    ec_D4mat->_HH = new HeaderBase( ecm->PutHeader() );
    UInt4 n_all = 0;
    UInt4 n_eca = ecm->PutSize();
    Int4 numOfec = 0;
    for (UInt4 i=0;i<n_eca;i++){
        if (ecm->PutPointer(i)->PutHeaderPointer()->PutInt4(UTSUSEMI_KEY_HEAD_MASKED)==1) continue;
        for (UInt4 j=0;j<(ecm->PutPointer(i)->PutSize());j++){
            if (ecm->PutPointer(i)->PutPointer(j)->PutHeaderPointer()->PutInt4(UTSUSEMI_KEY_HEAD_MASKED)==1) continue;
            std::vector<Double>  v_ec = ecm->PutPointer(i)->PutPointer(j)->Put(UTSUSEMI_KEY_INTENSITY);
            UInt4 n_ii = (UInt4)(v_ec.size());
            n_all += n_ii;
            numOfec++;
        }
    }
    ec_D4mat->NumOfPixels = numOfec;
    std::vector<Double> *hw = new std::vector<Double>( n_all,0.0 );
    std::vector<Double> *ii = new std::vector<Double>( n_all,0.0 );
    std::vector<Double> *ee = new std::vector<Double>( n_all,0.0 );

    std::vector<Double> PA;
    std::vector<Double> AA;
    std::vector<Double> PAd; //delta of PA
    std::vector<Double> AAd; //delta of AA
    std::vector<Double> L2;
    std::vector<Double> EF;

    UInt4 cnt = 0;

    for (UInt4 i=0;i<n_eca;i++){
        if (ecm->PutPointer(i)->PutHeaderPointer()->PutInt4(UTSUSEMI_KEY_HEAD_MASKED)==1) continue;
        for (UInt4 j=0;j<(ecm->PutPointer(i)->PutSize());j++){
            if (ecm->PutPointer(i)->PutPointer(j)->PutHeaderPointer()->PutInt4(UTSUSEMI_KEY_HEAD_MASKED)==1) continue;
            ElementContainer* ec = ecm->PutPointer(i)->PutPointer(j);
            std::vector<Double>* vii = ec->PutP(ec->PutYKey());
            std::vector<Double>* vee = ec->PutP(ec->PutEKey());
            std::vector<Double>* vhw = NULL;
            if (isDirectGeometry)
                vhw = (*ec)(UTSUSEMI_KEY_ENERGY);
            else
                vhw = (*ec)(UTSUSEMI_KEY_HW_DNA);
            for (UInt4 k=0; k<vii->size(); k++){
                (hw->at(cnt)) = ((vhw->at(k))+(vhw->at(k+1)))/2.0;
                (ii->at(cnt)) = vii->at(k);
                (ee->at(cnt)) = vee->at(k);
                cnt++;
            }
            std::vector<Double> ppv = ec->PutHeaderPointer()->PutDoubleVector(UTSUSEMI_KEY_HEAD_PIXELPOSITION);
            L2.push_back( sqrt( ppv[0]*ppv[0] + ppv[1]*ppv[1] + ppv[2]*ppv[2] ) );
            if (isDirectGeometry){
                std::vector<Double> vPA = ec->PutHeaderPointer()->PutDoubleVector(UTSUSEMI_KEY_HEAD_PIXELPOLARANGLES);
                std::vector<Double> vAA = ec->PutHeaderPointer()->PutDoubleVector(UTSUSEMI_KEY_HEAD_PIXELAZIMANGLES);
                PA.push_back( vPA[0]*M_PI/180.0 );
                AA.push_back( vAA[0]*M_PI/180.0 );
                PAd.push_back( vPA[1]*M_PI/180.0 );
                AAd.push_back( vAA[1]*M_PI/180.0 );
            }else{
                EF.push_back( ec->PutHeaderPointer()->PutDouble(UTSUSEMI_KEY_HEAD_EF) );
                PA.push_back( ec->PutHeaderPointer()->PutDouble(UTSUSEMI_KEY_HEAD_POLARANGLE) );
                AA.push_back( ec->PutHeaderPointer()->PutDouble(UTSUSEMI_KEY_HEAD_AZIMANGLE) );
            }
        }
    }
    //delete HB;

    if (ec_D4mat->PutHeaderPointer()->CheckKey(ec_D4mat->D4MAT2NUMOFPIXELS)==1)
        ec_D4mat->PutHeaderPointer()->OverWrite(ec_D4mat->D4MAT2NUMOFPIXELS,numOfec);
    else
        ec_D4mat->PutHeaderPointer()->Add(ec_D4mat->D4MAT2NUMOFPIXELS,numOfec);
    if (ec_D4mat->PutHeaderPointer()->CheckKey(ec_D4mat->D4MAT2LABEL)==1)
        ec_D4mat->PutHeaderPointer()->OverWrite(ec_D4mat->D4MAT2LABEL,label);
    else
        ec_D4mat->PutHeaderPointer()->Add(ec_D4mat->D4MAT2LABEL,label);
    if (ec_D4mat->PutHeaderPointer()->CheckKey(ec_D4mat->D4MAT2ANGLE)==1)
        ec_D4mat->PutHeaderPointer()->OverWrite(ec_D4mat->D4MAT2ANGLE,ang);
    else
        ec_D4mat->PutHeaderPointer()->Add(ec_D4mat->D4MAT2ANGLE,ang);

    delete ec_D4mat->Energy;
    ec_D4mat->Energy = new std::vector<float> ( hw->size(), 0.0 );
    for (UInt4 i=0; i<(UInt4)(hw->size()); i++) ec_D4mat->Energy->at(i) = (float)(hw->at(i));
    delete ec_D4mat->Intensity;
    ec_D4mat->Intensity = new std::vector<float> ( ii->size(), 0.0 );
    for (UInt4 i=0; i<ii->size(); i++) ec_D4mat->Intensity->at(i) = (float)(ii->at(i));
    delete ec_D4mat->Error;
    ec_D4mat->Error = new std::vector<float> ( ee->size(), 0.0 );
    for (UInt4 i=0; i<ee->size(); i++) ec_D4mat->Error->at(i) = (float)(ee->at(i));
    delete ec_D4mat->L2;
    ec_D4mat->L2 = new std::vector<float> ( L2.size(), 0.0 );
    for (UInt4 i=0; i<L2.size(); i++) ec_D4mat->L2->at(i) = (float)L2[i];
    delete ec_D4mat->PolarAngles;
    ec_D4mat->PolarAngles = new std::vector<float> ( PA.size(), 0.0 );
    for (UInt4 i=0; i<PA.size(); i++) ec_D4mat->PolarAngles->at(i) = (float)PA[i];
    delete ec_D4mat->AzimAngles;
    ec_D4mat->AzimAngles = new std::vector<float> ( AA.size(), 0.0 );
    for (UInt4 i=0; i<AA.size(); i++) ec_D4mat->AzimAngles->at(i) = (float)AA[i];
    if (isDirectGeometry){
        delete ec_D4mat->PolarAnglesW;
        ec_D4mat->PolarAnglesW = new std::vector<float> ( PAd.size(), 0.0 );
        for (UInt4 i=0; i<PAd.size(); i++) ec_D4mat->PolarAnglesW->at(i) = (float)PAd[i];
        delete ec_D4mat->AzimAnglesW;
        ec_D4mat->AzimAnglesW = new std::vector<float> ( AAd.size(), 0.0 );
        for (UInt4 i=0; i<AAd.size(); i++) ec_D4mat->AzimAnglesW->at(i) = (float)AAd[i];
    }
    delete ec_D4mat->EFs;
    ec_D4mat->EFs = new std::vector<float> ( EF.size(), 0.0 );
    for (UInt4 i=0; i<EF.size(); i++) ec_D4mat->EFs->at(i) = (float)EF[i];

    std::vector<std::string> imported_ecm = PutLabelsOfImportedEcm();
    if (isStepByStep){
        std::vector<std::string>::iterator it = find( imported_ecm.begin(), imported_ecm.end(), label );
        if (it==imported_ecm.end()){
            _D4mat->data->push_back( ec_D4mat );
        }else{
            RemoveEcm( label );
            _D4mat->data->push_back( ec_D4mat );
        }
    }else{
        char label_c[30];
        std::snprintf( label_c, sizeof(label_c), "%08.3f", ang );
        std::string label1(label_c);
        ec_D4mat->PutHeaderPointer()->OverWrite(ec_D4mat->D4MAT2LABEL,label1);
        UInt4 ind = _stools->StringToUInt4(label) - 1;
        if (_D4mat->data->at(ind)==NULL) _D4mat->data->at(ind)=ec_D4mat;
        else{
            delete _D4mat->data->at(ind);
            _D4mat->data->at(ind)=ec_D4mat;
        }
    }

    delete hw;
    delete ii;
    delete ee;
    return 0;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::ExportDataAsEcm(ElementContainerMatrix* ecm, UInt4 index){
    UInt4 size = PutNumOfAngles();
    if (index > (size - 1)){
        std::string msg = MessageTag+"ExportDataAsEcm : Too large the given index.";
        UtsusemiError(msg);
        return false;
    }
    D4MatOne* ec_D4mat = _D4mat->data->at(index);
    ecm->PutHeaderPointer()->InputString(ec_D4mat->PutHeaderPointer()->DumpToString());

    std::vector<float> *hwv = ec_D4mat->Energy;
    std::vector<float> *iiv = ec_D4mat->Intensity;
    std::vector<float> *eev = ec_D4mat->Error;
    std::vector<float> *L2 = ec_D4mat->L2;
    std::vector<float> *PA = ec_D4mat->PolarAngles;
    std::vector<float> *AA = ec_D4mat->AzimAngles;
    std::vector<float> *PAd = ec_D4mat->PolarAnglesW;
    std::vector<float> *AAd = ec_D4mat->AzimAnglesW;
    std::vector<float> *EFs = ec_D4mat->EFs;
    bool isDirectGeometry = false;
    if ((PA->size()) == (PAd->size())) isDirectGeometry = true;
    UInt4 num_of_ecs = (UInt4)(L2->size());
    UInt4 num_of_int = (UInt4)((hwv->size()) / num_of_ecs);

    UInt4 cnt = 0;
    ecm->Allocate(1);
    ElementContainerArray* eca = new ElementContainerArray();
    eca->Allocate(num_of_ecs);
    for (UInt4 i=0; i<num_of_ecs; i++){
        ElementContainer* ec = new ElementContainer();

        std::vector<Double> ppv;
        ppv.push_back((L2->at(i)) * sin(PA->at(i)) * cos(AA->at(i)));
        ppv.push_back((L2->at(i)) * sin(PA->at(i)) * sin(AA->at(i)));
        ppv.push_back((L2->at(i)) * cos(PA->at(i)));
        ec->AddToHeader(UTSUSEMI_KEY_HEAD_PIXELPOSITION, ppv);
        if (isDirectGeometry){
            std::vector<Double> PAv;
            std::vector<Double> AAv;
            PAv.push_back((PA->at(i))/M_PI*180.0);
            PAv.push_back((PAd->at(i))/M_PI*180.0);
            AAv.push_back((AA->at(i))/M_PI*180.0);
            AAv.push_back((AAd->at(i))/M_PI*180.0);
            ec->AddToHeader(UTSUSEMI_KEY_HEAD_PIXELPOLARANGLES, PAv);
            ec->AddToHeader(UTSUSEMI_KEY_HEAD_PIXELAZIMANGLES, PAv);
        }else{
            ec->AddToHeader(UTSUSEMI_KEY_HEAD_EF, EFs->at(i));
            ec->AddToHeader(UTSUSEMI_KEY_HEAD_POLARANGLE, PA->at(i));
            ec->AddToHeader(UTSUSEMI_KEY_HEAD_AZIMANGLE, AA->at(i));
        }
        std::vector<Double> hw(num_of_int + 1, 0.0);
        std::vector<Double> ii(num_of_int, 0.0);
        std::vector<Double> ee(num_of_int, 0.0);
        Double del_hw = ((hwv->at(cnt + 1)) - (hwv->at(cnt))) / 2.0;
        hw[0] = (hwv->at(cnt)) - del_hw;
        for (UInt4 j=0; j<num_of_int; j++){
            hw[j + 1] = hwv->at(cnt) + del_hw;
            ii[j] = (iiv->at(cnt));
            ee[j] = (eev->at(cnt));
            cnt++;
        }
        ec->Add(UTSUSEMI_KEY_ENERGYTRANSFER, hw, UTSUSEMI_KEY_ENERGY_UNIT);
        ec->Add(UTSUSEMI_KEY_INTENSITY, ii, UTSUSEMI_KEY_ARB_UNIT);
        ec->Add(UTSUSEMI_KEY_ERROR, ee, UTSUSEMI_KEY_ARB_UNIT);
        ec->SetKeys(UTSUSEMI_KEY_ENERGYTRANSFER, UTSUSEMI_KEY_INTENSITY, UTSUSEMI_KEY_ERROR);
        eca->Set(i, ec);
    }
    ecm->Set(0, eca);
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::ReplaceIntensityWithEcm(ElementContainerMatrix* ecm, UInt4 index){
    UInt4 size = PutNumOfAngles();
    if (index > (size - 1)){
        std::string msg = MessageTag+"ImportIntensityFromEcm : Too large the given index.";
        UtsusemiError(msg);
        return false;
    }

    D4MatOne* ec_D4mat = _D4mat->data->at(index);
    std::vector<float> *iiv = ec_D4mat->Intensity;
    std::vector<float> *eev = ec_D4mat->Error;
    UInt4 num_of_ecs = (UInt4)(ec_D4mat->L2->size());
    UInt4 num_of_int = (UInt4)((iiv->size()) / num_of_ecs);

    UInt4 cnt = 0;
    for (UInt4 i=0; i<(ecm->PutSize()); i++){
        for (UInt4 j=0; j<(ecm->PutPointer(i)->PutSize()); j++){
            ElementContainer* ec = ecm->PutPointer(i)->PutPointer(j);
            std::vector<Double>* ii = ec->PutP(UTSUSEMI_KEY_INTENSITY);
            std::vector<Double>* ee = ec->PutP(UTSUSEMI_KEY_ERROR);
            for (UInt4 k=0; k<(ii->size()); k++){
                iiv->at(cnt) = (float)(ii->at(k));
                eev->at(cnt) = (float)(ee->at(k));
                cnt++;
            }
        }
    }

    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::MakeVirtualD4Mat2(ElementContainerMatrix* ecm, std::vector<Double> angles, std::vector<std::string> labels){
    ResetD4mat();
    UInt4 ret=ImportEcmStepByStep( ecm, angles[0], labels[0], true );
    if (ret==0){
        D4MatOne* temp = _D4mat->data->at(0);
        for (UInt4 i=1; i<angles.size(); i++){
            std::cout << i <<"/"<<angles.size()-1<< std::endl;
            D4MatOne* c = new D4MatOne( *temp );
            c->PutHeaderPointer()->OverWrite(c->D4MAT2LABEL,labels[i]);
            c->PutHeaderPointer()->OverWrite(c->D4MAT2ANGLE,angles[i]);
            _D4mat->data->push_back( c );
        }
        return true;
    }
    return false;
}
//////////////////////////////////////////////////////////////////////
std::vector<std::string> UtsusemiD4Matrix2::PutLabelsOfImportedEcm(){
    std::vector<std::string> empty;
    if (_D4mat->PutSize()==0){
        return empty;
    }

    std::vector<std::string> retval;
    for (UInt4 i=0; i<_D4mat->PutSize(); i++){
        if (_D4mat->data->at(i)!=NULL){
            D4MatOne* ec = _D4mat->data->at(i);
            if (ec->PutHeaderPointer()->CheckKey(ec->D4MAT2LABEL)==0) return empty;
            retval.push_back( ec->PutHeaderPointer()->PutString(ec->D4MAT2LABEL) );
        }
    }
    return retval;
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4Matrix2::
SetMemorySaving(bool memSave){
    if (memSave){
        for (UInt4 i=0;i<_D4mat->PutSize();i++){
            if (_D4mat->PutPointer(i)==NULL) continue;
            D4MatOne* ec = _D4mat->PutPointer(i);
            if (ec->Vx != NULL) delete ec->Vx;
            if (ec->Vy != NULL) delete ec->Vy;
            if (ec->Vz != NULL) delete ec->Vz;
            if (ec->Vw != NULL) delete ec->Vw;
            ec->Vx = new std::vector<float>();
            ec->Vy = new std::vector<float>();
            ec->Vz = new std::vector<float>();
            ec->Vw = new std::vector<float>();
        }
    }
    isMemSaveMode = memSave;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
Projection( std::vector<Double> viewAxis ){
    UtsusemiMessage( MessageTag+"Projection start. ");
    if (_D4mat->PutSize()==0){
        return false;
    }

    if (_D4mat->PutPointer(0)->Energy->empty()){
        return false;
    }

    if (viewAxis.size() == 16){
        _viewAxis.clear();
        _viewAxis.resize(viewAxis.size());
        copy(viewAxis.begin(), viewAxis.end(), _viewAxis.begin());
    }else{
        std::string msg = "Projection : given argument (viewAxis) is invalid. Its size must be 16, given size is " + _stools->UInt4ToString(viewAxis.size());
        UtsusemiMessage(MessageTag + msg + ".");
        return false;
    }

    if (isMemSaveMode){
        UtsusemiMessage( MessageTag+"Projection : Memory-Saving mode. ");
        return true;
    }
    /*
    _viewAxis.clear();
    _viewAxis.resize(viewAxis.size());
    copy(viewAxis.begin(), viewAxis.end(), _viewAxis.begin());
    */

    std::vector<Double> LatticeConsts = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS);
    std::vector<Double> Uvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT);
    std::vector<Double> Vvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT);
    std::vector<Double> Rvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS);

    UtsusemiSqeCalc2* vc = new UtsusemiSqeCalc2();
    UtsusemiUnitConverter* UCC = new UtsusemiUnitConverter();
    Double Ei = 0.0;
    Double ki = 0.0;
    Double kf = 0.0;
    for (UInt4 i=0;i<_D4mat->PutSize();i++){
        if (_D4mat->PutPointer(i)==NULL) continue;
        D4MatOne* ec = _D4mat->PutPointer(i);
        HeaderBase* hh = ec->PutHeaderPointer();
        std::vector<Double> rv( Rvec.size() );
        copy( Rvec.begin(), Rvec.end(), rv.begin() );
        rv.push_back(1);
        rv.push_back(hh->PutDouble( ec->D4MAT2ANGLE ));
        std::vector<Double> A = vc->MakeProjectionMatrix( LatticeConsts, Uvec, Vvec, rv, viewAxis );
        if (A.size() != 16){
            std::string msg = "Projection(vect) >> Failed to create Projection Matrix. (size = " + _stools->UInt4ToString(A.size()) + ")";
            UtsusemiError(MessageTag + msg);
            continue;
        }

        std::vector<float>* vhw = ec->Energy;
        std::vector<float>* vx = NULL;
        std::vector<float>* vy = NULL;
        std::vector<float>* vz = NULL;
        std::vector<float>* vw = NULL;
        if (ec->Vx->empty()) ec->Vx->resize( vhw->size(), 0.0 );
        else{
            delete ec->Vx;
            ec->Vx = new std::vector<float>( vhw->size(), 0.0 );
        }
        if (ec->Vy->empty()) ec->Vy->resize( vhw->size(), 0.0 );
        else{
            delete ec->Vy;
            ec->Vy = new std::vector<float>( vhw->size(), 0.0 );
        }
        if (ec->Vz->empty()) ec->Vz->resize( vhw->size(), 0.0 );
        else{
            delete ec->Vz;
            ec->Vz = new std::vector<float>( vhw->size(), 0.0 );
        }
        if (ec->Vw->empty()) ec->Vw->resize( vhw->size(), 0.0 );
        else{
            delete ec->Vw;
            ec->Vw = new std::vector<float>( vhw->size(), 0.0 );
        }
        vx = ec->Vx;
        vy = ec->Vy;
        vz = ec->Vz;
        vw = ec->Vw;

        if (isDirectGeometry){
            Ei = hh->PutDouble(UTSUSEMI_KEY_HEAD_EI);
            ki = sqrt( UCC->EtoK2( Ei ) );
        }

        std::vector<float>* PA = ec->PolarAngles;
        std::vector<float>* AA = ec->AzimAngles;
        std::vector<float>* Ef = ec->EFs;

        UInt4 nPix = hh->PutInt4( ec->D4MAT2NUMOFPIXELS );
        UInt4 cnt = 0;
        UInt4 numOfhw = (UInt4)(vhw->size())/nPix;
        for (UInt4 iPix=0; iPix<nPix; iPix++){
            Double px = sin(PA->at(iPix))*cos(AA->at(iPix));
            Double py = sin(PA->at(iPix))*sin(AA->at(iPix));
            Double pz = cos(PA->at(iPix));
            Double ef = 0;
            if ((!Ef->empty()) && (Ef->at(0) != 0.0)) ef = Ef->at(iPix);
            //if (!(Ef->empty())) ef=(Ef->at(iPix));
            for (UInt4 j=0; j<numOfhw; j++){
                Double hw = vhw->at(numOfhw*iPix+j);
                if (isDirectGeometry){
                    kf = sqrt( UCC->EtoK2( Ei-hw ) );
                }else{
                    ki = sqrt( UCC->EtoK2( ef+hw ) );
                    kf = sqrt( UCC->EtoK2( ef ));
                }
                Double qx = -kf*px;
                Double qy = -kf*py;
                Double qz = ki-kf*pz;

                vx->at(cnt) = (float)(qx*A[0] + qy*A[1] + qz*A[2] + hw*A[3]);
                vy->at(cnt) = (float)(qx*A[4] + qy*A[5] + qz*A[6] + hw*A[7]);
                vz->at(cnt) = (float)(qx*A[8] + qy*A[9] + qz*A[10] + hw*A[11]);
                vw->at(cnt) = (float)(qx*A[12] + qy*A[13] + qz*A[14] + hw*A[15]);
                cnt++;
            }
        }
    }
    delete vc;
    delete UCC;
    AxLimit.clear();
    UtsusemiMessage( MessageTag+"Projection end. ");
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
Projection( UInt4 ind, std::vector<Double> viewAxis ){
    if (ind>=_D4mat->PutSize()){
        std::string msg = MessageTag+"Projection > given index is too large for ths size of inner D4mat data : ";
        msg += ("ind = " + _stools->UInt4ToString(ind) + "/" + _stools->UInt4ToString(_D4mat->PutSize()));
        UtsusemiError(msg);
        return false;
    }
    if (_D4mat->PutPointer(ind)->Energy->empty()){
        std::string msg = MessageTag+"Projection > Energy bin size of inner D4mat data is zero.";
        UtsusemiError(msg);
        return false;
    }
    _viewAxis.clear();
    _viewAxis.resize(viewAxis.size());
    copy(viewAxis.begin(), viewAxis.end(), _viewAxis.begin());

    if (isMemSaveMode){
        UtsusemiMessage( MessageTag+"Projection : Memory-Saving mode. ");
        return true;
    }
    std::vector<Double> LatticeConsts = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS);
    std::vector<Double> Uvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_UVECT);
    std::vector<Double> Vvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_VVECT);
    std::vector<Double> Rvec = _HH->PutDoubleVector(UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS);

    UtsusemiSqeCalc2* vc = new UtsusemiSqeCalc2();
    UtsusemiUnitConverter* UCC = new UtsusemiUnitConverter();
    Double Ei = 0.0;
    Double ki = 0.0;
    Double kf = 0.0;

    if (_D4mat->PutPointer(ind)==NULL) return true;
    D4MatOne* ec = _D4mat->PutPointer(ind);
    HeaderBase* hh = ec->PutHeaderPointer();
    std::vector<Double> rv( Rvec.size() );
    copy( Rvec.begin(), Rvec.end(), rv.begin() );
    rv.push_back(1);
    rv.push_back(hh->PutDouble( ec->D4MAT2ANGLE ));
    std::vector<Double> A = vc->MakeProjectionMatrix( LatticeConsts, Uvec, Vvec, rv, viewAxis );

    std::vector<float>* vhw = ec->Energy;
    std::vector<float>* vx = NULL;
    std::vector<float>* vy = NULL;
    std::vector<float>* vz = NULL;
    std::vector<float>* vw = NULL;
    if (ec->Vx->empty()) ec->Vx->resize( vhw->size(), 0.0 );
    else{
        delete ec->Vx;
        ec->Vx = new std::vector<float>( vhw->size(), 0.0 );
    }
    if (ec->Vy->empty()) ec->Vy->resize( vhw->size(), 0.0 );
    else{
        delete ec->Vy;
        ec->Vy = new std::vector<float>( vhw->size(), 0.0 );
    }
    if (ec->Vz->empty()) ec->Vz->resize( vhw->size(), 0.0 );
    else{
        delete ec->Vz;
        ec->Vz = new std::vector<float>( vhw->size(), 0.0 );
    }
    if (ec->Vw->empty()) ec->Vw->resize( vhw->size(), 0.0 );
    else{
        delete ec->Vw;
        ec->Vw = new std::vector<float>( vhw->size(), 0.0 );
    }
    vx = ec->Vx;
    vy = ec->Vy;
    vz = ec->Vz;
    vw = ec->Vw;

    if (isDirectGeometry){
        Ei = hh->PutDouble(UTSUSEMI_KEY_HEAD_EI);
        ki = sqrt( UCC->EtoK2( Ei ) );
    }

    std::vector<float>* PA = ec->PolarAngles;
    std::vector<float>* AA = ec->AzimAngles;
    std::vector<float>* Ef = ec->EFs;

    UInt4 nPix = hh->PutInt4( ec->D4MAT2NUMOFPIXELS );
    UInt4 cnt = 0;
    UInt4 numOfhw = (UInt4)(vhw->size())/nPix;
    for (UInt4 iPix=0; iPix<nPix; iPix++){
        Double px = sin(PA->at(iPix))*cos(AA->at(iPix));
        Double py = sin(PA->at(iPix))*sin(AA->at(iPix));
        Double pz = cos(PA->at(iPix));
        Double ef = 0;
        if ((!Ef->empty()) && (Ef->at(0) != 0.0)) ef = Ef->at(iPix);
        //if (!(Ef->empty())) ef=(Ef->at(iPix));
        for (UInt4 j=0; j<numOfhw; j++){
            Double hw = vhw->at(numOfhw*iPix+j);
            if (isDirectGeometry){
                kf = sqrt( UCC->EtoK2( Ei-hw ) );
            }else{
                ki = sqrt( UCC->EtoK2( ef+hw ) );
                kf = sqrt( UCC->EtoK2( ef ));
            }
            Double qx = -kf*px;
            Double qy = -kf*py;
            Double qz = ki-kf*pz;

            vx->at(cnt) = (float)(qx*A[0] + qy*A[1] + qz*A[2] + hw*A[3]);
            vy->at(cnt) = (float)(qx*A[4] + qy*A[5] + qz*A[6] + hw*A[7]);
            vz->at(cnt) = (float)(qx*A[8] + qy*A[9] + qz*A[10] + hw*A[11]);
            vw->at(cnt) = (float)(qx*A[12] + qy*A[13] + qz*A[14] + hw*A[15]);
            cnt++;
        }
    }
    delete vc;
    delete UCC;
    AxLimit.clear();
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
Projection( PyObject* viewAxis ){
    if (!PyList_Check(viewAxis)){
        UtsusemiError( MessageTag + "Projection >> arguments must be python-list" );
        return false;
    }
    std::vector<Double> vav = __gCppToPython.ListToDoubleVector( viewAxis );
    if ((vav.empty())||(vav.size()!=16)){
        UtsusemiError( MessageTag + "Projection >> Arguments viewAxis must be list with size of 16" );
        return false;
    }
    return Projection( vav );
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
Projection(){
    if (_HH->CheckKey("ProjectionAxes") == 0){
        UtsusemiError( MessageTag + "Projection >> Projection Axes must be set by SetD4MatProjectionAxes or use Projection(<vect>)." );
        return false;
    }
    return Projection(_HH->PutDoubleVector("ProjectionAxes"));
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
ExportEcmFromStepByStep(ElementContainerMatrix* ecm, UInt4 index){
    if (index>=(_D4mat->PutSize())) return false;
    HeaderBase *hh_arr = _D4mat->PutPointer(0)->PutHeaderPointer();
    ecm->InputHeader( *hh_arr );
    D4MatOne* ec = _D4mat->PutPointer(index);
    HeaderBase* hh = ec->PutHeaderPointer();
    Double phi = hh->PutDouble(ec->D4MAT2ANGLE);

    std::vector<float>* vhw = ec->Energy;
    std::vector<float>* II = ec->Intensity;
    std::vector<float>* EE = ec->Error;
    std::vector<float>* PA = ec->PolarAngles;
    std::vector<float>* AA = ec->AzimAngles;
    std::vector<float>* L2 = ec->L2;
    std::vector<float>* PAd = NULL;
    std::vector<float>* AAd = NULL;
    std::vector<float>* Ef = ec->EFs;
    if (isDirectGeometry){
        PAd = ec->PolarAnglesW;
        AAd = ec->AzimAnglesW;
    }
    UInt4 nPix = hh->PutInt4( ec->D4MAT2NUMOFPIXELS );

    UInt4 numOfhw = (UInt4)(vhw->size())/nPix;

    ecm->Allocate(1);
    ElementContainerArray* eca = new ElementContainerArray();
    eca->Allocate(nPix);

    std::vector<float> hw(numOfhw+1,0.0);
    hw[0] = (float)( (vhw->at(0)) - ( (vhw->at(1))-(vhw->at(0)) )/2.0 );
    for (UInt4 i=0; i<numOfhw-1; i++)
        hw[i+1] = (float)( ( (vhw->at(i)) + (vhw->at(i+1)) )/2.0 );
    hw[numOfhw] = (float)( (vhw->at(numOfhw-1)) + ((vhw->at(numOfhw-1)) - (vhw->at(numOfhw-2)))/2.0 );
    for (UInt4 iPix=0; iPix<nPix; iPix++){
        ElementContainer* ret_ec = new ElementContainer();
        std::vector<Double> ii(numOfhw,0.0);
        std::vector<Double> ee(numOfhw,0.0);
        copy( II->begin()+(iPix*numOfhw), II->begin()+(iPix+1)*numOfhw, ii.begin() );
        copy( EE->begin()+(iPix*numOfhw), EE->begin()+(iPix+1)*numOfhw, ee.begin() );
        ret_ec->Add( UTSUSEMI_KEY_ENERGY, hw, UTSUSEMI_KEY_ENERGY_UNIT );
        ret_ec->Add( UTSUSEMI_KEY_INTENSITY, ii, UTSUSEMI_KEY_COUNTS_UNIT );
        ret_ec->Add( UTSUSEMI_KEY_ERROR, ee, UTSUSEMI_KEY_COUNTS_UNIT );
        ret_ec->SetKeys(UTSUSEMI_KEY_ENERGY,UTSUSEMI_KEY_INTENSITY,UTSUSEMI_KEY_ERROR);

        ret_ec->AddToHeader(UTSUSEMI_KEY_HEAD_MASKED,0 );
        ret_ec->AddToHeader("NormByBinWidth",1 );
        std::vector<Double> vPP(3,0.0);
        std::vector<Double> vPA(2,1.0);
        std::vector<Double> vAA(2,1.0);
        vPP[0] = L2->at(iPix)*sin(PA->at(iPix))*cos(AA->at(iPix));
        vPP[1] = L2->at(iPix)*sin(PA->at(iPix))*sin(AA->at(iPix));
        vPP[2] = L2->at(iPix)*cos(PA->at(iPix));
        vPA[0] = (PA->at(iPix))/M_PI*180.0;
        vAA[0] = (AA->at(iPix))/M_PI*180.0;
        if (isDirectGeometry){
            vPA[1] = (PAd->at(iPix))/M_PI*180.0;
            vAA[1] = (AAd->at(iPix))/M_PI*180.0;
        }else{
            ret_ec->AddToHeader( UTSUSEMI_KEY_HEAD_POLARANGLE, vPA[0] );
            ret_ec->AddToHeader( UTSUSEMI_KEY_HEAD_AZIMANGLE, vAA[0] );
            ret_ec->AddToHeader( UTSUSEMI_KEY_HEAD_EF, Ef->at(iPix) );
        }
        ret_ec->AddToHeader( UTSUSEMI_KEY_HEAD_PIXELPOSITION, vPP );
        ret_ec->AddToHeader( UTSUSEMI_KEY_HEAD_PIXELPOLARANGLES, vPA );
        ret_ec->AddToHeader( UTSUSEMI_KEY_HEAD_PIXELAZIMANGLES, vAA );
        eca->Set( iPix, ret_ec );
    }
    ecm->Set(0, eca);

    if (ecm->PutHeaderPointer()->CheckKey(ec->D4MAT2ANGLE)==1)
        ecm->PutHeaderPointer()->OverWrite( ec->D4MAT2ANGLE,phi);
    else
        ecm->AddToHeader( ec->D4MAT2ANGLE,phi);

    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
LoadData(std::string filepath)
{
    ResetD4mat();
    if (_D4mat->Load(filepath)){
        if (_XP->DecodeFromXml(_D4mat->_XtalParam, _XP->TOXML_ALL)){
            Int4 ret = SetCrystalParametersToHeader(_HH, _XP->PutLatticeConsts(), _XP->PutUVector(), _XP->PutVVector(), _XP->PutRotateSteps());
            if (ret != 0) {
                UtsusemiError(MessageTag + "LoadData >> Failes load XtalParam infor from file :" + filepath);
                return false;
            }
            if (SetD4MatProjectionAxesInfo(_XP->PutViewAxes())){
            }else{
                UtsusemiError(MessageTag + "LoadData >> Failes load viewAxes of XtalParam infor from file :" + filepath);
                return false;
            }
            if (_TP->ImportXmlString(_D4mat->_XtalParam, true)){
                _HH->Add("D4MAT2MODE", (Int4)(_TP->mode));
                std::vector<Double> p;
                p.push_back(_TP->timeSlice0);
                p.push_back(_TP->timeSlice1);
                p.push_back(_TP->ei);
                p.push_back(_TP->energyBin);
                p.push_back(_TP->energyMin);
                p.push_back(_TP->energyMax);
                p.push_back(_TP->angleMin);
                p.push_back(_TP->angleMax);
                p.push_back(_TP->angleStep);
                _HH->Add("DATAREDPARAM", p);
                UtsusemiMessage("LoadData succeeded.", true);
                // _HH->Dump();
                return true;
            }
        }
    }
    UtsusemiError(MessageTag + "LoadData >> Failed file open : " + filepath);
    return false;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SaveData(std::string filepath, bool withComp)
{
    _D4mat->_XtalParam = MakeXmlStringFromHeader( _HH );
    return _D4mat->Save(filepath, withComp);
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
SaveXtalParam(std::string filepath)
{
    _D4mat->_XtalParam = MakeXmlStringFromHeader( _HH );
    BoostXmlParser BX(_D4mat->_XtalParam);
    return BX.Save(filepath);
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
DumpAllDataPoints(std::string filepath)
{
    return _D4mat->DumpSqeAsText(filepath);
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
PutSlicedD4MatrixToText(std::string filepath, std::vector<Double> ax1range, std::vector<Double> ax2range, std::vector<Double> ax3range, std::vector<Double> ax4range, std::vector<Double> folding, bool isAve )
{
    FILE* fp;
    if ((fp=fopen(filepath.c_str(),"w"))==NULL){
        UtsusemiError("ERROR to open the given file path : "+filepath);
        return false;
    }
    if (MakeSlicedD4MatrixInner( ax1range, ax2range, ax3range, ax4range, folding)){
        // Output as TEXT file
        if (isAve){
            for (UInt4 i=0;i<_n_XArray4;i++){
                for (UInt4 j=0;j<_n_YArray4;j++){
                    for (UInt4 k=0;k<_n_ZArray4;k++){
                        for (UInt4 l1=0;l1<_n_TArray4;l1++){
                            Double ii = 0.0;
                            Double ee = 0.0;
                            Double cc = 0.0;
                            for (UInt4 th=0;th<_NumOfMulTh;th++){
                                ii += (Double)dArray4[th][i][j][k][l1];
                                ee += (Double)eArray4[th][i][j][k][l1];
                                cc += (Double)cArray4[th][i][j][k][l1];
                            }
                            if (cc != 0.0){
                                ii /= cc;
                                ee = sqrt(ee)/cc;
                            }else{
                                ee = UTSUSEMIMASKERRORVALUE;
                            }
                            char line_c[200];
                            std::snprintf( line_c, sizeof(line_c), "%g, %g, %g, %g, %g, %g", _XbinArray4[i], _YbinArray4[j], _ZbinArray4[k], _TbinArray4[l1], ii, ee);
                            std::string a_line(line_c);
                           std::fprintf( fp, "%s\n", a_line.c_str() );
                        }
                    }
                }
            }
        }else{
            for (UInt4 i=0;i<_n_XArray4;i++){
                for (UInt4 j=0;j<_n_YArray4;j++){
                    for (UInt4 k=0;k<_n_ZArray4;k++){
                        for (UInt4 l1=0;l1<_n_TArray4;l1++){
                            Double ii = 0.0;
                            Double ee = 0.0;
                            Double cc = 0.0;
                            for (UInt4 th=0;th<_NumOfMulTh;th++){
                                ii += (Double)dArray4[th][i][j][k][l1];
                                ee += (Double)eArray4[th][i][j][k][l1];
                                cc += (Double)cArray4[th][i][j][k][l1];
                            }
                            if (cc != 0.0) ee = sqrt(ee);
                            else ee = UTSUSEMIMASKERRORVALUE;
                            char line_c[200];
                            std::snprintf( line_c, sizeof(line_c), "%g, %g, %g, %g, %g, %g", _XbinArray4[i], _YbinArray4[j], _ZbinArray4[k], _TbinArray4[l1], ii, ee);
                            std::string a_line(line_c);
                           std::fprintf( fp, "%s\n", a_line.c_str() );
                        }
                    }
                }
            }
        }
    }else{
        fclose( fp );
        return false;
    }
    fclose( fp );
    ClearSlicedD4MatrixInner();
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
PutSlicedD4MatrixToVectors(std::vector<Double> *ax1, std::vector<Double> *ax2, std::vector<Double> *ax3, std::vector<Double> *ax4, std::vector<Double> *intensity, std::vector<Double> *error, bool isAve)
{
    if ((dArray4 == NULL) || (eArray4 == NULL)){
        return false;
    }
    ax1 -> clear();
    ax2 -> clear();
    ax3 -> clear();
    ax4 -> clear();
    intensity -> clear();
    error -> clear();

    ax1 -> resize(_n_XArray4);
    ax2 -> resize(_n_YArray4);
    ax3 -> resize(_n_ZArray4);
    ax4 -> resize(_n_TArray4);
    intensity -> resize(_n_XArray4 * _n_YArray4 * _n_ZArray4 * _n_TArray4);
    error -> resize(_n_XArray4 * _n_YArray4 * _n_ZArray4 * _n_TArray4);

    copy(_XbinArray4.begin(), _XbinArray4.end(), ax1 -> begin());
    copy(_YbinArray4.begin(), _YbinArray4.end(), ax2 -> begin());
    copy(_ZbinArray4.begin(), _ZbinArray4.end(), ax3 -> begin());
    copy(_TbinArray4.begin(), _TbinArray4.end(), ax4 -> begin());

    UInt4 ind = 0;
    if (isAve){
        for (UInt4 i=0;i<_n_XArray4;i++){
            for (UInt4 j=0;j<_n_YArray4;j++){
                for (UInt4 k=0;k<_n_ZArray4;k++){
                    for (UInt4 l1=0;l1<_n_TArray4;l1++){
                        Double ii = 0.0;
                        Double ee = 0.0;
                        Double cc = 0.0;
                        for (UInt4 th=0;th<_NumOfMulTh;th++){
                            ii += Double(dArray4[th][i][j][k][l1]);
                            ee += Double(eArray4[th][i][j][k][l1]);
                            cc += Double(cArray4[th][i][j][k][l1]);
                        }
                        if (cc != 0.0){
                            intensity -> at(ind) = ii / cc;
                            error -> at(ind) = sqrt(ee) / cc;
                        }else{
                            error -> at(ind) = UTSUSEMIMASKERRORVALUE;
                        }
                        ind ++;
                    }
                }
            }
        }
    }else{
        for (UInt4 i=0;i<_n_XArray4;i++){
            for (UInt4 j=0;j<_n_YArray4;j++){
                for (UInt4 k=0;k<_n_ZArray4;k++){
                    for (UInt4 l1=0;l1<_n_TArray4;l1++){
                        Double ii = 0.0;
                        Double ee = 0.0;
                        Double cc = 0.0;
                        for (UInt4 th=0;th<_NumOfMulTh;th++){
                            ii += Double(dArray4[th][i][j][k][l1]);
                            ee += Double(eArray4[th][i][j][k][l1]);
                            cc += Double(cArray4[th][i][j][k][l1]);
                        }
                        if (cc != 0.0){
                            intensity -> at(ind) = ii;
                            error -> at(ind) = sqrt(ee);
                        }else{
                            error -> at(ind) = UTSUSEMIMASKERRORVALUE;
                        }
                        ind ++;
                    }
                }
            }
        }
    }
    std::cout << "PutSlicedD4MatrixToVectors::";
    for (UInt4 i=0; i<(ax1->size()); i++) std::cout << ax1->at(i) << ", ";
    std::cout << std::endl;
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4Matrix2::
MakeSlicedD4MatrixInner( std::vector<Double> ax1range, std::vector<Double> ax2range, std::vector<Double> ax3range, std::vector<Double> ax4range, std::vector<Double> folding)
{
    std::vector<Double> xrange = CalcRangeAsBinCenterZero(ax1range[0], ax1range[1], ax1range[2]);
    std::vector<Double> yrange = CalcRangeAsBinCenterZero(ax2range[0], ax2range[1], ax2range[2]);
    std::vector<Double> zrange = CalcRangeAsBinCenterZero(ax3range[0], ax3range[1], ax3range[2]);
    std::vector<Double> trange = CalcRangeAsBinCenterZero(ax4range[0], ax4range[1], ax4range[2]);
    std::vector<Double> xbin;
    std::vector<Double> ybin;
    std::vector<Double> zbin;
    std::vector<Double> tbin;
    Double xbin_width = ax1range[2];
    Double ybin_width = ax2range[2];
    Double zbin_width = ax3range[2];
    Double tbin_width = ax4range[2];
    for (Double x=xrange[0];x<=xrange[1];x+=xbin_width) xbin.push_back( x );
    for (Double y=yrange[0];y<=yrange[1];y+=ybin_width) ybin.push_back( y );
    for (Double z=zrange[0];z<=zrange[1];z+=zbin_width) zbin.push_back( z );
    for (Double t=trange[0];t<=trange[1];t+=tbin_width) tbin.push_back( t );
    UInt4 n_X = (UInt4)( xrange[2] );
    UInt4 n_Y = (UInt4)( yrange[2] );
    UInt4 n_Z = (UInt4)( zrange[2] );
    UInt4 n_T = (UInt4)( trange[2] );
    //std::cout << "yrange=" << yrange[0] << "," << yrange[1] << "," << yrange[2] << std::endl;

    //float *****dArray4, *****eArray4, *****cArray4;
    dArray4 = new float****[ _NumOfMulTh ];
    eArray4 = new float****[ _NumOfMulTh ];
    cArray4 = new float****[ _NumOfMulTh ];
    for (UInt4 i=0;i<_NumOfMulTh;i++){
        dArray4[i] = new float***[ n_X ];
        eArray4[i] = new float***[ n_X ];
        cArray4[i] = new float***[ n_X ];

        for (UInt4 j=0;j<n_X;j++){
            dArray4[i][j] = new float**[ n_Y ];
            eArray4[i][j] = new float**[ n_Y ];
            cArray4[i][j] = new float**[ n_Y ];

            for (UInt4 k=0;k<n_Y;k++){
                dArray4[i][j][k] = new float*[ n_Z ];
                eArray4[i][j][k] = new float*[ n_Z ];
                cArray4[i][j][k] = new float*[ n_Z ];

                for (UInt4 l1=0;l1<n_Z;l1++){
                    dArray4[i][j][k][l1] = new float[ n_T ];
                    eArray4[i][j][k][l1] = new float[ n_T ];
                    cArray4[i][j][k][l1] = new float[ n_T ];
                }
            }
        }
    }

    for (UInt4 i=0;i<_NumOfMulTh;i++){
        for (UInt4 j=0;j<n_X;j++){
            for (UInt4 k=0;k<n_Y;k++){
                for (UInt4 l1=0;l1<n_Z;l1++){
                    for (UInt4 l2=0;l2<n_T;l2++){
                        dArray4[i][j][k][l1][l2]=eArray4[i][j][k][l1][l2]=cArray4[i][j][k][l1][l2]=0.0;
                    }
                }
            }
        }
    }

    for (UInt4 runId=0;runId<_D4mat->PutSize();runId++){
        D4MatOne* ec_D4mat = _D4mat->data->at(runId);
        std::vector<std::vector<float>*> ax(4);
        if (isMemSaveMode){
            ax[0] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            ax[1] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            ax[2] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            ax[3] = new std::vector<float>(ec_D4mat->Energy->size(), 0.0);
            _putQvectorsFromData(ec_D4mat, ax[0], ax[1], ax[2], ax[3]);
        }else{
            ax[0] = ec_D4mat->Vx;
            ax[1] = ec_D4mat->Vy;
            ax[2] = ec_D4mat->Vz;
            ax[3] = ec_D4mat->Vw;
        }
        std::vector<float>* ii = ec_D4mat->Intensity;
        std::vector<float>* ee = ec_D4mat->Error;
        //std::cout << "@@@ runId=" << runId << std::endl;
#ifdef MULTH
        omp_set_num_threads( _NumOfMulTh );
#pragma omp parallel for
#if (_OPENMP >= 200805)  // OpenMP 3.0 and later
        for (UInt4 ind=0;ind<ax[0]->size();ind++){
#else
        for (Int4 ind=0;ind<ax[0]->size();ind++){
#endif
            UInt4 multh = omp_get_thread_num();
            Double X = ax[0]->at(ind);
            if (folding[0]==0.0) X = fabs(X);
            if (folding[0]>0.0) X = fabs(X) - (floor(fabs(X)/folding[0])*folding[0]);
            Double Y = ax[1]->at(ind);
            if (folding[1]==0.0) Y = fabs(Y);
            if (folding[1]>0.0) Y = fabs(Y) - (floor(fabs(Y)/folding[1])*folding[1]);
            Double Z = ax[2]->at(ind);
            if (folding[2]==0.0) Z = fabs(Z);
            if (folding[2]>0.0) Z = fabs(Z) - (floor(fabs(Z)/folding[2])*folding[2]);
            Double T = ax[3]->at(ind);
            if (folding[3]==0.0) T = fabs(T);
            if (folding[3]>0.0) T = fabs(T) - (floor(fabs(T)/folding[3])*folding[3]);

            if ((trange[0]<=T)&&(T<trange[1])){
                if ((xrange[0]<=X)&&(X<=xrange[1])){
                    if ((yrange[0]<=Y)&&(Y<=yrange[1])){
                        if ((zrange[0]<=Z)&&(Z<=zrange[1])){
                            UInt4 i_X = (UInt4)( (X-xrange[0])/xbin_width );
                            UInt4 i_Y = (UInt4)( (Y-yrange[0])/ybin_width );
                            UInt4 i_Z = (UInt4)( (Z-zrange[0])/zbin_width );
                            UInt4 i_T = (UInt4)( (T-trange[0])/tbin_width );

                            if ((ee->at(ind))>=0.0){
                                dArray4[multh][i_X][i_Y][i_Z][i_T] += (ii->at(ind));
                                eArray4[multh][i_X][i_Y][i_Z][i_T] += (ee->at(ind))*(ee->at(ind));
                                cArray4[multh][i_X][i_Y][i_Z][i_T] += 1.0;
                            }
                        }
                    }
                }
            }
        }
        if (isMemSaveMode){
            delete ax[0];
            delete ax[1];
            delete ax[2];
            delete ax[3];
        }
#else
        for (UInt4 ind=0;ind<ax[0]->size();ind++){
            Double X = ax[0]->at(ind);
            if (folding[0]==0.0) X = fabs(X);
            if (folding[0]>0.0) X = fabs(X) - (floor(fabs(X)/folding[0])*folding[0]);
            Double Y = ax[1]->at(ind);
            if (folding[1]==0.0) Y = fabs(Y);
            if (folding[1]>0.0) Y = fabs(Y) - (floor(fabs(Y)/folding[1])*folding[1]);
            Double Z = ax[2->at(ind);
            if (folding[2]==0.0) Z = fabs(Z);
            if (folding[2]>0.0) Z = fabs(Z) - (floor(fabs(Z)/folding[2])*folding[2]);
            Double T = ax[3]->at(ind);
            if (folding[3]==0.0) T = fabs(T);
            if (folding[3]>0.0) T = fabs(T) - (floor(fabs(T)/folding[3])*folding[3]);

            if ((trange[0]<=T)&&(T<trange[1])){
                if ((xrange[0]<=X)&&(X<=xrange[1])){
                    if ((yrange[0]<=Y)&&(Y<=yrange[1])){
                        if ((zrange[0]<=Z)&&(Z<=zrange[1])){
                            UInt4 i_X = (UInt4)( (X-xrange[0])/xbin_width );
                            UInt4 i_Y = (UInt4)( (Y-yrange[0])/ybin_width );
                            UInt4 i_Z = (UInt4)( (Z-yrange[0])/zbin_width );
                            UInt4 i_T = (UInt4)( (T-trange[0])/tbin_width );

                            if ((ee->at(ind))>=0.0){
                                dArray4[0][i_X][i_Y][i_Z][i_T] += (ii->at(ind));
                                eArray4[0][i_X][i_Y][i_Z][i_T] += (ee->at(ind))*(ee->at(ind));
                                cArray4[0][i_X][i_Y][i_Z][i_T] += 1.0;
                            }
                        }
                    }
                }
            }
        }
#endif
    }

    _n_XArray4 = n_X;
    _n_YArray4 = n_Y;
    _n_ZArray4 = n_Z;
    _n_TArray4 = n_T;

    _XbinArray4.clear();
    _YbinArray4.clear();
    _ZbinArray4.clear();
    _TbinArray4.clear();
    _XbinArray4.resize(n_X);
    _YbinArray4.resize(n_Y);
    _ZbinArray4.resize(n_Z);
    _TbinArray4.resize(n_T);
    if ((n_X + 1) == xbin.size()){
        for (UInt4 i=0; i<n_X; i++) _XbinArray4[i] = (xbin[i] + xbin[i + 1]) / 2.0;
    }else if (n_X == xbin.size()){
        copy(xbin.begin(), xbin.end(), _XbinArray4.begin());
    }else{
        return false;
    }
    if ((n_Y + 1) == ybin.size()){
        for (UInt4 i=0; i<n_Y; i++) _YbinArray4[i] = (ybin[i] + ybin[i + 1]) / 2.0;
    }else if (n_Y == ybin.size()){
        copy(ybin.begin(), ybin.end(), _YbinArray4.begin());
    }else{
        return false;
    }
    if ((n_Z + 1) == zbin.size()){
        for (UInt4 i=0; i<n_Z; i++) _ZbinArray4[i] = (zbin[i] + zbin[i + 1]) / 2.0;
    }else if (n_Z == zbin.size()){
        copy(zbin.begin(), zbin.end(), _ZbinArray4.begin());
    }else{
        return false;
    }
    if ((n_T + 1) == tbin.size()){
        for (UInt4 i=0; i<n_T; i++) _TbinArray4[i] = (tbin[i] + tbin[i + 1]) / 2.0;
    }else if (n_T == tbin.size()){
        copy(tbin.begin(), tbin.end(), _TbinArray4.begin());
    }else{
        return false;
    }

    if (UtsusemiEnvGetDebugMode()){
        std::cout << "MakeSlicedD4MatrixInner ::"<<std::endl;
        std::cout << "_n  = " << n_X << ", " << n_Y << ", " << n_Z << ", " << n_T << std::endl;
        std::cout << "bin = " << xbin.size() << ", " << ybin.size() << ", " << zbin.size() << ", " << tbin.size() << std::endl;
        std::cout << "_XbinArray4 = ";
        for (UInt4 i=0; i < _XbinArray4.size(); i++) std::cout << _XbinArray4[i] << ", ";
        std::cout << std::endl;
    }
    return true;
}
void UtsusemiD4Matrix2::ClearSlicedD4MatrixInner(){
    if (dArray4 != NULL){
        for (UInt4 th=0;th<_NumOfMulTh;th++){
            for (UInt4 i=0;i<_n_XArray4;i++){
                for (UInt4 j=0;j<_n_YArray4;j++){
                    for (UInt4 k=0;k<_n_ZArray4;k++){
                        delete [] dArray4[th][i][j][k];
                    }
                    delete [] dArray4[th][i][j];
                }
                delete [] dArray4[th][i];
            }
            delete [] dArray4[th];
        }
        delete [] dArray4;
        dArray4 = NULL;
    }
    if (eArray4 != NULL){
        for (UInt4 th=0;th<_NumOfMulTh;th++){
            for (UInt4 i=0;i<_n_XArray4;i++){
                for (UInt4 j=0;j<_n_YArray4;j++){
                    for (UInt4 k=0;k<_n_ZArray4;k++){
                        delete [] eArray4[th][i][j][k];
                    }
                    delete [] eArray4[th][i][j];
                }
                delete [] eArray4[th][i];
            }
            delete [] eArray4[th];
        }
        delete [] eArray4;
        eArray4 = NULL;
    }
    if (cArray4 != NULL){
        for (UInt4 th=0;th<_NumOfMulTh;th++){
            for (UInt4 i=0;i<_n_XArray4;i++){
                for (UInt4 j=0;j<_n_YArray4;j++){
                    for (UInt4 k=0;k<_n_ZArray4;k++){
                        delete [] cArray4[th][i][j][k];
                    }
                    delete [] cArray4[th][i][j];
                }
                delete [] cArray4[th][i];
            }
            delete [] cArray4[th];
        }
        delete [] cArray4;
        cArray4 = NULL;
    }
    _n_XArray4 = 0;
    _n_YArray4 = 0;
    _n_ZArray4 = 0;
    _n_TArray4 = 0;

    _XbinArray4.clear();
    _YbinArray4.clear();
    _ZbinArray4.clear();
    _TbinArray4.clear();

}
