#include "UtsusemiD4MatOnMem.hh"
//////////////////////////////////////////////////////////////////////
UtsusemiD4MatOnMem::
UtsusemiD4MatOnMem(){
    _Initialize();
}
//////////////////////////////////////////////////////////////////////
UtsusemiD4MatOnMem::
~UtsusemiD4MatOnMem(){
    _Clear();
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4MatOnMem::
_Initialize(){        
    MessageTag = "UtsusemiD4MatOnMem::";
    
    //MASKVALUE=100000000.0;
    MASKVALUE = UTSUSEMIMASKVALUE64;
    _D4mat = new ElementContainerArray();
    _HH = new HeaderBase();
    
    _NumOfMulTh = UtsusemiGetNumOfMulTh();
    _stools = new StringTools();
    isDirectGeometry = true;
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4MatOnMem::
_Clear(){
    
    delete _D4mat;
    delete _HH;
    delete _stools;
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4MatOnMem::
ResetD4mat(){
    
    _Clear();
    _D4mat = new ElementContainerArray();
    _HH = new HeaderBase();
    _stools = new StringTools();
}

//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
SetCrystalParameters( ElementContainerMatrix* ecm, vector<Double> LatticeConsts, vector<Double> Uvec, vector<Double> Vvec, vector<Double> Rvec, Double phi ){
    
    if (LatticeConsts.size()!=6){
        UtsusemiError( MessageTag + "Invalid argument for LatticeConsts" );
        return -1;
    }
    if (Uvec.size()!=3){
        UtsusemiError( MessageTag + "Invalid argument for U vector" );
        return -1;
    }
    if (Vvec.size()!=3){
        UtsusemiError( MessageTag + "Invalid argument for V vector" );
        return -1;
    }
    HeaderBase* hh = ecm->PutHeaderPointer();
    
    SetCrystalParametersToHeader( hh, LatticeConsts, Uvec, Vvec, Rvec );
    vector<Double> SampleRotateSteps( Rvec );
    SampleRotateSteps.push_back( 1.0 ); // Y-axis for rotation (phi)
    SampleRotateSteps.push_back( phi );
    if (hh->CheckKey("SampleRotateSteps")==1){
        hh->OverWrite("SampleRotateSteps", SampleRotateSteps);
    }else{
        hh->Add("SampleRotateSteps", SampleRotateSteps);
    }
    /*
    if (hh->CheckKey("SampleRotatePhi")==1){
        hh->OverWrite("SampleRotatePhi", phi);
    }else{
        hh->Add("SampleRotatePhi", phi);
    }
    */
    return 0;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4MatOnMem::
SetCrystalParameters( ElementContainerMatrix* ecm, PyObject* LatticeConsts, PyObject* Uvec, PyObject* Vvec, PyObject* Rvec, Double phi ){
    if ((!PyList_Check(LatticeConsts))||(!PyList_Check(Uvec))||(!PyList_Check(Vvec))||(!PyList_Check(Rvec))){
        UtsusemiError( MessageTag + "SetCrystalParameters >> arguments must be python-list" );
        return false;
    }
    vector<Double> lcv = __gCppToPython.ListToDoubleVector( LatticeConsts );
    if ((lcv.empty())||(lcv.size()!=6)){
        UtsusemiError( MessageTag + "SetCrystalParameters >> Arguments LatticeConstants must be list with size of 6" );
        return false;
    }
    vector<Double> uvv = __gCppToPython.ListToDoubleVector( Uvec );
    if ((uvv.empty())||(uvv.size()!=3)){
        UtsusemiError( MessageTag + "SetCrystalParameters >> Arguments Uvec must be list with size of 3" );
        return false;
    }
    vector<Double> vvv = __gCppToPython.ListToDoubleVector( Vvec );
    if ((vvv.empty())||(vvv.size()!=3)){
        UtsusemiError( MessageTag + "SetCrystalParameters >> Arguments Vvec must be list with size of 3" );
        return false;
    }
    vector<Double> rvv = __gCppToPython.ListToDoubleVector( Rvec );
    Int4 ret = SetCrystalParameters( ecm, lcv, uvv, vvv, rvv, phi );
    if (ret==0) return true;
    else return false;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
SetCrystalParametersToHeader( HeaderBase* head, vector<Double> LatticeConsts, vector<Double> Uvec, vector<Double> Vvec, vector<Double> Rvec ){
    if (head->CheckKey("SimpleLatticeConsts")==1){
        head->OverWrite("SimpleLatticeConsts",LatticeConsts);
    }else{
        head->Add("SimpleLatticeConsts",LatticeConsts);
    }
    if (head->CheckKey("SampleUvec")==1){
        head->OverWrite("SampleUvec",Uvec);
    }else{
        head->Add("SampleUvec",Uvec);
    }
    if (head->CheckKey("SampleVvec")==1){
        head->OverWrite("SampleVvec",Vvec);
    }else{
        head->Add("SampleVvec",Vvec);
    }
    if (head->CheckKey("SampleRotateSteps")==1){
        head->OverWrite("SampleRotateSteps",Rvec);
    }else{
        head->Add("SampleRotateSteps",Rvec);
    }
    
    return 0;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
SetD4MatParameters( Int4 runNo, vector<Double> dataRedParam,vector<Double> LatticeConsts, vector<Double> Uvec, vector<Double> Vvec, vector<Double> Rvec){
    if (_HH->CheckKey(UTSUSEMI_KEY_HEAD_RUNNUMBER)==1)
        _HH->OverWrite(UTSUSEMI_KEY_HEAD_RUNNUMBER,runNo);
    else
        _HH->Add(UTSUSEMI_KEY_HEAD_RUNNUMBER,runNo);
    
    if (dataRedParam.size()!=9){
        UtsusemiError( MessageTag + " SetD4MatParameters >> data reductio parameter is invalid." );
        return -1;
    }
    
    if (_HH->CheckKey("DATAREDPARAM")==1)
        _HH->OverWrite("DATAREDPARAM",dataRedParam);
    else
        _HH->Add("DATAREDPARAM",dataRedParam);
    
    SetCrystalParametersToHeader( _HH, LatticeConsts, Uvec, Vvec, Rvec );
    _D4mat->InputHeader( (*_HH) );
    
    return 0;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4MatOnMem::
SetD4MatParameters( Int4 runNo, PyObject* dataRedParam, PyObject* LatticeConsts, PyObject* Uvec, PyObject* Vvec, PyObject* Rvec){
    if ((!PyList_Check(LatticeConsts))||(!PyList_Check(Uvec))||(!PyList_Check(Vvec))||(!PyList_Check(Rvec))||(!PyList_Check(dataRedParam))){
        UtsusemiError( MessageTag + "SetD4MatParameters >> arguments must be python-list" );
        return false;
    }
    vector<Double> drv = __gCppToPython.ListToDoubleVector( dataRedParam );
    if ((drv.empty())||(drv.size()!=9)){
        UtsusemiError( MessageTag + "SetD4MatParameters >> Arguments dataRedParam must be list with size of 9" );
        return false;
    }
    vector<Double> lcv = __gCppToPython.ListToDoubleVector( LatticeConsts );
    if ((lcv.empty())||(lcv.size()!=6)){
        UtsusemiError( MessageTag + "SetD4MatParameters >> Arguments LatticeConstants must be list with size of 6" );
        return false;
    }
    vector<Double> uvv = __gCppToPython.ListToDoubleVector( Uvec );
    if ((uvv.empty())||(uvv.size()!=3)){
        UtsusemiError( MessageTag + "SetD4MatParameters >> Arguments Uvec must be list with size of 3" );
        return false;
    }
    vector<Double> vvv = __gCppToPython.ListToDoubleVector( Vvec );
    if ((vvv.empty())||(vvv.size()!=3)){
        UtsusemiError( MessageTag + "SetD4MatParameters >> Arguments Vvec must be list with size of 3" );
        return false;
    }
    vector<Double> rvv = __gCppToPython.ListToDoubleVector( Rvec );
    Int4 ret = SetD4MatParameters( runNo, drv, lcv, uvv, vvv, rvv );
    if (ret==0) return true;
    else return false;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
PutD4MatRunNo(){
    HeaderBase* hh = _D4mat->PutHeaderPointer();
    if (hh->CheckKey(UTSUSEMI_KEY_HEAD_RUNNUMBER)==1)
        return hh->PutInt4(UTSUSEMI_KEY_HEAD_RUNNUMBER);
    else
        return -1;
}
//////////////////////////////////////////////////////////////////////
vector<Double> UtsusemiD4MatOnMem::
PutD4MatDataRedParams(){
    HeaderBase* hh = _D4mat->PutHeaderPointer();
    if (hh->CheckKey("DATAREDPARAM")==1)
        return hh->PutDoubleVector("DATAREDPARAM");
    else{
        vector<Double> ret;
        return ret;
    }
}
//////////////////////////////////////////////////////////////////////
vector<Double> UtsusemiD4MatOnMem::
PutD4MatLatticeConsts(){
    HeaderBase* hh = _D4mat->PutHeaderPointer();
    if (hh->CheckKey("SimpleLatticeConsts")==1)
        return hh->PutDoubleVector("SimpleLatticeConsts");
    else{
        vector<Double> ret;
        return ret;
    }
}
//////////////////////////////////////////////////////////////////////
vector<Double> UtsusemiD4MatOnMem::
PutD4MatUVvects(){
    HeaderBase* hh = _D4mat->PutHeaderPointer();
    vector<Double> ret;
    if ( (hh->CheckKey("SampleUvec")==1)&&(hh->CheckKey("SampleVvec")==1) ){
        vector<Double> retU = hh->PutDoubleVector("SampleUvec");
        vector<Double> retV = hh->PutDoubleVector("SampleVvec");
        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 UtsusemiD4MatOnMem::
ImportEcm( vector<Double> viewAxis, Double arg1, ElementContainerMatrix* ecm1, string ope,
           Double arg2, ElementContainerMatrix* ecm2, string label ){
    
    UtsusemiCalcContainers UCC;
    ElementContainerMatrix ecm = UCC.CalcContainers( arg1, ecm1, ope, arg2, ecm2 );
    Int4 ret = ImportEcm( viewAxis, &ecm, label );
    return ret;
}

//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
ImportEcm( vector<Double> viewAxis, ElementContainerMatrix* ecm, string label ){
    HistogramBinToPoint* HB = new HistogramBinToPoint();
    for (UInt4 i=0;i<ecm->PutSize();i++){
        for (UInt4 j=0;j<ecm->PutPointer(i)->PutSize();j++){
            ElementContainer* ec0 = ecm->PutPointer(i)->PutPointer(j);
            HB->Clear();
            HB->SetTarget(ec0);
            HB->Convert();
            string x_key = ec0->PutXKey();
            string y_key = ec0->PutYKey();
            string e_key = ec0->PutEKey();
            ec0->Replace( y_key, HB->PutY() );
            ec0->Replace( e_key, HB->PutE() );
            ec0->SetKeys( x_key, y_key, e_key );
        }
    }
    delete HB;
    
    UtsusemiSqeCalc* vc = new UtsusemiSqeCalc();
    vc->SetTarget( ecm );
    vc->Projection( viewAxis );
    
    vector<Double> tmp_vx;
    vector<Double> tmp_vy;
    vector<Double> tmp_vz;
    vector<Double> tmp_vw;
    vector<Double> tmp_ii;
    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++){
            vector<Double>  v_ec = ecm->PutPointer(i)->PutPointer(j)->Put("Vx");
            UInt4 n_ii = 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++){
        //cout << "i=" << i << 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){
                    vector<Double>* vx = (*ec)("Vx");
                    vector<Double>* vy = (*ec)("Vy");
                    vector<Double>* vz = (*ec)("Vz");
                    vector<Double>* vw = (*ec)("Vw");
                    
                    vector<Double>* ii = (*ec)(UTSUSEMI_KEY_INTENSITY);
                    vector<Double>* ee = (*ec)(UTSUSEMI_KEY_ERROR);
                    
                    for (UInt4 k=0;k<(ii->size());k++){
                        tmp_vx[cnt]=(*vx)[k];
                        tmp_vy[cnt]=(*vy)[k];
                        tmp_vz[cnt]=(*vz)[k];
                        tmp_vw[cnt]=(*vw)[k];
                        tmp_ii[cnt]=(*ii)[k];
                        tmp_ee[cnt]=(*ee)[k];
                        cnt++;
                    }
                }else{
                    //cout << "i,j=" << i << "," << j << " is MASKED." <<  endl;
                }
            }
        }else{
            //cout << "i=" << i << " is MASKED." <<  endl;
        }
    }
    //cout << "cnt,tmp_ii.size()=" << cnt << "," << tmp_ii.size() << endl;
    ElementContainer ec_D4mat(ecm->PutHeader());
    if (ec_D4mat.PutHeaderPointer()->CheckKey("D4matRLabel")==1){
        ec_D4mat.PutHeaderPointer()->OverWrite("D4matRLabel",label);
    }else{
        ec_D4mat.AddToHeader("D4matRLabel",label);
    }
    ec_D4mat.Add("Vx",tmp_vx,"1/Ang");
    ec_D4mat.Add("Vy",tmp_vy,"1/Ang");
    ec_D4mat.Add("Vz",tmp_vz,"1/Ang");
    ec_D4mat.Add("Vw",tmp_vw,"1/Ang");
    ec_D4mat.Add(UTSUSEMI_KEY_INTENSITY,tmp_ii,"Counts");
    ec_D4mat.Add(UTSUSEMI_KEY_ERROR,tmp_ee,"Counts");
    _D4mat->Add( ec_D4mat );
    
    delete vc;
    return 0;
    
}

//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
ImportEcms( UtsusemiEventDataConverterNeunet* EDC,
	    const vector<UInt4> CaseId, const vector<Double> Phi,
	    const vector<Double> LC, const vector<Double> UV, const vector<Double> VV,
            const vector<Double> VA, const vector<Double> RV, const string maskfile, const Double dOmega ){

    UInt4 num_multh = UtsusemiGetNumOfMulTh();

    delete _D4mat;
    _D4mat = new ElementContainerArray();
    _D4mat->Allocate( Phi.size() );
    
    UInt4 csize=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<csize;ind++){
#endif
        ElementContainerMatrix* ecm = new ElementContainerMatrix();
        //UInt4 p=omp_get_thread_num();
        //cout << "#"<<"("<< p <<")";

        EDC->SetElementContainerMatrix( ecm, CaseId[ind] );
        
        PhiCalculation* PhiC = new PhiCalculation(ecm,19.05,25.0,19.05);
        PhiC->CalcPhi();
        delete PhiC;
	
        if (maskfile!=""){
            UtsusemiSetMask *MSK = new UtsusemiSetMask(ecm, maskfile);
            MSK->Execute();
            delete MSK;
        }
        
        for (UInt4 i=0; i<ecm->PutTableSize(); i++){
            if (ecm->PutPointer(i)->PutHeaderPointer()->PutString(UTSUSEMI_KEY_HEAD_DETTYPE)==UTSUSEMI_KEY_HEAD_DETTYPE_PSD){
                for (UInt4 j=0; j<ecm->PutPointer(i)->PutTableSize(); j++){
                    ElementContainer* ec = ecm->PutPointer(i)->PutPointer(j);
                    Double sa = ec->PutHeaderPointer()->PutDouble(UTSUSEMI_KEY_HEAD_PIXELSOLIDANGLE);
                    sa = sa/dOmega;
                    if (sa!=0)
                        ec->MulMySelf(1.0/sa);
                }
            }
        }
        
        KiKfCorrection* KK = new KiKfCorrection();
        KK->SetTarget(ecm);
        KK->KiKfCorrect();
        delete KK;
        
        if (ecm->PutHeaderPointer()->CheckKey(UTSUSEMI_KEY_HEAD_KICKERCOUNT)==1){
            Double cnts = (Double)( ecm->PutHeaderPointer()->PutInt4(UTSUSEMI_KEY_HEAD_KICKERCOUNT) );
            if (cnts!=0.){
                ecm->MulMySelf( 1.0/ cnts );
            }
        }
        
        SetCrystalParameters( ecm, LC, UV, VV, RV, Phi[ind] );
        
        HistogramBinToPoint* HB = new HistogramBinToPoint();
        for (UInt4 i=0;i<ecm->PutSize();i++){
            for (UInt4 j=0;j<ecm->PutPointer(i)->PutSize();j++){
                ElementContainer* ec0 = ecm->PutPointer(i)->PutPointer(j);
                HB->Clear();
                HB->SetTarget(ec0);
                HB->Convert();
                string x_key = ec0->PutXKey();
                string y_key = ec0->PutYKey();
                string e_key = ec0->PutEKey();
                ec0->Replace( y_key, HB->PutY() );
                ec0->Replace( e_key, HB->PutE() );
                ec0->SetKeys( x_key, y_key, e_key );
            }
        }
        delete HB;
        
        UtsusemiSqeCalc* vc = new UtsusemiSqeCalc();
        vc->SetTarget( ecm );
        vc->Projection( VA );
        delete vc;

        vector<Double> tmp_vx;
        vector<Double> tmp_vy;
        vector<Double> tmp_vz;
        vector<Double> tmp_vw;
        vector<Double> tmp_ii;
        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++){
                vector<Double>  v_ec = ecm->PutPointer(i)->PutPointer(j)->Put("Vx");
                UInt4 n_ii = 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++){
            //cout << "i=" << i << 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){
                        vector<Double>* vx = (*ec)("Vx");
                        vector<Double>* vy = (*ec)("Vy");
                        vector<Double>* vz = (*ec)("Vz");
                        vector<Double>* vw = (*ec)("Vw");
                        
                        vector<Double>* ii = (*ec)(UTSUSEMI_KEY_INTENSITY);
                        vector<Double>* ee = (*ec)(UTSUSEMI_KEY_ERROR);
                        
                        for (UInt4 k=0;k<(ii->size());k++){
                            tmp_vx[cnt]=(*vx)[k];
                            tmp_vy[cnt]=(*vy)[k];
                            tmp_vz[cnt]=(*vz)[k];
                            tmp_vw[cnt]=(*vw)[k];
                            tmp_ii[cnt]=(*ii)[k];
                            tmp_ee[cnt]=(*ee)[k];
                            cnt++;
                        }
                    }else{
                        //cout << "i,j=" << i << "," << j << " is MASKED." <<  endl;
                    }
                }
            }else{
                //cout << "i=" << i << " is MASKED." <<  endl;
            }
        }
        //cout << "cnt,tmp_ii.size()=" << cnt << "," << tmp_ii.size() << endl;
        string label = _stools->UInt4ToString( ind );
        ElementContainer* ec_D4mat = new ElementContainer(ecm->PutHeader());
        if (ec_D4mat->PutHeaderPointer()->CheckKey("D4matRLabel")==1){
            ec_D4mat->PutHeaderPointer()->OverWrite("D4matRLabel",label);
        }else{
            ec_D4mat->AddToHeader("D4matRLabel",label);
        }
        ec_D4mat->Add("Vx",tmp_vx,"1/Ang");
        ec_D4mat->Add("Vy",tmp_vy,"1/Ang");
        ec_D4mat->Add("Vz",tmp_vz,"1/Ang");
        ec_D4mat->Add("Vw",tmp_vw,"1/Ang");
        ec_D4mat->Add(UTSUSEMI_KEY_INTENSITY,tmp_ii,"Counts");
        ec_D4mat->Add(UTSUSEMI_KEY_ERROR,tmp_ee,"Counts");
        _D4mat->Set( ind, ec_D4mat );
        delete ecm;
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4MatOnMem::
ImportEcms( UtsusemiEventDataConverterNeunet* EDC,
            PyObject* CaseId, PyObject* Phi,
            PyObject* LC, PyObject* UV, PyObject* VV,
            PyObject* VA, PyObject* RV, const string maskfile, const Double dOmega ){
    if ((!PyList_Check(CaseId))||(!PyList_Check(Phi))||(!PyList_Check(LC))||(!PyList_Check(UV))||(!PyList_Check(VV))
        ||(!PyList_Check(VA))||(!PyList_Check(RV))){
        UtsusemiError( MessageTag + "ImportEcms >> arguments must be python-list" );
        return false;
    }
    vector<UInt4> civ = __gCppToPython.ListToUInt4Vector( CaseId );
    vector<Double> phv = __gCppToPython.ListToDoubleVector( Phi );
    vector<Double> lcv = __gCppToPython.ListToDoubleVector( LC );
    if ((lcv.empty())||(lcv.size()!=6)){
        UtsusemiError( MessageTag + "ImportEcms >> Arguments LC must be list with size of 6" );
        return false;
    }
    vector<Double> uvv = __gCppToPython.ListToDoubleVector( UV );
    if ((uvv.empty())||(uvv.size()!=3)){
        UtsusemiError( MessageTag + "ImportEcms >> Arguments UV must be list with size of 3" );
        return false;
    }
    vector<Double> vvv = __gCppToPython.ListToDoubleVector( VV );
    if ((vvv.empty())||(vvv.size()!=3)){
        UtsusemiError( MessageTag + "ImportEcms >> Arguments VV must be list with size of 3" );
        return false;
    }
    vector<Double> rvv = __gCppToPython.ListToDoubleVector( RV );
    vector<Double> vav = __gCppToPython.ListToDoubleVector( VA );
    if ((vav.empty())||(vav.size()!=16)){
        UtsusemiError( MessageTag + "ImportEcms >> Arguments VA must be list with size of 16" );
        return false;
    }
    Int4 ret = ImportEcms( EDC, civ, phv, lcv, uvv, vvv, vav, rvv, maskfile, dOmega );
    if (ret==0) return true;
    else return false;
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4MatOnMem::
AllocateD4MatPseudOnLine( UInt4 num_of_cases ){
    delete _D4mat;
    _D4mat = new ElementContainerArray();
    _D4mat->Allocate( num_of_cases );
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
ImportEcmsPsuedOnLine( UtsusemiEventDataMonitorNeunet* EDC,
                       const vector<UInt4> CaseId, const vector<Double> Phi,
                       const vector<Double> LC, const vector<Double> UV, const vector<Double> VV,
                       const vector<Double> VA, const vector<Double> RV, const string maskfile, const Double dOmega, const bool isRefresh ){
    
    UInt4 num_multh = UtsusemiGetNumOfMulTh();

    if (isRefresh){
        delete _D4mat;
        _D4mat = new ElementContainerArray();
        _D4mat->Allocate( Phi.size() );
    }
    
    UInt4 csize=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<csize;ind++){
#endif
        ElementContainerMatrix* ecm = new ElementContainerMatrix();
        //UInt4 p=omp_get_thread_num();
        //cout << "#"<<"("<< p <<")";

        EDC->Output( ecm, CaseId[ind] );
        
        PhiCalculation* PhiC = new PhiCalculation(ecm,19.05,25.0,19.05);
        PhiC->CalcPhi();
        delete PhiC;
	
        UtsusemiSetMask *MSK = new UtsusemiSetMask(ecm, maskfile);
        MSK->Execute();
        delete MSK;
        
        for (UInt4 i=0; i<ecm->PutTableSize(); i++){
            if (ecm->PutPointer(i)->PutHeaderPointer()->PutString(UTSUSEMI_KEY_HEAD_DETTYPE)==UTSUSEMI_KEY_HEAD_DETTYPE_PSD){
                for (UInt4 j=0; j<ecm->PutPointer(i)->PutTableSize(); j++){
                    ElementContainer* ec = ecm->PutPointer(i)->PutPointer(j);
                    Double sa = ec->PutHeaderPointer()->PutDouble(UTSUSEMI_KEY_HEAD_PIXELSOLIDANGLE);
                    sa = sa/dOmega;
                    if (sa!=0)
                        ec->MulMySelf(1.0/sa);
                }
            }
        }
        
        KiKfCorrection* KK = new KiKfCorrection();
        KK->SetTarget(ecm);
        KK->KiKfCorrect();
        delete KK;
        
        if (ecm->PutHeaderPointer()->CheckKey(UTSUSEMI_KEY_HEAD_KICKERCOUNT)==1){
            Double cnts = (Double)( ecm->PutHeaderPointer()->PutInt4(UTSUSEMI_KEY_HEAD_KICKERCOUNT) );
            if (cnts!=0.){
                ecm->MulMySelf( 1.0/ cnts );
            }
        }
        
        SetCrystalParameters( ecm, LC, UV, VV, RV, Phi[ind] );
        
        HistogramBinToPoint* HB = new HistogramBinToPoint();
        for (UInt4 i=0;i<ecm->PutSize();i++){
            for (UInt4 j=0;j<ecm->PutPointer(i)->PutSize();j++){
                ElementContainer* ec0 = ecm->PutPointer(i)->PutPointer(j);
                HB->Clear();
                HB->SetTarget(ec0);
                HB->Convert();
                string x_key = ec0->PutXKey();
                string y_key = ec0->PutYKey();
                string e_key = ec0->PutEKey();
                ec0->Replace( y_key, HB->PutY() );
                ec0->Replace( e_key, HB->PutE() );
                ec0->SetKeys( x_key, y_key, e_key );
            }
        }
        delete HB;
        
        UtsusemiSqeCalc* vc = new UtsusemiSqeCalc();
        vc->SetTarget( ecm );
        vc->Projection( VA );
        delete vc;

        vector<Double> tmp_vx;
        vector<Double> tmp_vy;
        vector<Double> tmp_vz;
        vector<Double> tmp_vw;
        vector<Double> tmp_ii;
        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++){
                vector<Double>  v_ec = ecm->PutPointer(i)->PutPointer(j)->Put("Vx");
                UInt4 n_ii = 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++){
            //cout << "i=" << i << 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){
                        vector<Double>* vx = (*ec)("Vx");
                        vector<Double>* vy = (*ec)("Vy");
                        vector<Double>* vz = (*ec)("Vz");
                        vector<Double>* vw = (*ec)("Vw");
                        
                        vector<Double>* ii = (*ec)(UTSUSEMI_KEY_INTENSITY);
                        vector<Double>* ee = (*ec)(UTSUSEMI_KEY_ERROR);
                        
                        for (UInt4 k=0;k<(ii->size());k++){
                            tmp_vx[cnt]=(*vx)[k];
                            tmp_vy[cnt]=(*vy)[k];
                            tmp_vz[cnt]=(*vz)[k];
                            tmp_vw[cnt]=(*vw)[k];
                            tmp_ii[cnt]=(*ii)[k];
                            tmp_ee[cnt]=(*ee)[k];
                            cnt++;
                        }
                    }else{
                        //cout << "i,j=" << i << "," << j << " is MASKED." <<  endl;
                    }
                }
            }else{
                //cout << "i=" << i << " is MASKED." <<  endl;
            }
        }
        //cout << "cnt,tmp_ii.size()=" << cnt << "," << tmp_ii.size() << endl;
        string label = _stools->UInt4ToString( CaseId[ind] );
        ElementContainer* ec_D4mat = new ElementContainer(ecm->PutHeader());
        if (ec_D4mat->PutHeaderPointer()->CheckKey("D4matRLabel")==1){
            ec_D4mat->PutHeaderPointer()->OverWrite("D4matRLabel",label);
        }else{
            ec_D4mat->AddToHeader("D4matRLabel",label);
        }
        ec_D4mat->Add("Vx",tmp_vx,"1/Ang");
        ec_D4mat->Add("Vy",tmp_vy,"1/Ang");
        ec_D4mat->Add("Vz",tmp_vz,"1/Ang");
        ec_D4mat->Add("Vw",tmp_vw,"1/Ang");
        ec_D4mat->Add(UTSUSEMI_KEY_INTENSITY,tmp_ii,"Counts");
        ec_D4mat->Add(UTSUSEMI_KEY_ERROR,tmp_ee,"Counts");
        if (_D4mat->PutPointer( CaseId[ind]-1 )!=NULL)
            delete _D4mat->PutPointer( CaseId[ind]-1 );
        _D4mat->Set( CaseId[ind]-1, ec_D4mat );
        delete ecm;
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
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->EraseElement(i);
            num_of_ec -= 1;
        }
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
RemoveEcm( 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("D4matRLabel") ){
            _D4mat->EraseElement(i);
            num_of_ec -= 1;
        }
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////
void UtsusemiD4MatOnMem::
ClearAll(){
    _D4mat->reset();
}
//////////////////////////////////////////////////////////////////////
ElementContainerArray UtsusemiD4MatOnMem::
Slice2d( vector<Double> ax1range, vector<Double> ax2range, vector<Double> ax3range, vector<Double> ax4range, vector<string> type, vector<Double> folding )
{
    vector<Int4> v_type;
    v_type.resize(4,-1);
    
    vector< 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;
            }
        }
    }
    
    vector<Double> xrange = CalcRangeAsBinCenterZero( ranges[v_type[0]][0],ranges[v_type[0]][1],ranges[v_type[0]][2] );
    vector<Double> yrange = CalcRangeAsBinCenterZero( ranges[v_type[1]][0],ranges[v_type[1]][1],ranges[v_type[1]][2] );
    vector<Double> xbin;
    vector<Double> ybin;
    Double xbin_width = ranges[v_type[0]][2];
    Double ybin_width = ranges[v_type[1]][2];
    //for (Double x=xrange[0];x<=xrange[1];x+=xrange[2]) xbin.push_back( x );
    //for (Double y=yrange[0];y<=yrange[1];y+=yrange[2]) ybin.push_back( y );
    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 );
    UInt4 n_X = (UInt4)( xrange[2] );
    UInt4 n_Y = (UInt4)( yrange[2] );
    //cout << "yrange=" << yrange[0] << "," << yrange[1] << "," << yrange[2] << endl;
    
    //UInt4 n_X = (UInt4)( (xrange[1]-xrange[0])/xrange[2] +0.5 );
    //UInt4 n_Y = (UInt4)( (yrange[1]-yrange[0])/yrange[2] +0.5 );
    
    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];
    //T1range[0] = ranges[v_type[2]][0];
    //T1range[1] = ranges[v_type[2]][1];
    vector<Double> t1range = CalcRangeAsBinCenterZero( ranges[v_type[2]][0],ranges[v_type[2]][1],ranges[v_type[2]][2] );
    T1range[0] = t1range[0];
    T1range[1] = t1range[1]-0.5*ranges[v_type[2]][2];
    Double *T2range = new Double[2];
    //T2range[0] = ranges[v_type[3]][0];
    //T2range[1] = ranges[v_type[3]][1];
    vector<Double> t2range = CalcRangeAsBinCenterZero( ranges[v_type[3]][0],ranges[v_type[3]][1],ranges[v_type[3]][2] );
    T2range[0] = t2range[0];
    T2range[1] = t2range[1]-0.5*ranges[v_type[3]][2];

    for (UInt4 runId=0;runId<_D4mat->PutSize();runId++){
        ElementContainer* ec_D4mat = _D4mat->PutPointer(runId);
        if (ec_D4mat==NULL) continue;
        vector<vector<Double>*> ax(4);
        ax[0] = (*ec_D4mat)("Vx");
        ax[1] = (*ec_D4mat)("Vy");
        ax[2] = (*ec_D4mat)("Vz");
        ax[3] = (*ec_D4mat)("Vw");
        vector<Double>* ii = (*ec_D4mat)(UTSUSEMI_KEY_INTENSITY);
        vector<Double>* ee = (*ec_D4mat)(UTSUSEMI_KEY_ERROR);
        //cout << "@@@ runId=" << runId << 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 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)[ind]>=0.0){
                                dArray[multh][i_X][i_Y] += (*ii)[ind];
                                eArray[multh][i_X][i_Y] += (*ee)[ind]*(*ee)[ind];
                                cArray[multh][i_X][i_Y] += 1.0;
                            }
                        }
                    }
                }
            }
        }
