1
0
mirror of https://github.com/aportelli/LatAnalyze.git synced 2025-06-18 07:17:05 +01:00

first implementation of HDF5 format

This commit is contained in:
2015-10-01 00:13:34 +01:00
committed by Antonin Portelli
parent c672c33189
commit 5e3247697d
17 changed files with 932 additions and 70 deletions

View File

@ -89,6 +89,12 @@ void AsciiFile::save(const RandGenState &state, const std::string &name)
fileStream_ << "#L latan_end rg_state " << endl;
}
// read first name ////////////////////////////////////////////////////////////
string AsciiFile::getFirstName(void)
{
return load();
}
// tests ///////////////////////////////////////////////////////////////////////
bool AsciiFile::isOpen() const
{
@ -118,7 +124,9 @@ void AsciiFile::open(const string &name, const unsigned int mode)
else
{
ios_base::openmode stdMode = static_cast<ios_base::openmode>(0);
name_ = name;
mode_ = mode;
if (mode & Mode::write)
{
stdMode |= ios::out|ios::trunc;
@ -131,8 +139,6 @@ void AsciiFile::open(const string &name, const unsigned int mode)
{
stdMode |= ios::out|ios::app;
}
name_ = name;
mode_ = mode;
isParsed_ = false;
fileStream_.open(name_.c_str(), stdMode);
if (mode_ & Mode::read)

View File

@ -24,6 +24,7 @@
#include <LatAnalyze/File.hpp>
#include <LatAnalyze/Mat.hpp>
#include <LatAnalyze/MatSample.hpp>
#include <LatAnalyze/ParserState.hpp>
#include <LatAnalyze/RandGen.hpp>
#include <fstream>
@ -67,6 +68,8 @@ public:
virtual void save(const DMat &m, const std::string &name);
virtual void save(const DMatSample &s, const std::string &name);
virtual void save(const RandGenState &state, const std::string &name);
// read first name
virtual std::string getFirstName(void);
// tests
virtual bool isOpen(void) const;
// IO

View File

@ -17,12 +17,11 @@
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Latan_Io_hpp_
#define Latan_Io_hpp_
#ifndef Latan_File_hpp_
#define Latan_File_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/IoObject.hpp>
#include <LatAnalyze/ParserState.hpp>
#include <LatAnalyze/Mat.hpp>
#include <LatAnalyze/MatSample.hpp>
#include <LatAnalyze/RandGen.hpp>
@ -64,6 +63,8 @@ public:
virtual void save(const DMat &m, const std::string &name) = 0;
virtual void save(const DMatSample &state, const std::string &name) = 0;
virtual void save(const RandGenState &state, const std::string &name) = 0;
// read first name
virtual std::string getFirstName(void) = 0;
// tests
virtual bool isOpen(void) const = 0;
// IO
@ -114,39 +115,6 @@ const IoT& File::getData(const std::string &name) const
}
}
/******************************************************************************
* Static IO functions *
******************************************************************************/
class Io
{
public:
template <typename IoT, typename FileType>
static IoT load(const std::string &fileName, const std::string &name = "");
template <typename IoT, typename FileType>
static void save(const IoT &data, const std::string &fileName,
const unsigned int mode = File::Mode::write,
const std::string &name = "");
};
// template implementation /////////////////////////////////////////////////////
template <typename IoT, typename FileType>
IoT Io::load(const std::string &fileName, const std::string &name)
{
FileType file(fileName, File::Mode::read);
return file.template read<IoT>(name);
}
template <typename IoT, typename FileType>
void Io::save(const IoT &data, const std::string &fileName,
const unsigned int mode, const std::string &name)
{
FileType file(fileName, mode);
std::string realName = (name.empty()) ? fileName : name;
file.save(data, realName);
}
END_LATAN_NAMESPACE
#endif

315
lib/Hdf5File.cpp Normal file
View File

@ -0,0 +1,315 @@
/*
* Hdf5File.cpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2015 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#include <LatAnalyze/Hdf5File.hpp>
#include <LatAnalyze/IoObject.hpp>
#include <LatAnalyze/includes.hpp>
using namespace std;
using namespace Latan;
#ifndef H5_NO_NAMESPACE
using namespace H5NS;
#endif
constexpr unsigned int maxGroupNameSize = 1024u;
const short dMatType = static_cast<short>(IoObject::IoType::dMat);
const short dMatSampleType = static_cast<short>(IoObject::IoType::dMatSample);
const short rgStateType = static_cast<short>(IoObject::IoType::rgState);
/******************************************************************************
* Hdf5File implementation *
******************************************************************************/
// constructors ////////////////////////////////////////////////////////////////
Hdf5File::Hdf5File(void)
{}
Hdf5File::Hdf5File(const std::string &name, const unsigned int mode)
{
open(name, mode);
}
// destructor //////////////////////////////////////////////////////////////////
Hdf5File::~Hdf5File(void)
{
close();
}
// access //////////////////////////////////////////////////////////////////////
void Hdf5File::save(const DMat &m, const string &name)
{
Group group;
Attribute attr;
DataSet dataset;
hsize_t dim[2] = {static_cast<hsize_t>(m.rows()),
static_cast<hsize_t>(m.cols())};
hsize_t attrDim = 1;
DataSpace dataSpace(2, dim), attrSpace(1, &attrDim);
group = h5File_->createGroup(name.c_str());
attr = group.createAttribute("type", PredType::NATIVE_SHORT, attrSpace);
attr.write(PredType::NATIVE_SHORT, &dMatType);
dataset = group.createDataSet("data", PredType::NATIVE_DOUBLE, dataSpace);
dataset.write(m.data(), PredType::NATIVE_DOUBLE);
}
void Hdf5File::save(const DMatSample &sample, const string &name)
{
Group group;
Attribute attr;
DataSet dataset;
hsize_t dim[2] = {static_cast<hsize_t>(sample[central].rows()),
static_cast<hsize_t>(sample[central].cols())};
hsize_t attrDim = 1;
DataSpace dataSpace(2, dim), attrSpace(1, &attrDim);
const long int nSample = sample.size();
string datasetName;
group = h5File_->createGroup(name.c_str());
attr = group.createAttribute("type", PredType::NATIVE_SHORT, attrSpace);
attr.write(PredType::NATIVE_SHORT, &dMatSampleType);
attr = group.createAttribute("nSample", PredType::NATIVE_LONG, attrSpace);
attr.write(PredType::NATIVE_LONG, &nSample);
FOR_STAT_ARRAY(sample, s)
{
datasetName = (s == central) ? "data_C" : ("data_S_" + strFrom(s));
dataset = group.createDataSet(datasetName, PredType::NATIVE_DOUBLE,
dataSpace);
dataset.write(sample[s].data(), PredType::NATIVE_DOUBLE);
}
}
void Hdf5File::save(const RandGenState &state, const string &name)
{
Group group;
Attribute attr;
DataSet dataset;
hsize_t dim = RLXG_STATE_SIZE;
hsize_t attrDim = 1;
DataSpace dataSpace(1, &dim), attrSpace(1, &attrDim);
group = h5File_->createGroup(name.c_str());
attr = group.createAttribute("type", PredType::NATIVE_SHORT, attrSpace);
attr.write(PredType::NATIVE_SHORT, &rgStateType);
dataset = group.createDataSet("data", PredType::NATIVE_DOUBLE, dataSpace);
dataset.write(state.data(), PredType::NATIVE_DOUBLE);
}
// read first name ////////////////////////////////////////////////////////////
string Hdf5File::getFirstName(void)
{
return getFirstGroupName();
}
// tests ///////////////////////////////////////////////////////////////////////
bool Hdf5File::isOpen(void) const
{
return (h5File_ != nullptr);
}
// IO //////////////////////////////////////////////////////////////////////////
void Hdf5File::close(void)
{
if (isOpen())
{
h5File_->close();
}
h5File_.reset(nullptr);
name_ = "";
mode_ = Mode::null;
deleteData();
}
void Hdf5File::open(const string &name, const unsigned int mode)
{
if (isOpen())
{
LATAN_ERROR(Io, "file already opened with name '" + name_ + "'");
}
else
{
unsigned int h5Mode = 0;
name_ = name;
mode_ = mode;
if (mode & Mode::write)
{
h5Mode |= H5F_ACC_TRUNC;
}
if (mode & Mode::read)
{
h5Mode |= H5F_ACC_RDONLY;
}
if (mode & Mode::append)
{
h5Mode |= H5F_ACC_RDWR|H5F_ACC_CREAT;
}
h5File_.reset(new H5File(name_.c_str(), h5Mode));
}
}
string Hdf5File::getFirstGroupName(void)
{
string res;
if ((mode_ & Mode::read)&&(isOpen()))
{
auto firstGroupName = [](hid_t loc_id, const char *name, void *fname)
{
H5G_stat_t statbuf;
H5Gget_objinfo(loc_id, name, 0, &statbuf);
if ((statbuf.type == H5G_GROUP) && (strlen((char *)fname) == 0))
{
strncpy((char *)fname, name, maxGroupNameSize);
}
return 0;
};
char groupName[maxGroupNameSize];
h5File_->iterateElems("/", nullptr, firstGroupName, groupName);
res = groupName;
}
else
{
if (isOpen())
{
LATAN_ERROR(Io, "file '" + name_ + "' is not opened in read mode");
}
else
{
LATAN_ERROR(Io, "file '" + name_ + "' is not opened");
}
return "";
}
return res;
}
void Hdf5File::load(DMat &m, const DataSet &d)
{
DataSpace dataspace;
hsize_t dim[2];
dataspace = d.getSpace();
dataspace.getSimpleExtentDims(dim);
m.resize(dim[0], dim[1]);
d.read(m.data(), PredType::NATIVE_DOUBLE);
}
void Hdf5File::load(RandGenState &state, const DataSet &d)
{
DataSpace dataspace;
hsize_t dim[1];
dataspace = d.getSpace();
dataspace.getSimpleExtentDims(dim);
if (dim[0] != RLXG_STATE_SIZE)
{
// error here
}
d.read(state.data(), PredType::NATIVE_INT);
}
string Hdf5File::load(const string &name)
{
if ((mode_ & Mode::read)&&(isOpen()))
{
string groupName;
Group group;
Attribute attribute;
DataSet dataset;
IoObject::IoType type;
groupName = (name.empty()) ? getFirstGroupName() : name;
group = h5File_->openGroup(groupName.c_str());
attribute = group.openAttribute("type");
attribute.read(PredType::NATIVE_SHORT, &type);
switch (type)
{
case IoObject::IoType::dMat:
{
DMat *pt = new DMat;
data_[groupName].reset(pt);
dataset = group.openDataSet("data");
load(*pt, dataset);
break;
}
case IoObject::IoType::dMatSample:
{
DMatSample *pt = new DMatSample;
long int nSample;
data_[groupName].reset(pt);
attribute = group.openAttribute("nSample");
attribute.read(PredType::NATIVE_LONG, &nSample);
pt->resize(nSample);
FOR_STAT_ARRAY(*pt, s)
{
if (s == central)
{
dataset = group.openDataSet("data_C");
}
else
{
dataset = group.openDataSet("data_S_" + strFrom(s));
}
load((*pt)[s], dataset);
}
break;
}
case IoObject::IoType::rgState:
{
RandGenState *pt = new RandGenState;
data_[groupName].reset(pt);
dataset = group.openDataSet("data");
load(*pt, dataset);
break;
}
default:
{
LATAN_ERROR(Io, "unknown data type ("
+ strFrom(static_cast<int>(type)) + ") "
" (" + name_ + ":" + groupName + ")");
break;
}
}
return groupName;
}
else
{
if (isOpen())
{
LATAN_ERROR(Io, "file '" + name_ + "' is not opened in read mode");
}
else
{
LATAN_ERROR(Io, "file '" + name_ + "' is not opened");
}
return "";
}
}

72
lib/Hdf5File.hpp Normal file
View File

@ -0,0 +1,72 @@
/*
* Hdf5File.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2015 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Latan_Hdf5File_hpp_
#define Latan_Hdf5File_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/File.hpp>
#include <LatAnalyze/Mat.hpp>
#include <LatAnalyze/MatSample.hpp>
#include <LatAnalyze/RandGen.hpp>
#include <H5Cpp.h>
BEGIN_LATAN_NAMESPACE
#ifndef H5_NO_NAMESPACE
#define H5NS H5
#endif
/******************************************************************************
* HDF5 datafile class *
******************************************************************************/
class Hdf5File: public File
{
public:
// constructors
Hdf5File(void);
Hdf5File(const std::string &name, const unsigned int mode);
// destructor
virtual ~Hdf5File(void);
// access
virtual void save(const DMat &m, const std::string &name);
virtual void save(const DMatSample &s, const std::string &name);
virtual void save(const RandGenState &state, const std::string &name);
// read first name
virtual std::string getFirstName(void);
// tests
virtual bool isOpen(void) const;
// IO
virtual void close(void);
virtual void open(const std::string &name, const unsigned int mode);
private:
// IO
std::string getFirstGroupName(void);
virtual std::string load(const std::string &name = "");
void load(DMat &m, const H5NS::DataSet &d);
void load(DMatSample &s, const H5NS::DataSet &d);
void load(RandGenState &state, const H5NS::DataSet &d);
private:
// file name
std::unique_ptr<H5NS::H5File> h5File_{nullptr};
};
END_LATAN_NAMESPACE
#endif // Latan_Hdf5File_hpp_

42
lib/Io.cpp Normal file
View File

@ -0,0 +1,42 @@
/*
* Io.cpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2015 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#include <LatAnalyze/Io.hpp>
#include <LatAnalyze/includes.hpp>
using namespace std;
using namespace Latan;
string Io::getFirstName(const string &fileName)
{
string ext = extension(fileName);
if (ext == "h5")
{
return getFirstName<Hdf5File>(fileName);
}
else if ((ext == "dat")||(ext == "sample")||(ext == "seed"))
{
return getFirstName<AsciiFile>(fileName);
}
else
{
LATAN_ERROR(Io, "unknown file extension '" + ext + "'");
}
}

120
lib/Io.hpp Normal file
View File

@ -0,0 +1,120 @@
/*
* Io.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2015 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Latan_Io_hpp_
#define Latan_Io_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/AsciiFile.hpp>
#include <LatAnalyze/Hdf5File.hpp>
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* Static IO functions *
******************************************************************************/
class Io
{
public:
template <typename IoT, typename FileType>
static IoT load(const std::string &fileName, const std::string &name = "");
template <typename IoT>
static IoT load(const std::string &fileName, const std::string &name = "");
template <typename IoT, typename FileType>
static void save(const IoT &data, const std::string &fileName,
const unsigned int mode = File::Mode::write,
const std::string &name = "");
template <typename IoT>
static void save(const IoT &data, const std::string &fileName,
const unsigned int mode = File::Mode::write,
const std::string &name = "");
template <typename FileType>
static std::string getFirstName(const std::string &fileName);
static std::string getFirstName(const std::string &fileName);
};
// template implementation /////////////////////////////////////////////////////
template <typename IoT, typename FileType>
IoT Io::load(const std::string &fileName, const std::string &name)
{
FileType file(fileName, File::Mode::read);
return file.template read<IoT>(name);
}
template <typename IoT>
IoT Io::load(const std::string &fileName, const std::string &name)
{
std::string ext = extension(fileName);
if (ext == "h5")
{
return load<IoT, Hdf5File>(fileName, name);
}
else if ((ext == "dat")||(ext == "sample")||(ext == "seed"))
{
return load<IoT, AsciiFile>(fileName, name);
}
else
{
LATAN_ERROR(Io, "unknown file extension '" + ext + "'");
}
}
template <typename IoT, typename FileType>
void Io::save(const IoT &data, const std::string &fileName,
const unsigned int mode, const std::string &name)
{
FileType file(fileName, mode);
std::string realName = (name.empty()) ? fileName : name;
file.save(data, realName);
}
template <typename IoT>
void Io::save(const IoT &data, const std::string &fileName,
const unsigned int mode, const std::string &name)
{
std::string ext = extension(fileName);
if (ext == "h5")
{
save<IoT, Hdf5File>(data, fileName, mode, name);
}
else if ((ext == "dat")||(ext == "sample")||(ext == "seed"))
{
save<IoT, AsciiFile>(data, fileName, mode, name);
}
else
{
LATAN_ERROR(Io, "unknown file extension '" + ext + "'");
}
}
template <typename FileType>
std::string Io::getFirstName(const std::string &fileName)
{
FileType file(fileName, File::Mode::read);
return file.getFirstName();
}
END_LATAN_NAMESPACE
#endif // Latan_Io_hpp_

View File

@ -30,7 +30,7 @@ BEGIN_LATAN_NAMESPACE
class IoObject
{
public:
enum class IoType
enum class IoType: short int
{
noType = 0,
dMat = 1,

View File

@ -29,8 +29,10 @@ libLatAnalyze_la_SOURCES = \
Global.cpp \
GslHybridRootFinder.cpp\
GslQagsIntegrator.cpp \
Hdf5File.cpp \
Histogram.cpp \
includes.hpp \
Io.cpp \
Mat.cpp \
Math.cpp \
MathInterpreter.cpp \
@ -62,8 +64,10 @@ libLatAnalyze_la_HEADERS = \
Global.hpp \
GslHybridRootFinder.hpp\
GslQagsIntegrator.hpp \
Hdf5File.hpp \
Histogram.hpp \
Integrator.hpp \
Io.hpp \
IoObject.hpp \
Mat.hpp \
Math.hpp \