/*
$Id: WriteNeXusFile.cc 2247 2011-04-27 05:20:41Z jisuzuki $
 */

#include "WriteNeXusFile.hh"
////////////////////////////////////////////////////
WriteNeXusFile::
WriteNeXusFile( const std::string &FileName, const std::string &UserName, UInt4 CompMode )
{
  CreateNeXusFile( FileName, UserName );

  Comp = (CompMode+1)*100;
  if (CompMode!=0) Comp=NX_COMP_LZW;    //???
  r_handleFlag =0;
}
////////////////////////////////////////////////////
WriteNeXusFile::
WriteNeXusFile(  NXhandle r_handle, UInt4 CompMode )
{
  handle = r_handle;

  Comp = (CompMode+1)*100;
  if (CompMode!=0) Comp=NX_COMP_LZW;    //???
  r_handleFlag =1;
}
////////////////////////////////////////////////////
WriteNeXusFile::
~WriteNeXusFile()
{
  if( r_handleFlag == 0 ){
    CloseNeXusFile();
  }
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData1( const std::string &Name, UInt4ContainerMatrix UCM )
{
  if( Name == "" ){
    MakeOpenGroup( "UInt4ContainerMatrix", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  UInt4 size = UCM.PutSize();
  WriteData( "size", size );
  for( UInt4 i=0; i<size; i++ ){
    std::string name = "UInt4ContainerArray";
    Char *index = new Char[ 128 ];
    std::snprintf( index, sizeof(index), "%d", i );
    name = name + std::string( index );
    delete [] index;
    WriteData1( name.c_str(), UCM.Put( i ) );
  }
  WriteData1( "HeaderBase_in_UInt4ContainerMatrix", UCM.PutHeader() );
  NXgetgroupID( handle, &link );
  CloseGroup();
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData1( const std::string &Name, ElementContainerMatrix M )
{
  if( Name == "" ){
    MakeOpenGroup( "ElementContainerMatrix", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  UInt4 size = M.PutSize();
  WriteData( "size", size );
  for( UInt4 i=0; i<size; i++ ){
    std::string name = "ElementContainerArray";
    Char *index = new Char[ 128 ];
    std::snprintf( index, sizeof(index), "%d", i );
    name = name + std::string( index );
    delete [] index;
    WriteData1( name.c_str(), M.Put( i ) );
  }
  WriteData1( "HeaderBase_in_ElementContainerMatrix", M.PutHeader() );
  NXgetgroupID( handle, &link );
  CloseGroup();
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteDataP( const std::string &Name, ElementContainerMatrix *M )
{
  if( Name == "" ){
    MakeOpenGroup( "ElementContainerMatrix", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  UInt4 size = M->PutSize();
  WriteData( "size", size );
  for( UInt4 i=0; i<size; i++ ){
    std::string name = "ElementContainerArray";
    Char *index = new Char[ 128 ];
    std::snprintf( index, sizeof(index), "%d", i );
    name = name + std::string( index );
    delete [] index;
    WriteDataP( name.c_str(), M->PutPointer( i ) );
  }
  WriteDataP( "HeaderBase_in_ElementContainerMatrix", M->PutHeaderPointer() );
  NXgetgroupID( handle, &link );
  CloseGroup();
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData1( const std::string &Name, ElementContainerArray ECA )
{
  if( Name == "" ){
    MakeOpenGroup( "ElementContainerArray", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  UInt4 size = ECA.PutSize();
  WriteData( "size", size );
  for( UInt4 i=0; i<size; i++ ){
    std::string name = "ElementContainer";
    Char *index = new Char[ 128 ];
    std::snprintf( index, sizeof(index), "%d", i );
    name = name + std::string( index );
    delete [] index;
    WriteData1( name.c_str(), ECA.Put( i ) );
  }
  WriteData1( "HeaderBase_in_ElementContainerArray", ECA.PutHeader() );
  NXgetgroupID( handle, &link );
  CloseGroup();
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteDataP( const std::string &Name, ElementContainerArray *ECA )
{
  if( Name == "" ){
    MakeOpenGroup( "ElementContainerArray", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  UInt4 size = ECA->PutSize();
  WriteData( "size", size );
  for( UInt4 i=0; i<size; i++ ){
    std::string name = "ElementContainer";
    Char *index = new Char[ 128 ];
    std::snprintf( index, sizeof(index), "%d", i );
    name = name + std::string( index );
    delete [] index;
    WriteDataP( name.c_str(), ECA->PutPointer( i ) );
  }
  WriteDataP( "HeaderBase_in_ElementContainerArray", ECA->PutHeaderPointer() );
  NXgetgroupID( handle, &link );
  CloseGroup();
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData1( const std::string &Name, UInt4ContainerArray UCA )
{
  if( Name == "" ){
    MakeOpenGroup( "UInt4ContainerArray", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  UInt4 size = UCA.PutSize();
  WriteData( "size", size );
  for( UInt4 i=0; i<size; i++ ){
    std::string name = "UInt4Container";
    Char *index = new Char[ 128 ];
    std::snprintf( index, sizeof(index), "%d", i );
    name = name + std::string( index );
    delete [] index;
    WriteData1( name.c_str(), UCA.Put( i ) );
  }
  WriteData1( "HeaderBase_in_UInt4ContainerArray", UCA.PutHeader() );
  NXgetgroupID( handle, &link );
  CloseGroup();
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData1( const std::string &Name, HeaderBase Header )
{
  if( Name == "" ){
    MakeOpenGroup( "HeaderBase", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  std::vector<UInt4> MapList(6);
  MapList[0] = Header.Int4Map->PutTableSize();
  MapList[1] = Header.DoubleMap->PutTableSize();
  MapList[2] = Header.StringMap->PutTableSize();
  MapList[3] = Header.Int4VectorMap->PutTableSize();
  MapList[4] = Header.DoubleVectorMap->PutTableSize();
  MapList[5] = Header.StringVectorMap->PutTableSize();

  std::vector< std::string > KeyList;
  for (UInt4 i=0;i<MapList[0];++i) KeyList.push_back(Header.Int4Map->PutKey(i));
  for (UInt4 i=0;i<MapList[1];++i) KeyList.push_back(Header.DoubleMap->PutKey(i));
  for (UInt4 i=0;i<MapList[2];++i) KeyList.push_back(Header.StringMap->PutKey(i));
  for (UInt4 i=0;i<MapList[3];++i) KeyList.push_back(Header.Int4VectorMap->PutKey(i));
  for (UInt4 i=0;i<MapList[4];++i) KeyList.push_back(Header.DoubleVectorMap->PutKey(i));
  for (UInt4 i=0;i<MapList[5];++i) KeyList.push_back(Header.StringVectorMap->PutKey(i));

  WriteData("MapList", MapList);
  WriteData("KeyList", KeyList);

  for (UInt4 i=0;i<MapList[0];++i)
    WriteData(Header.Int4Map->PutKey(i), Header.Int4Map->Put(i));
  for (UInt4 i=0;i<MapList[1];++i)
    WriteData(Header.DoubleMap->PutKey(i), Header.DoubleMap->Put(i));
  for (UInt4 i=0;i<MapList[2];++i)
    WriteData(Header.StringMap->PutKey(i), Header.StringMap->Put(i));
  for (UInt4 i=0;i<MapList[3];++i)
    WriteData(Header.Int4VectorMap->PutKey(i), Header.Int4VectorMap->Put(i));
  for (UInt4 i=0;i<MapList[4];++i)
    WriteData(Header.DoubleVectorMap->PutKey(i), Header.DoubleVectorMap->Put(i));
  for (UInt4 i=0;i<MapList[5];++i)
    WriteData(Header.StringVectorMap->PutKey(i), Header.StringVectorMap->Put(i));

  //WriteData( "HeaderBaseInString", Header.DumpToString() );
  NXgetgroupID( handle, &link );
  CloseGroup(); // Close HeaderBase directory.
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteDataP( const std::string &Name, HeaderBase *Header )
{
  if( Name == "" ){
    MakeOpenGroup( "HeaderBase", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  std::vector<UInt4> MapList(6);
  MapList[0] = Header->Int4Map->PutTableSize();
  MapList[1] = Header->DoubleMap->PutTableSize();
  MapList[2] = Header->StringMap->PutTableSize();
  MapList[3] = Header->Int4VectorMap->PutTableSize();
  MapList[4] = Header->DoubleVectorMap->PutTableSize();
  MapList[5] = Header->StringVectorMap->PutTableSize();

  std::vector< std::string > KeyList;
  for (UInt4 i=0;i<MapList[0];++i) KeyList.push_back(Header->Int4Map->PutKey(i));
  for (UInt4 i=0;i<MapList[1];++i) KeyList.push_back(Header->DoubleMap->PutKey(i));
  for (UInt4 i=0;i<MapList[2];++i) KeyList.push_back(Header->StringMap->PutKey(i));
  for (UInt4 i=0;i<MapList[3];++i) KeyList.push_back(Header->Int4VectorMap->PutKey(i));
  for (UInt4 i=0;i<MapList[4];++i) KeyList.push_back(Header->DoubleVectorMap->PutKey(i));
  for (UInt4 i=0;i<MapList[5];++i) KeyList.push_back(Header->StringVectorMap->PutKey(i));

  WriteData("MapList", MapList);
  WriteData("KeyList", KeyList);

  for (UInt4 i=0;i<MapList[0];++i)
    WriteData(Header->Int4Map->PutKey(i), Header->Int4Map->Put(i));
  for (UInt4 i=0;i<MapList[1];++i)
    WriteData(Header->DoubleMap->PutKey(i), Header->DoubleMap->Put(i));
  for (UInt4 i=0;i<MapList[2];++i)
    WriteData(Header->StringMap->PutKey(i), Header->StringMap->Put(i));
  for (UInt4 i=0;i<MapList[3];++i)
    WriteData(Header->Int4VectorMap->PutKey(i), Header->Int4VectorMap->Put(i));
  for (UInt4 i=0;i<MapList[4];++i)
    WriteData(Header->DoubleVectorMap->PutKey(i), Header->DoubleVectorMap->Put(i));
  for (UInt4 i=0;i<MapList[5];++i)
    WriteData(Header->StringVectorMap->PutKey(i), Header->StringVectorMap->Put(i));

  //WriteData( "HeaderBaseInString", Header.DumpToString() );
  NXgetgroupID( handle, &link );
  CloseGroup(); // Close HeaderBase directory.
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData1( const std::string &Name, TwoDimElementContainer TDEC ){

  if( Name == "" ){
    MakeOpenGroup( "TwoDimElementContainer", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  WriteData1( "HeaderBase_in_TwoDimElementContainer", TDEC.PutHeader() );
  WriteData1( "DimensionVector", TDEC.PutDimension() );

  Char *buf = new Char[10];
  std::vector<ElementContainer> cont = TDEC.PutPackedContainer();
  for( UInt4 i=0; i<cont.size(); i++ ){
    std::string name = "ElementContainer_";
    std::snprintf( buf, sizeof(buf), "%d", i );
    name = name + std::string( buf );
    WriteData1( name, cont[ i ] );
  }

  NXgetgroupID( handle, &link );
  CloseGroup();
  delete [] buf;
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData1( const std::string &Name, ElementContainer EC )
{
  if( Name == "" ){
    MakeOpenGroup( "ElementContainer", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  UInt4 size = EC.PutSize();
  WriteData( "size", size );
  WriteData( "KeyList", EC.PutMergedKey() );
  for( UInt4 i=0; i<size; i++ ){
    std::string name = EC.PutName( i );
    WriteData( name, EC.Put( name ) );
  }

  WriteData( "Xkey", EC.PutXKey() );
  WriteData( "Ykey", EC.PutYKey() );
  WriteData( "Ekey", EC.PutEKey() );
  WriteData1( "HeaderBase_in_ElementContainer", EC.PutHeader() );
  WriteData1( "UnitHeader_in_ElementContainer", EC.PutUnitHeader() );
  NXgetgroupID( handle, &link );
  CloseGroup();
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteDataP( const std::string &Name, ElementContainer *EC )
{
  if( Name == "" ){
    MakeOpenGroup( "ElementContainer", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  UInt4 size = EC->PutSize();
  WriteData( "size", size );
  WriteData( "KeyList", EC->PutMergedKey() );
  for( UInt4 i=0; i<size; i++ ){
    std::string name = EC->PutName( i );
    WriteDataP( name, EC->PutP( name ) );
  }

  WriteData( "Xkey", EC->PutXKey() );
  WriteData( "Ykey", EC->PutYKey() );
  WriteData( "Ekey", EC->PutEKey() );
  WriteDataP( "HeaderBase_in_ElementContainer", EC->PutHeaderPointer() );
  WriteDataP( "UnitHeader_in_ElementContainer", EC->PutUnitHeaderPointer() );
  NXgetgroupID( handle, &link );
  CloseGroup();
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData1( const std::string &Name, UInt4Container UC )
{
  if( Name == "" ){
    MakeOpenGroup( "UInt4Container", "NXdata" );
  }
  else{
    MakeOpenGroup( Name, "NXdata" );
  }

  UInt4 size = UC.PutSize();
  WriteData( "size", size );
  WriteData( "KeyList", UC.PutMergedKey() );
  for( UInt4 i=0; i<size; i++ ){
    std::string name = UC.PutName( i );
    WriteData( name, UC.Put( name ) );
  }

  WriteData1( "HeaderBase_in_UInt4Container", UC.PutHeader() );
  NXgetgroupID( handle, &link );
  CloseGroup();
}
////////////////////////////////////////////////////
void WriteNeXusFile::
CreateNeXusFile( const std::string &FileName, const std::string &UserName )
{
  //NXopen( name, NXACC_CREATE, &handle );  // Create NeXus file in HDF4 format
  NXopen( FileName.c_str(), NXACC_CREATE5, &handle );   // Create NeXus file in HDF5 format

  NXputattr( handle, "user_name", ( void* )UserName.c_str(), (int)(UserName.size()), NX_CHAR );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
AppendAttribute( HeaderBase *header )
{
  Map< Int4 >             *mi  = header->Int4Map;
  Map< Double >           *md  = header->DoubleMap;
  Map< std::string >           *ms  = header->StringMap;
  Map< std::vector< Int4 > >   *mvi = header->Int4VectorMap;
  Map< std::vector< Double > > *mvd = header->DoubleVectorMap;
  Map< std::vector< std::string > > *mvs = header->StringVectorMap;

  UInt4 mi_size  = mi  -> Size();
  UInt4 md_size  = md  -> Size();
  UInt4 ms_size  = ms  -> Size();
  UInt4 mvi_size = mvi -> Size();
  UInt4 mvd_size = mvd -> Size();
  UInt4 mvs_size = mvs -> Size();

  for( UInt4 i=0; i<mi_size;  i++) AppendAttribute( mi->PutKey( i ),  mi ->Put( i ) );
  for( UInt4 i=0; i<md_size;  i++) AppendAttribute( md->PutKey( i ),  md ->Put( i ) );
  for( UInt4 i=0; i<ms_size;  i++) AppendAttribute( ms->PutKey( i ),  ms ->Put( i ) );
  for( UInt4 i=0; i<mvi_size; i++) AppendAttribute( mvi->PutKey( i ), mvi->Put( i ) );
  for( UInt4 i=0; i<mvd_size; i++) AppendAttribute( mvd->PutKey( i ), mvd->Put( i ) );
  for( UInt4 i=0; i<mvs_size; i++) AppendAttribute( mvs->PutKey( i ), mvs->Put( i ) );

}
////////////////////////////////////////////////////
void WriteNeXusFile::
AppendAttribute( const std::string &Name, std::string value )
{
  NXputattr( handle, Name.c_str(), (void*)value.c_str(), (int)(value.size()), NX_CHAR );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
AppendAttribute( const std::string &Name, UInt4 value )
{
  UInt4 v = value;
  NXputattr( handle, Name.c_str(), (void*)( &v ), 1, NX_UINT32 );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
AppendAttribute( const std::string &Name, Int4 value )
{
  Int4 v = value;
  NXputattr( handle, Name.c_str(), (void*)( &v ), 1, NX_INT32 );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
AppendAttribute( const std::string &Name, Double value )
{
  Double v = value;
  NXputattr( handle, Name.c_str(), (void*)( &v ), 1, NX_FLOAT64 );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
AppendAttribute( const std::string &Name, std::vector<Int4> value )
{
  UInt4 size = (UInt4)(value.size());
  Int4 *v    = new Int4 [ size ];
  for( UInt4 s=0; s<size; s++ ){
    v[s] = value[s];
  }

  NXputattr( handle, Name.c_str(), (void*)v, ( Int4 )size, NX_INT32 );
  delete [] v;
}
////////////////////////////////////////////////////
void WriteNeXusFile::
AppendAttribute( const std::string &Name, std::vector<Double> value )
{
  UInt4 size = (UInt4)(value.size());
  Double *v    = new Double [ size ];
  for( UInt4 s=0; s<size; s++ ){
    v[s] = value[s];
  }

  NXputattr( handle, Name.c_str(), (void*)v, ( Int4 )size, NX_FLOAT64 );
  delete [] v;
}
////////////////////////////////////////////////////
void WriteNeXusFile::
AppendAttribute( const std::string &Name, std::vector<std::string> value )
{
  UInt4 size = (UInt4)(value.size());
  for( UInt4 i=0; i<size; i++ ){
    std::string NewName = "ManyoLib=VectorString=" + Name + "=";
    Char num[256];
    std::snprintf( num,  sizeof(num),"%d", i );
    NewName = NewName + std::string( num );

    NXputattr( handle, NewName.c_str(), (void*)(value[i]).c_str(), ( Int4 )( ( value[i] ).size() ), NX_CHAR );
  }
}
////////////////////////////////////////////////////
void WriteNeXusFile::
MakeOpenGroup( const std::string &Name, std::string Class )
{
  NXmakegroup( handle, Name.c_str(), Class.c_str() );
  NXopengroup( handle, Name.c_str(), Class.c_str() );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
CloseGroup()
{
  NXclosegroup( handle );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
CloseNeXusFile()
{
  NXclose( &handle );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
CloseData()
{
  NXclosedata( handle );
}
////////////////////////////////////////////////////
/*
NXlink * WriteNeXusFile::
MakeLink( NXlink *link )
{
  NXlink *plink;

  if( link == NULL ){
    plink = new NXlink;
  }

  else{
    plink = link;
  }

  NXmakelink( handle, plink );

  return plink;
}
*/
////////////////////////////////////////////////////
/*
void WriteNeXusFile::
WriteData( const std::string &Name )
{
  Int4 rank = 1;
  Int4 ArrayDemDef = 1;

  Char *name = StringToChar( Name );

  NXmakedata( handle, name, NX_CHAR, rank, &ArrayDemDef );
  NXopendata( handle, name );

  //NXputdata( handle, ( void* )Value );
  //NXclosedata( handle );

  delete [] name;
}
*/
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, UInt4  value )
{
  WriteData(Name, &value, 1);
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, Int4 value )
{
  WriteData(Name, &value, 1);
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, Double value )
{
  WriteData(Name, &value, 1);
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, bool value )
{
  Int4 rank = 1;
  Int4 ArrayDemDef = 1;
  Int4 val=0;
  if (value) val = 1;

  //NXmakedata( handle, Name.c_str(), NX_INT8, rank, &ArrayDemDef );
  NXmakedata( handle, Name.c_str(), NX_INT32, rank, &ArrayDemDef );
  // NXcompmakedata is not work well.

  NXopendata( handle, Name.c_str() );

  NXputdata( handle, &val );
  NXgetdataID( handle, &link );
  NXclosedata( handle );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, std::string value )
{
  Int4 rank = 1;
  Int4 ArrayDemDef = ( Int4 )( value.size() );

  NXmakedata( handle, Name.c_str(), NX_CHAR, rank, &ArrayDemDef );
  // NXcompmakedata is not work well.

  NXopendata( handle, Name.c_str() );

  NXputdata( handle, ( void* )value.c_str() );
  NXgetdataID( handle, &link );
  NXclosedata( handle );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, const UInt4 *value, UInt4 size )
{
  Int4 rank = 1;
  Int4 ArrayDemDef = ( Int4 )size;

  if( size == 0 ){
    std::cout << "ERROR : The size of data should not be zero." << std::endl;
  }

  if( Comp!=NX_COMP_NONE ){
    Int4 BufSize = (Int4)size;
    NXcompmakedata( handle, Name.c_str(), NX_UINT32, rank, &ArrayDemDef, Comp, &BufSize );
  }
  else{
    NXmakedata( handle, Name.c_str(), NX_UINT32, rank, &ArrayDemDef );
  }
  NXopendata( handle, Name.c_str() );

  NXputdata( handle, ( void* )value );
  NXgetdataID( handle, &link );
  NXclosedata( handle );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, const Int4 *value, UInt4 size )
{
  Int4 rank = 1;
  Int4 ArrayDemDef = ( Int4 )size;

  if( size == 0 ){
    std::cout << "ERROR : The size of data should not be zero." << std::endl;
  }

  if( Comp!=NX_COMP_NONE ){
    Int4 BufSize = (Int4)size;
    NXcompmakedata( handle, Name.c_str(), NX_INT32, rank, &ArrayDemDef, Comp, &BufSize );
  }
  else{
    NXmakedata( handle, Name.c_str(), NX_INT32, rank, &ArrayDemDef );
  }
  NXopendata( handle, Name.c_str() );

  NXputdata( handle, ( void* )value );
  NXgetdataID( handle, &link );
  NXclosedata( handle );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, const Double *value, UInt4 size )
{
  Int4 rank = 1;
  Int4 ArrayDemDef = ( Int4 )size;

  if( size == 0 ){
    std::cout << "ERROR : The size of data should not be zero." << std::endl;
  }


  if( Comp!=NX_COMP_NONE ){
    Int4 BufSize = (Int4)size;
    NXcompmakedata( handle, Name.c_str(), NX_FLOAT64, rank, &ArrayDemDef, Comp, &BufSize );
  }
  else{
    NXmakedata( handle, Name.c_str(), NX_FLOAT64, rank, &ArrayDemDef );
  }
  NXopendata( handle, Name.c_str() );

  NXputdata( handle, ( void* )value );
  NXgetdataID( handle, &link );
  NXclosedata( handle );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, const Double *value, UInt4 size1, UInt4 size2 )
{
  Int4 rank = 2;
  Int4 ArrayDemDef[2] = { int(size1), int(size2) };

  if( (size1 == 0) || (size2 == 0) ){
      std::cout << "ERROR : The size of data should not be zero." << std::endl;
  }

  if( Comp!=NX_COMP_NONE ){
      Int4 BufSize[2] = {int(size1),int(size2)};
      NXcompmakedata( handle, Name.c_str(), NX_FLOAT64, rank, ArrayDemDef, Comp, BufSize );
  }
  else{
      NXmakedata( handle, Name.c_str(), NX_FLOAT64, rank, ArrayDemDef );
  }
  NXopendata( handle, Name.c_str() );
  NXputdata( handle, ( void* )value );
  NXgetdataID( handle, &link );
  NXclosedata( handle );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, const std::vector<std::string> &value )
{
  NXmakegroup( handle, Name.c_str(), "NXdata" );
  NXopengroup( handle, Name.c_str(), "NXdata" );
  {
    Int4 rank = 1;
    Int4 ArrayDemDef;
    UInt4 size = (UInt4)(value.size());

    for( UInt4 s=0; s<size; s++ ){
      ArrayDemDef = ( Int4 )( ( value[s] ).size() );

      Char buf[256];
      std::snprintf( buf, sizeof(buf), "%d", s );

      /*
      if( Comp!=NX_COMP_NONE ){
        Int4 BufSize = ArrayDemDef;
        NXcompmakedata( handle, buf, NX_CHAR, rank, &ArrayDemDef, Comp, &BufSize );
      }
      else{
        NXmakedata( handle, buf, NX_CHAR, rank, &ArrayDemDef );
      }
      */

      NXmakedata( handle, buf, NX_CHAR, rank, &ArrayDemDef );

      NXopendata( handle, buf );
      {
        NXputdata( handle, ( void* )(value[s]).c_str()  );
      } NXclosedata( handle );
    }
  }
  NXgetgroupID( handle, &link );
  NXclosegroup( handle );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, const std::vector<UInt4> &value )
{
  WriteData(Name, &(value[0]), (UInt4)(value.size()));
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, const std::vector<Int4> &value )
{
  WriteData(Name, &(value[0]), (UInt4)(value.size()));
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, const std::vector<Double> &value )
{
  WriteData(Name, &(value[0]), (UInt4)(value.size()));
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteData( const std::string &Name, const std::vector< std::vector<Double> > &value )
{
  UInt4 size1 = (UInt4)(value.size());
  UInt4 size2 = (UInt4)(value[0].size());
  Double *vals = new Double[size1*size2];
  UInt4 i= 0;
  for (UInt4 r=0; r<size1; r++){
      for (UInt4 s=0; s<size2; s++)
          vals[r*size2+s] = value[r][s];
  }
  WriteData(Name, vals, size1, size2);
  delete [] vals;
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteDataP( const std::string &Name, std::vector<Double> *value )
{
  WriteData( Name, (Double*)(&(*value)[0]), (UInt4)(value->size()));
}
////////////////////////////////////////////////////

void WriteNeXusFile::
MakeLink( NXlink Link ){
  NXmakelink( handle, &link );
}
////////////////////////////////////////////////////
void WriteNeXusFile::
WriteDataWithAttribute(const std::string &Name, std::string value, const std::string &attrname, std::string attrvalue)
{
  Int4 rank = 1;
  Int4 ArrayDemDef = ( Int4 )( value.size() );

  NXmakedata( handle, Name.c_str(), NX_CHAR, rank, &ArrayDemDef );
  // NXcompmakedata is not work well.

  NXopendata( handle, Name.c_str() );

  NXputdata( handle, ( void* )value.c_str() );
  NXputattr( handle, attrname.c_str(), (void*)attrvalue.c_str(), (int)(attrvalue.size()), NX_CHAR );
  NXgetdataID( handle, &link );
  NXclosedata( handle );
}
////////////////////////////////////////////////////