#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 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)[ind]>=0.0){
                                dArray[0][i_X][i_Y] += (*ii)[ind];
                                eArray[0][i_X][i_Y] += (*ee)[ind]*(*ee)[ind];
                                cArray[0][i_X][i_Y] += 1.0;
                            }
                        }
                    }
                }
            }
        }
#endif
    }

        //cout << "n_X,n_y=" << n_X << "," << n_Y << endl;
        //cout << "xbin.size()=" << xbin.size() << endl;
        //cout << "ybin.size()=" << ybin.size() << endl;
    
    ElementContainerArray eca;
    
    for (UInt4 x=0;x<n_X;x++){
        vector<Double> xr;
        xr.push_back( xbin[x] );
        xr.push_back( xbin[x+1] );
        HeaderBase hh;
        hh.Add( UTSUSEMI_KEY_HEAD_XRANBE, xr );
        
        ElementContainer ec(hh);
        ec.Add("Ybin",ybin );
        vector<Double> Int;
        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){
                Int[y] = ii/cc;
                Err[y] = sqrt(ee)/cc;
            }else{
                Int[y] = MASKVALUE;
                Err[y] = 0.0;
            }
        }
        ec.Add( UTSUSEMI_KEY_INTENSITY, Int );
        ec.Add( UTSUSEMI_KEY_ERROR, Err );
        ec.SetKeys( "Ybin", UTSUSEMI_KEY_INTENSITY, UTSUSEMI_KEY_ERROR );
        
        eca.Add(ec);
    }
    
    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;
    
    return eca;
    
}
//////////////////////////////////////////////////////////////////////
ElementContainerArray UtsusemiD4MatOnMem::
Slice2d( PyObject* ax1range, PyObject* ax2range, PyObject* ax3range, PyObject* ax4range, PyObject* axistype, PyObject* folding ){
    ElementContainerArray empty_ret;
    if ((!PyList_Check(ax1range))||(!PyList_Check(ax2range))||(!PyList_Check(ax3range))||(!PyList_Check(ax4range))
        ||(!PyList_Check(axistype))||(!PyList_Check(folding))){
        UtsusemiError( MessageTag + "Slice2d >> arguments must be python-list" );
        return empty_ret;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    vector<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;
    }
    vector<Double> fldv = __gCppToPython.ListToDoubleVector( folding );
    if ((fldv.empty())||(fldv.size()!=4)){
        UtsusemiError( MessageTag + "Slice2d >> Arguments folding must be list with size of 4" );
        return empty_ret;
    }
    return Slice2d( ax1v, ax2v, ax3v, ax4v, axtv, fldv );
}
//////////////////////////////////////////////////////////////////////
ElementContainerMatrix UtsusemiD4MatOnMem::
Slice3d( vector<Double> ax1range, vector<Double> ax2range, vector<Double> ax3range, vector<Double> ax4range, vector<string> type, vector<Double> folding )
{
    vector<Int4> v_type;
    v_type.resize(4,-1);
    
    vector< 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 + "UtsusemiD4MatOnMem::Slice3d >> type is invalid." );
            ElementContainerMatrix tmp;
            return tmp;
        }
    }
    
    vector<Double> xrange = CalcRangeAsBinCenterZero( ranges[v_type[0]][0],ranges[v_type[0]][1],ranges[v_type[0]][2] );
    vector<Double> yrange = CalcRangeAsBinCenterZero( ranges[v_type[1]][0],ranges[v_type[1]][1],ranges[v_type[1]][2] );
    vector<Double> zrange = CalcRangeAsBinCenterZero( ranges[v_type[2]][0],ranges[v_type[2]][1],ranges[v_type[2]][2] );
    vector<Double> xbin;
    vector<Double> ybin;
    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+=xrange[2]) xbin.push_back( x );
    //for (Double y=yrange[0];y<=yrange[1];y+=yrange[2]) ybin.push_back( y );
    //for (Double z=zrange[0];z<=zrange[1];z+=zrange[2]) zbin.push_back( z );
    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] );
    //cout << "yrange=" << yrange[0] << "," << yrange[1] << "," << yrange[2] << endl;
    
    //UInt4 n_X = (UInt4)( (xrange[1]-xrange[0])/xrange[2] +0.5 );
    //UInt4 n_Y = (UInt4)( (yrange[1]-yrange[0])/yrange[2] +0.5 );
    //UInt4 n_Z = (UInt4)( (zrange[1]-zrange[0])/zrange[2] +0.5 );
    
    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++){
        ElementContainer* ec_D4mat = _D4mat->PutPointer(runId);
        vector<vector<Double>*> ax(4);
        ax[0] = (*ec_D4mat)("Vx");
        ax[1] = (*ec_D4mat)("Vy");
        ax[2] = (*ec_D4mat)("Vz");
        ax[3] = (*ec_D4mat)("Vw");
        vector<Double>* ii = (*ec_D4mat)(UTSUSEMI_KEY_INTENSITY);
        vector<Double>* ee = (*ec_D4mat)(UTSUSEMI_KEY_ERROR);
        //cout << "@@@ runId=" << runId << 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)[ind]>=0.0){
                                dArray[multh][i_X][i_Y][i_Z] += (*ii)[ind];
                                eArray[multh][i_X][i_Y][i_Z] += (*ee)[ind]*(*ee)[ind];
                                cArray[multh][i_X][i_Y][i_Z] += 1.0;
                            }
                        }
                    }
                }
            }
        }
#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)[ind]>=0.0){
                                dArray[0][i_X][i_Y][i_Z] += (*ii)[ind];
                                eArray[0][i_X][i_Y][i_Z] += (*ee)[ind]*(*ee)[ind];
                                cArray[0][i_X][i_Y][i_Z] += 1.0;
                            }
                        }
                    }
                }
            }
        }
#endif
    }

        //cout << "n_X,n_y=" << n_X << "," << n_Y << endl;
        //cout << "xbin.size()=" << xbin.size() << endl;
        //cout << "ybin.size()=" << ybin.size() << endl;
    
    ElementContainerMatrix ecm;
    ecm.Allocate( n_X );
    
    Double xval=0.0;
    Double yval=0.0;
    Double zval=0.0;
    for (UInt4 x=0;x<n_X;x++){
        vector<Double> xr;
        xr.push_back( xbin[x] );
        xr.push_back( xbin[x+1] );
        HeaderBase hh;
        hh.Add( UTSUSEMI_KEY_HEAD_XRANBE, 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++){
            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);
            
            vector<Double> Int( n_Z, 0.0 );
            vector<Double> Err( n_Z, 0.0 );
            vector<Double> xval_vec( n_Z, xval );
            vector<Double> yval_vec( n_Z, yval );
            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){
                    Int[z] = ii/cc;
                    Err[z] = sqrt(ee)/cc;
                }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( "Vx", xval_vec );
            ec->Add( "Vy", yval_vec );
            ec->Add( "Vz", zval_vec );
            eca->Set( y, ec );
        }
        ecm.Set( x, eca );
    }

    //[inamura 170228]-->
    vector<string> keys(3);
    keys[0]="Vx";
    keys[1]="Vy";
    keys[2]="Vz";
    ecm.PutHeaderPointer()->Add("SLICE3DKEYS",keys);
    //<--[inamura 170228]
    
    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 ecm;
    
}
//////////////////////////////////////////////////////////////////////
ElementContainerMatrix UtsusemiD4MatOnMem::
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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    vector<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;
    }
    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;
    }
    return Slice3d( ax1v, ax2v, ax3v, ax4v, axtv, fldv );
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
WriteData( string filepath ){

    WriteSerializationFile<boost::archive::binary_oarchive>  WS( filepath.c_str() );
    
    WS.Save( (*_D4mat) );
    
    return 0;

}

//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
ReadData( string filepath ){
    delete _D4mat;
    _D4mat = new ElementContainerArray();
    ReadSerializationFile<boost::archive::binary_iarchive>  RS( filepath.c_str() );
    
    RS.Load( (*_D4mat) );
    
    return 0;
}

//////////////////////////////////////////////////////////////////////
vector<Double> UtsusemiD4MatOnMem::
GetAxLimit(){
    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 ];
    }
    ElementContainer *ec = _D4mat->PutPointer(0);
    vector<Double>* v1 = (*ec)("Vx");
    vector<Double>* v2 = (*ec)("Vy");
    vector<Double>* v3 = (*ec)("Vz");
    vector<Double>* v4 = (*ec)("Vw");
    for (UInt4 i=0;i<_NumOfMulTh;i++){
        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);
        }
    }
    
    for (UInt4 i=0;i<_D4mat->PutSize();i++){
        ElementContainer *ec = _D4mat->PutPointer(i);
        
        vector<Double> *Vx=(*ec)("Vx");
        vector<Double> *Vy=(*ec)("Vy");
        vector<Double> *Vz=(*ec)("Vz");
        vector<Double> *Vw=(*ec)("Vw");
        
        UInt4 n_v = 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<n_v;j++){
#endif
            UInt4 multh = omp_get_thread_num();
            if ((*Vx)[j]<Ax1[multh][0]) Ax1[multh][0]=(*Vx)[j];
            if ((*Vx)[j]>Ax1[multh][1]) Ax1[multh][1]=(*Vx)[j];
            if ((*Vy)[j]<Ax2[multh][0]) Ax2[multh][0]=(*Vy)[j];
            if ((*Vy)[j]>Ax2[multh][1]) Ax2[multh][1]=(*Vy)[j];
            if ((*Vz)[j]<Ax3[multh][0]) Ax3[multh][0]=(*Vz)[j];
            if ((*Vz)[j]>Ax3[multh][1]) Ax3[multh][1]=(*Vz)[j];
            if ((*Vw)[j]<Ax4[multh][0]) Ax4[multh][0]=(*Vw)[j];
            if ((*Vw)[j]>Ax4[multh][1]) Ax4[multh][1]=(*Vw)[j];
        }
    }
    
    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;
    
    return ret;
}

//////////////////////////////////////////////////////////////////////
void UtsusemiD4MatOnMem::
AllocateD4MatOnDisk(vector<Double> vx_range, vector<Double> vy_range, vector<Double> vz_range, vector<Double> vw_range,
                    vector<string> titles, string data_dir, string paramfile ){
    
    // Make D4Matrix Data
    Double vx_step = vx_range[2];
    Double vy_step = vy_range[2];
    Double vz_step = vz_range[2];
    Double vw_step = vw_range[2];
    vector<Double> Vxrange = CalcRangeAsBinCenterZero( vx_range[0],vx_range[1],vx_step );
    vector<Double> Vyrange = CalcRangeAsBinCenterZero( vy_range[0],vy_range[1],vy_step );
    vector<Double> Vzrange = CalcRangeAsBinCenterZero( vz_range[0],vz_range[1],vz_step );
    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] );
    
    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
    string data_name_base( paramfile );
    string d4mat_param_file;
    string d4mat_data_dir;
    string::size_type ind = paramfile.find_last_of(".xml");
    if (ind == 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 )!=string("/")){
        d4mat_data_dir = data_dir+"/";
    }else{
        d4mat_data_dir = 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 );
    
    vector<UInt4> index_of_blocks;
    vector<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];
        sprintf( ff,"%05d", i );
        string fst = ff;
        string fname = data_name_base+"_"+fst+".bin";
        //cout << MessageTag << "fname=" << fname<< endl;
        name_of_blocks.push_back(fname);
    }
    index_of_blocks.push_back(n_Vw);
    
    vector< 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;

    //cout << "--- index_of_blocks : ";
    //for (UInt4 i=0; i<index_of_blocks.size(); i++) cout << index_of_blocks[i] << ",";
    //cout << endl;
    //for (UInt4 i=0; i<4; i++){
    //    cout << "--- range : ";
    //    for (UInt4 j=0; j<3; j++) cout << ranges[i][j] << ",";
    //    cout << endl;
    //}
    // Save Parameter XML file for D4MatOnDisk
    Int4 ret = SaveParamXmlD4MatOnDisk( d4mat_data_dir, d4mat_param_file, name_of_blocks, index_of_blocks, ranges, titles, _vbinFileComponents );
    if (ret==-1){
        UtsusemiError( MessageTag + "Fail to make new param.xml." );
        return;
    }
    
    // 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];
    //cout << MessageTag << "Size of data="<< sizeof(data) << endl;
    
    for (UInt4 i=0;i<(index_of_blocks.size()-1);i++){
        string datapath = d4mat_data_dir + name_of_blocks[i];
        if ((fp=fopen(datapath.c_str(),"wb"))==NULL){
            UtsusemiError( MessageTag+"Cannot open file="+datapath);
            return;
        }
        
        for (UInt4 j=0;j<_D4mat->PutSize();j++){
            ElementContainer *ec = _D4mat->PutPointer(j);
            vector<Double> *Vx=(*ec)("Vx");
            vector<Double> *Vy=(*ec)("Vy");
            vector<Double> *Vz=(*ec)("Vz");
            vector<Double> *Vw=(*ec)("Vw");
            vector<Double>* ii = (*ec)(UTSUSEMI_KEY_INTENSITY);
            vector<Double>* ee = (*ec)(UTSUSEMI_KEY_ERROR);
        
            UInt4 n_v = Vx->size();
            
            for (UInt4 k=0;k<n_v;k++){
                Double vw = (*Vw)[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)[k];
                Double vy = (*Vy)[k];
                Double vz = (*Vz)[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)[k]);
                eArray[i_vx][i_vy][i_vz][i_vw] += float((*ee)[k]*(*ee)[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)fwrite( data, sizeof(data), 1, fp ) !=1){
                            usleep(50000);
                            if ((int)fwrite( data, sizeof(data), 1, fp ) !=1){
                                UtsusemiError( MessageTag+"Failed to write" );
                                return;
                            }        
                        }
                    }
                }
            }
        }
        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;
    
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4MatOnMem::
AllocateD4MatOnDisk(PyObject* a1range, PyObject* a2range, PyObject* a3range, PyObject* a4range,
                    PyObject* titles, string data_dir, string paramfile ){
    if ((!PyList_Check(a1range))||(!PyList_Check(a2range))||(!PyList_Check(a3range))||(!PyList_Check(a4range))
        ||(!PyList_Check(titles))){
        UtsusemiError( MessageTag + "AllocateD4MatOnDisk >> arguments must be python-list" );
        return false;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    vector<string> axtv = __gCppToPython.ListToStringVector( titles );
    if ((axtv.empty())||(ax4v.size()!=4)){
        UtsusemiError( MessageTag + "AllocateD4MatOnDisk >> Arguments titles must be list with size of 4" );
        return false;
    }
    AllocateD4MatOnDisk( ax1v, ax2v, ax3v, ax4v, axtv, data_dir, paramfile );
    return true;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
SaveParamXmlD4MatOnDisk( string d4mat_datadir, string d4mat_param_file, vector<string> name_of_blocks, vector<UInt4> index_of_blocks, vector< vector<Double> > ranges, vector<string> axtitles, vector<string> pathbinfiles ){
    BoostXmlParser *bxml = new BoostXmlParser();
    
    if ( bxml->CreateNewTree() ){
        string xml_base = "D4Matrix";
        string xml_numOfFileBlocks = xml_base + "/numOfFileBlocks";
        bxml->AddElement( xml_numOfFileBlocks, _stools->Int4ToString( name_of_blocks.size() ) );
        
        string xml_blocks = xml_base + "/blocks";
        string xml_block = xml_blocks + "/block";
        for (Int4 i=0; i<name_of_blocks.size(); i++){
            string xml_file_i = xml_block + ",i=" + _stools->Int4ToString(i);
            bxml->AddElement( xml_file_i, "" );
            string xml_file = xml_file_i+"/filename";
            bxml->AddElement( xml_file, name_of_blocks[i] );
            for (Int4 j=0; j<3; j++){
                string xml_ax = xml_file_i+"/ax"+_stools->Int4ToString(j+1);
                string conts = _stools->DoubleToString( ranges[j][0] )+",";
                conts += _stools->DoubleToString( ranges[j][1] )+",";
                conts += _stools->DoubleToString( ranges[j][2] );
                bxml->AddElement( xml_ax, conts );
            }
            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] );
            string xml_ax = xml_file_i+"/ax4";
            bxml->AddElement( xml_ax, conts );
        }
        string xml_axTitle = xml_base + "/axisTitle";
        for (UInt4 i=0; i<4; i++){
            string xml_ax = xml_axTitle+"/ax"+_stools->Int4ToString(i+1);
            bxml->AddElement( xml_ax, axtitles[i] );
        }
        string xml_numoffile = xml_base+"/numOfFileComponents";
        bxml->AddElement( xml_numoffile, _stools->Int4ToString( pathbinfiles.size() ) );
        
        for (UInt4 i=0;i<pathbinfiles.size();i++){
            string xml_filecomp = xml_base+"/fileComponents";
            bxml->AddElement( xml_filecomp, "" );
            string xml_filepath = xml_filecomp+"/filepath,i="+_stools->Int4ToString(i);
            bxml->AddElement( xml_filepath, pathbinfiles[i] );
        }
        
        
        if (d4mat_datadir.substr( d4mat_datadir.size()-1 )!=string("/"))
            d4mat_datadir = d4mat_datadir+"/";
        bxml->Save( d4mat_datadir+d4mat_param_file );
        
    }else{
        UtsusemiError( MessageTag+"SaveParamXmlD4MatOnDisk > Cannot Make new xml" );
    }
    delete bxml;
    
    return 0;
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
SaveParamXmlD4MatOnDisk( string d4mat_datadir, string d4mat_param_file, vector<string> name_of_blocks, vector<UInt4> index_of_blocks, vector<Double> ax1range, vector<Double> ax2range, vector<Double> ax3range, vector<Double> ax4range, vector<string> axtitles, vector<string> pathbinfiles ){
    vector< 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, pathbinfiles );
}
//////////////////////////////////////////////////////////////////////
Int4 UtsusemiD4MatOnMem::
ImportEcmStepByStep( ElementContainerMatrix* ecm, double ang, string label ){
    ElementContainer ec_D4mat( 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;
            vector<Double>  v_ec = ecm->PutPointer(i)->PutPointer(j)->Put(UTSUSEMI_KEY_INTENSITY);
            UInt4 n_ii = v_ec.size();
            n_all += n_ii;
            numOfec++;
        }
    }
    vector<Double> *hw = new vector<Double>( n_all,0.0 );
    vector<Double> *ii = new vector<Double>( n_all,0.0 );
    vector<Double> *ee = new vector<Double>( n_all,0.0 );

    vector<Double> PA;
    vector<Double> AA;
    vector<Double> PAd;
    vector<Double> AAd;
    vector<Double> PPosi;
    vector<Double> EF;
    
    HistogramBinToPoint* HB = new HistogramBinToPoint();

    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);
            HB->Clear();
            HB->SetTarget(ec);
            HB->Convert();
            vector<Double> vii = HB->PutY();
            vector<Double> vee = HB->PutE();
            vector<Double>* vhw = (*ec)(UTSUSEMI_KEY_ENERGY);
            for (UInt4 k=0; k<vii.size(); k++){
                (*hw)[cnt] = ((*vhw)[k]+(*vhw)[k+1])/2.0;
                (*ii)[cnt] = vii[k];
                (*ee)[cnt] = vee[k];
                cnt++;
            }
            vector<Double> ppv = ec->PutHeaderPointer()->PutDoubleVector(UTSUSEMI_KEY_HEAD_PIXELPOSITION);
            PPosi.push_back( ppv[0] );
            PPosi.push_back( ppv[1] );
            PPosi.push_back( ppv[2] );
            if (isDirectGeometry){
                vector<Double> vPA = ec->PutHeaderPointer()->PutDoubleVector(UTSUSEMI_KEY_HEAD_PIXELPOLARANGLES);
                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("D4mat2NumOfPixels")==1)
        ec_D4mat.PutHeaderPointer()->OverWrite("D4mat2NumOfPixels",numOfec);
    else
        ec_D4mat.AddToHeader("D4mat2NumOfPixels",numOfec);
    if (ec_D4mat.PutHeaderPointer()->CheckKey("D4matRLabel")==1)
        ec_D4mat.PutHeaderPointer()->OverWrite("D4matRLabel",label);
    else
        ec_D4mat.AddToHeader("D4matRLabel",label);
    if (ec_D4mat.PutHeaderPointer()->CheckKey("D4mat2Ang")==1)
        ec_D4mat.PutHeaderPointer()->OverWrite("D4mat2Ang",ang);
    else
        ec_D4mat.AddToHeader("D4mat2Ang",ang);
    
    ec_D4mat.Add(UTSUSEMI_KEY_HW,(*hw),"meV");
    ec_D4mat.Add(UTSUSEMI_KEY_INTENSITY,(*ii),"Counts");
    ec_D4mat.Add(UTSUSEMI_KEY_ERROR,(*ee),"Counts");
    ec_D4mat.Add("PixelPositions",PPosi);
    ec_D4mat.Add("PolarAngles",PA);
    ec_D4mat.Add("AzimAngles",AA);
    if (isDirectGeometry){
        ec_D4mat.Add("PolarAngles2",PAd);
        ec_D4mat.Add("AzimAngles2",AAd);
    }
    ec_D4mat.Add("Efs",EF);

    _D4mat->Add( ec_D4mat );

    delete hw,ii,ee;
    return 0;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4MatOnMem::
ProjectionStepByStep( vector<Double> viewAxis ){
    UtsusemiMessage( MessageTag+"ProjectionStepByStep start. ");
    if (_D4mat->PutSize()==0){
        return false;
    }
    if (_D4mat->PutPointer(0)->CheckKey(UTSUSEMI_KEY_HW)==0){
        return false;
    }

    vector<Double> LatticeConsts = _HH->PutDoubleVector("SimpleLatticeConsts");
    vector<Double> Uvec = _HH->PutDoubleVector("SampleUvec");
    vector<Double> Vvec = _HH->PutDoubleVector("SampleVvec");
    vector<Double> Rvec = _HH->PutDoubleVector("SampleRotateSteps");

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

    for (UInt4 i=0;i<_D4mat->PutSize();i++){
        ElementContainer* ec = _D4mat->PutPointer(i);
        HeaderBase* hh = ec->PutHeaderPointer();
        vector<Double> rv( Rvec.size() );
        copy( Rvec.begin(), Rvec.end(), rv.begin() );
        rv.push_back(1);
        rv.push_back(hh->PutDouble( "D4mat2Ang" ));
        vector<Double> A = vc->MakeProjectionMatrix( LatticeConsts, Uvec, Vvec, rv, viewAxis );

        
        vector<Double>* vhw = (*ec)(UTSUSEMI_KEY_HW);
        vector<Double>* vx = NULL;
        vector<Double>* vy = NULL;
        vector<Double>* vz = NULL;
        vector<Double>* vw = NULL;
        if ( ec->CheckKey("Vx")==0 ){
            vector<Double> tmp( vhw->size(), 0.0 );
            ec->Add("Vx",tmp);
        }
        if ( ec->CheckKey("Vy")==0 ){
            vector<Double> tmp( vhw->size(), 0.0 );
            ec->Add("Vy",tmp);
        }
        if ( ec->CheckKey("Vz")==0 ){
            vector<Double> tmp( vhw->size(), 0.0 );
            ec->Add("Vz",tmp);
        }
        if ( ec->CheckKey("Vw")==0 ){
            vector<Double> tmp( vhw->size(), 0.0 );
            ec->Add("Vw",tmp);
        }
        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 ) );
        }

        vector<Double>* PA = (*ec)("PolarAngles");
        vector<Double>* AA = (*ec)("AzimAngles");
        vector<Double>* Ef = (*ec)("Efs");

        UInt4 nPix = hh->PutInt4( "D4mat2NumOfPixels" );
        UInt4 cnt = 0;
        UInt4 numOfhw = (vhw->size())/nPix;
        for (UInt4 iPix=0; iPix<nPix; iPix++){
            Double px = sin((*PA)[iPix])*cos((*AA)[iPix]);
            Double py = sin((*PA)[iPix])*sin((*AA)[iPix]);
            Double pz = cos((*PA)[iPix]);
            Double ef = 0;
            if (!(Ef->empty())) ef=(*Ef)[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 ) );
                }
                Double qx = -kf*px;
                Double qy = -kf*py;
                Double qz = ki-kf*pz;

                (*vx)[cnt] = qz*A[0] + qx*A[1] + qy*A[2] + hw*A[3];
                (*vy)[cnt] = qz*A[4] + qx*A[5] + qy*A[6] + hw*A[7];
                (*vz)[cnt] = qz*A[8] + qx*A[9] + qy*A[10] + hw*A[11];
                (*vw)[cnt] = qz*A[12] + qx*A[13] + qy*A[14] + hw*A[15];
                cnt++;
            }
        }
    }
    delete vc;
    delete UCC;
    UtsusemiMessage( MessageTag+"ProjectionStepByStep end. ");
    return true;
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4MatOnMem::
ProjectionStepByStep( PyObject* viewAxis ){
    if (!PyList_Check(viewAxis)){
        UtsusemiError( MessageTag + "ProjectionStepByStep >> arguments must be python-list" );
        return false;
    }
    vector<Double> vav = __gCppToPython.ListToDoubleVector( viewAxis );
    if ((vav.empty())||(vav.size()!=16)){
        UtsusemiError( MessageTag + "ProjectionStepByStep >> Arguments viewAxis must be list with size of 16" );
        return false;
    }
    return ProjectionStepByStep( vav );
}
//////////////////////////////////////////////////////////////////////
bool UtsusemiD4MatOnMem::
ExportEcmFromStepByStep(ElementContainerMatrix* ecm, UInt4 index){
    if (index>=(_D4mat->PutSize())) return false;
    HeaderBase *hh_arr = _D4mat->PutHeaderPointer();
    ecm->InputHeader( *hh_arr );
    ElementContainer * ec = _D4mat->PutPointer(index);
    HeaderBase* hh = ec->PutHeaderPointer();

    vector<Double>* vhw = (*ec)(UTSUSEMI_KEY_HW);
    vector<Double>* II = (*ec)(UTSUSEMI_KEY_INTENSITY);
    vector<Double>* EE = (*ec)(UTSUSEMI_KEY_ERROR);
    vector<Double>* PA = (*ec)("PolarAngles");
    vector<Double>* AA = (*ec)("AzimAngles");
    vector<Double>* PP = (*ec)("PixelPositions");
    vector<Double>* PAd = NULL;
    vector<Double>* AAd = NULL;
    if (isDirectGeometry){
        PAd = (*ec)("PolarAngles2");
        AAd = (*ec)("AzimAngles2");
    }
    vector<Double>* Ef = (*ec)("Efs");

    UInt4 nPix = hh->PutInt4( "D4mat2NumOfPixels" );

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

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

    vector<Double> hw(numOfhw+1,0.0);
    hw[0] = (*vhw)[0] - ( (*vhw)[1]-(*vhw)[0] )/2.0;
    for (UInt4 i=0; i<numOfhw-1; i++)
        hw[i+1] = ( (*vhw)[i] + (*vhw)[i+1] )/2.0;
    hw[numOfhw] = (*vhw)[numOfhw-1] + ((*vhw)[numOfhw-1] - (*vhw)[numOfhw-2])/2.0;
    for (UInt4 iPix=0; iPix<nPix; iPix++){
        ElementContainer* ret_ec = new ElementContainer();
        vector<Double> ii(numOfhw,0.0);
        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, "meV" );
        ret_ec->Add( UTSUSEMI_KEY_INTENSITY, ii, "counts" );
        ret_ec->Add( UTSUSEMI_KEY_ERROR, ee, "counts" );
        ret_ec->SetKeys(UTSUSEMI_KEY_ENERGY,UTSUSEMI_KEY_INTENSITY,UTSUSEMI_KEY_ERROR);

        ret_ec->AddToHeader(UTSUSEMI_KEY_HEAD_MASKED,0 );
        vector<Double> vPP(3,0.0);
        vector<Double> vPA(2,1.0);
        vector<Double> vAA(2,1.0);
        for (UInt4 i=0; i<3; i++)
            vPP[i] = PP->at(iPix*3+i);
        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( "AximAngle", 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 );
        eca->Add( *ret_ec );
    }
    //ecm->Set(0, eca);
    ecm->Add( *eca );

    return true;
}
