Skip to content

Commit

Permalink
Merge pull request #49 from pariterre/dev
Browse files Browse the repository at this point in the history
Reading large files
  • Loading branch information
pariterre authored Mar 10, 2019
2 parents 44480b6 + 6326068 commit abe7788
Show file tree
Hide file tree
Showing 18 changed files with 160 additions and 52 deletions.
5 changes: 5 additions & 0 deletions include/Analogs.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ class EZC3D_API ezc3d::DataNS::AnalogsNS::Analogs{
///
const std::vector<ezc3d::DataNS::AnalogsNS::SubFrame>& subframes() const;

///
/// \brief Return if the analogs are empty
/// \return if the analogs are empty
///
bool isempty() const;
};

#endif
5 changes: 5 additions & 0 deletions include/Channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ class EZC3D_API ezc3d::DataNS::AnalogsNS::Channel{
///
void data(float value);

///
/// \brief Return if the channel is empty
/// \return if the channel is empty
///
bool isempty() const;
};


Expand Down
6 changes: 6 additions & 0 deletions include/Frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ class EZC3D_API ezc3d::DataNS::Frame{
///
void add(const ezc3d::DataNS::Points3dNS::Points &points, const ezc3d::DataNS::AnalogsNS::Analogs &analogs);

///
/// \brief Return if the frame is empty
/// \return if the frame is empty
///
bool isempty() const;

};

#endif
6 changes: 6 additions & 0 deletions include/Point.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ class EZC3D_API ezc3d::DataNS::Points3dNS::Point{
/// \param residual The residual component of the 3d point
///
void residual(float residual);

///
/// \brief Return if the point is empty
/// \return if the point is empty
///
bool isempty() const;
};

#endif
5 changes: 5 additions & 0 deletions include/Points.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ class EZC3D_API ezc3d::DataNS::Points3dNS::Points{
///
const std::vector<ezc3d::DataNS::Points3dNS::Point>& points() const;

///
/// \brief Return if the points are empty
/// \return if the points are empty
///
bool isempty() const;
};

#endif
5 changes: 5 additions & 0 deletions include/Subframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ class EZC3D_API ezc3d::DataNS::AnalogsNS::SubFrame{
///
const std::vector<ezc3d::DataNS::AnalogsNS::Channel>& channels() const;

///
/// \brief Return if the subframe is empty
/// \return if the subframe is empty
///
bool isempty() const;
};

#endif
2 changes: 1 addition & 1 deletion include/ezc3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
/// this library is to eazily create, read and modify c3d (<a href="http://c3d.org">http://c3d.org</a>)
/// files, largely used in biomechanics.
///
/// This documentation was automatically generated for the version 0.3.4 on the 28th of February, 2019.
/// This documentation was automatically generated for the version 0.3.5 on the 10th of March, 2019.
///
/// \section install_sec Installation
///
Expand Down
8 changes: 8 additions & 0 deletions src/Analogs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,11 @@ const std::vector<ezc3d::DataNS::AnalogsNS::SubFrame> &ezc3d::DataNS::AnalogsNS:
{
return _subframe;
}

bool ezc3d::DataNS::AnalogsNS::Analogs::isempty() const
{
for (SubFrame subframe : subframes())
if (!subframe.isempty())
return false;
return true;
}
8 changes: 8 additions & 0 deletions src/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,11 @@ void ezc3d::DataNS::AnalogsNS::Channel::data(float v)
{
_data = v;
}

bool ezc3d::DataNS::AnalogsNS::Channel::isempty() const
{
if (static_cast<double>(data()) == 0.0)
return true;
else
return false;
}
23 changes: 16 additions & 7 deletions src/Data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ ezc3d::DataNS::Data::Data(ezc3d::c3d &file)
256*ezc3d::DATA_TYPE::WORD*file.parameters().nbParamBlock() -
ezc3d::DATA_TYPE::BYTE), std::ios::beg); // "- BYTE" so it is just prior

// Initialize some variables
if (file.header().nbFrames()>0)
_frames.resize(file.header().nbFrames());

// Get names of the data
std::vector<std::string> pointNames;
if (file.header().nb3dPoints() > 0)
Expand All @@ -36,6 +32,9 @@ ezc3d::DataNS::Data::Data(ezc3d::c3d &file)

// Read the actual data
for (size_t j = 0; j < file.header().nbFrames(); ++j){
if (file.eof())
break;

ezc3d::DataNS::Frame f;
if (file.header().scaleFactor() < 0){ // if it is float
// Read point 3d
Expand All @@ -55,7 +54,7 @@ ezc3d::DataNS::Data::Data(ezc3d::c3d &file)
}
ptsAtAFrame.point(pt, i);
}
_frames[j].add(ptsAtAFrame); // modified by pts_tp which is an nonconst ref to internal points
f.add(ptsAtAFrame); // modified by pts_tp which is an nonconst ref to internal points

// Read analogs
ezc3d::DataNS::AnalogsNS::Analogs analog;
Expand All @@ -77,12 +76,22 @@ ezc3d::DataNS::Data::Data(ezc3d::c3d &file)
}
analog.subframe(sub, k);
}
_frames[j].add(analog);

f.add(analog);
_frames.push_back(f);
}
else
throw std::invalid_argument("Points were recorded using int number which is not implemented yet");
}

// remove the trailing empty frames if they exist
size_t nFrames(_frames.size());
if (nFrames > 0)
for (size_t i=0; i<nFrames-1; i--){ // -1 so we at least keep one frame if frames are empty
if (_frames.back().isempty())
_frames.pop_back();
else
break;
}
}

void ezc3d::DataNS::Data::print() const
Expand Down
5 changes: 5 additions & 0 deletions src/Frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,8 @@ void ezc3d::DataNS::Frame::add(const ezc3d::DataNS::Points3dNS::Points &point3d_
add(point3d_frame);
add(analog_frame);
}

bool ezc3d::DataNS::Frame::isempty() const
{
return points().isempty() && analogs().isempty();
}
2 changes: 2 additions & 0 deletions src/Header.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ void ezc3d::Header::write(std::fstream &f) const
// Idx of first and last frame
size_t firstFrame(_firstFrame + 1); // 1-based!
size_t lastFrame(_lastFrame + 1); // 1-based!
if (lastFrame > 0xFFFF)
lastFrame = 0xFFFF; // Combine this with group("POINT").parameter("FRAMES") = -1
f.write(reinterpret_cast<const char*>(&firstFrame), 1*ezc3d::DATA_TYPE::WORD);
f.write(reinterpret_cast<const char*>(&lastFrame), 1*ezc3d::DATA_TYPE::WORD);

Expand Down
2 changes: 1 addition & 1 deletion src/Parameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void ezc3d::ParametersNS::GroupNS::Parameter::write(std::fstream &f, int groupId
f.write(reinterpret_cast<const char*>(&_data_type), 1*ezc3d::DATA_TYPE::BYTE);
size_t size_dim(_dimension.size());
// If it is a scalar, store it as so
if (_dimension.size() == 1 && _dimension[0] == 1){
if (_dimension.size() == 1 && _dimension[0] == 1 && _data_type != DATA_TYPE::CHAR){
int _size_dim(0);
f.write(reinterpret_cast<const char*>(&_size_dim), 1*ezc3d::DATA_TYPE::BYTE);
}
Expand Down
12 changes: 12 additions & 0 deletions src/Point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,15 @@ float ezc3d::DataNS::Points3dNS::Point::residual() const
void ezc3d::DataNS::Points3dNS::Point::residual(float residual){
_data[3] = residual;
}

bool ezc3d::DataNS::Points3dNS::Point::isempty() const
{
if (static_cast<double>(x()) == 0.0 &&
static_cast<double>(y()) == 0.0 &&
static_cast<double>(z()) == 0.0 &&
static_cast<double>(residual()) == 0.0)
return true;
else {
return false;
}
}
8 changes: 8 additions & 0 deletions src/Points.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,11 @@ const std::vector<ezc3d::DataNS::Points3dNS::Point> &ezc3d::DataNS::Points3dNS::
{
return _points;
}

bool ezc3d::DataNS::Points3dNS::Points::isempty() const
{
for (Point point : points())
if (!point.isempty())
return false;
return true;
}
8 changes: 8 additions & 0 deletions src/Subframe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,11 @@ const std::vector<ezc3d::DataNS::AnalogsNS::Channel> &ezc3d::DataNS::AnalogsNS::
{
return _channels;
}

bool ezc3d::DataNS::AnalogsNS::SubFrame::isempty() const
{
for (Channel channel : channels())
if (!channel.isempty())
return false;
return true;
}
94 changes: 55 additions & 39 deletions src/ezc3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,16 @@ ezc3d::c3d::c3d(const std::string &filePath):
// Read all the section
_header = std::shared_ptr<ezc3d::Header>(new ezc3d::Header(*this));
_parameters = std::shared_ptr<ezc3d::ParametersNS::Parameters>(new ezc3d::ParametersNS::Parameters(*this));

// header may be inconsistent with the parameters, so it must be update to make sure sizes are consistent
updateHeader();

// Now read the actual data
_data = std::shared_ptr<ezc3d::DataNS::Data>(new ezc3d::DataNS::Data(*this));

// Parameters and header may be inconsistent with actual data, so reprocess them if needed
updateParameters();

// Close the file
close();
}
Expand All @@ -78,7 +82,15 @@ void ezc3d::c3d::write(const std::string& filePath) const
this->header().write(f);

// Write the parameters
this->parameters().write(f);
// We must copy parameters since there is no way to make sure that the number of frames is not higher than 0xFFFF
ezc3d::ParametersNS::Parameters params(parameters());
int nFrames(this->parameters().group("POINT").parameter("FRAMES").valuesAsInt()[0]);
if (nFrames > 0xFFFF){
ezc3d::ParametersNS::GroupNS::Parameter frames("FRAMES");
frames.set(-1);
params.group_nonConst("POINT").parameter(frames);
}
params.write(f);

// Write the data
this->data().write(f);
Expand Down Expand Up @@ -502,47 +514,51 @@ void ezc3d::c3d::updateParameters(const std::vector<std::string> &newPoints, con
nAnalogs = 0;
} else
nAnalogs = parameters().group("ANALOG").parameter("LABELS").valuesAsString().size() + newAnalogs.size();
if (nAnalogs != static_cast<size_t>(grpAnalog.parameter("USED").valuesAsInt()[0])){
grpAnalog.parameter_nonConst("USED").set(nAnalogs);

size_t idxLabels(static_cast<size_t>(grpAnalog.parameterIdx("LABELS")));
size_t idxDescriptions(static_cast<size_t>(grpAnalog.parameterIdx("DESCRIPTIONS")));
std::vector<std::string> labels;
std::vector<std::string> descriptions;
for (size_t i = 0; i<nAnalogs; ++i){
std::string name;
if (data().nbFrames() == 0){
if (i < parameters().group("ANALOG").parameter("LABELS").valuesAsString().size())
name = parameters().group("ANALOG").parameter("LABELS").valuesAsString()[i];
else
name = newAnalogs[i-parameters().group("ANALOG").parameter("LABELS").valuesAsString().size()];
} else {
name = data().frame(0).analogs().subframe(0).channel(i).name();
// Should always be greater than 0..., but we have to take in account Optotrak lazyness
if (parameters().group("ANALOG").nbParameters()){
if (nAnalogs != static_cast<size_t>(grpAnalog.parameter("USED").valuesAsInt()[0])){
grpAnalog.parameter_nonConst("USED").set(nAnalogs);

size_t idxLabels(static_cast<size_t>(grpAnalog.parameterIdx("LABELS")));
size_t idxDescriptions(static_cast<size_t>(grpAnalog.parameterIdx("DESCRIPTIONS")));
std::vector<std::string> labels;
std::vector<std::string> descriptions;
for (size_t i = 0; i<nAnalogs; ++i){
std::string name;
if (data().nbFrames() == 0){
if (i < parameters().group("ANALOG").parameter("LABELS").valuesAsString().size())
name = parameters().group("ANALOG").parameter("LABELS").valuesAsString()[i];
else
name = newAnalogs[i-parameters().group("ANALOG").parameter("LABELS").valuesAsString().size()];
} else {
name = data().frame(0).analogs().subframe(0).channel(i).name();
}
labels.push_back(name);
descriptions.push_back("");
}
labels.push_back(name);
descriptions.push_back("");
}
grpAnalog.parameter_nonConst(idxLabels).set(labels);
grpAnalog.parameter_nonConst(idxDescriptions).set(descriptions);

size_t idxScale(grpAnalog.parameterIdx("SCALE"));
std::vector<float> scales(grpAnalog.parameter(idxScale).valuesAsFloat());
for (size_t i = grpAnalog.parameter(idxScale).valuesAsFloat().size(); i < nAnalogs; ++i)
scales.push_back(1);
grpAnalog.parameter_nonConst(idxScale).set(scales);

size_t idxOffset(grpAnalog.parameterIdx("OFFSET"));
std::vector<int> offset(grpAnalog.parameter(idxOffset).valuesAsInt());
for (size_t i = grpAnalog.parameter(idxOffset).valuesAsInt().size(); i < nAnalogs; ++i)
offset.push_back(0);
grpAnalog.parameter_nonConst(idxOffset).set(offset);

size_t idxUnits(grpAnalog.parameterIdx("UNITS"));
std::vector<std::string> units(grpAnalog.parameter(idxUnits).valuesAsString());
for (size_t i = grpAnalog.parameter(idxUnits).valuesAsString().size(); i < nAnalogs; ++i)
units.push_back("V");
grpAnalog.parameter_nonConst(idxUnits).set(units);
grpAnalog.parameter_nonConst(idxLabels).set(labels);
grpAnalog.parameter_nonConst(idxDescriptions).set(descriptions);

size_t idxScale(grpAnalog.parameterIdx("SCALE"));
std::vector<float> scales(grpAnalog.parameter(idxScale).valuesAsFloat());
for (size_t i = grpAnalog.parameter(idxScale).valuesAsFloat().size(); i < nAnalogs; ++i)
scales.push_back(1);
grpAnalog.parameter_nonConst(idxScale).set(scales);

size_t idxOffset(grpAnalog.parameterIdx("OFFSET"));
std::vector<int> offset(grpAnalog.parameter(idxOffset).valuesAsInt());
for (size_t i = grpAnalog.parameter(idxOffset).valuesAsInt().size(); i < nAnalogs; ++i)
offset.push_back(0);
grpAnalog.parameter_nonConst(idxOffset).set(offset);

size_t idxUnits(grpAnalog.parameterIdx("UNITS"));
std::vector<std::string> units(grpAnalog.parameter(idxUnits).valuesAsString());
for (size_t i = grpAnalog.parameter(idxUnits).valuesAsString().size(); i < nAnalogs; ++i)
units.push_back("V");
grpAnalog.parameter_nonConst(idxUnits).set(units);

}
}
updateHeader();
}
8 changes: 4 additions & 4 deletions test/test_ezc3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1478,8 +1478,8 @@ TEST(c3dFileIO, readOptotrakC3D){


EXPECT_EQ(Optotrak.header().firstFrame(), 0);
EXPECT_EQ(Optotrak.header().lastFrame(), 1148);
EXPECT_EQ(Optotrak.header().nbFrames(), 1149);
EXPECT_EQ(Optotrak.header().lastFrame(), 29);
EXPECT_EQ(Optotrak.header().nbFrames(), 30);


// Parameter tests
Expand All @@ -1495,7 +1495,7 @@ TEST(c3dFileIO, readOptotrakC3D){
EXPECT_EQ(Optotrak.parameters().group("POINT").parameter("RATE").type(), ezc3d::FLOAT);
EXPECT_EQ(Optotrak.parameters().group("POINT").parameter("RATE").valuesAsFloat().size(), 1);
EXPECT_FLOAT_EQ(Optotrak.parameters().group("POINT").parameter("RATE").valuesAsFloat()[0], 30);
EXPECT_EQ(Optotrak.parameters().group("POINT").parameter("FRAMES").valuesAsInt()[0], 1149); // ignore because it changes if analog is present
EXPECT_EQ(Optotrak.parameters().group("POINT").parameter("FRAMES").valuesAsInt()[0], 30); // ignore because it changes if analog is present
EXPECT_EQ(Optotrak.parameters().group("POINT").parameter("FRAMES").type(), ezc3d::INT);
EXPECT_EQ(Optotrak.parameters().group("POINT").parameter("LABELS").type(), ezc3d::CHAR);
EXPECT_EQ(Optotrak.parameters().group("POINT").parameter("LABELS").valuesAsString().size(), 54);
Expand All @@ -1509,6 +1509,6 @@ TEST(c3dFileIO, readOptotrakC3D){
EXPECT_EQ(Optotrak.parameters().group("FORCE_PLATFORM").parameter("USED").valuesAsInt()[0], 0);

// DATA
for (size_t f = 0; f < 1149; ++f)
for (size_t f = 0; f < 30; ++f)
EXPECT_EQ(Optotrak.data().frame(f).points().nbPoints(), 54);
}

0 comments on commit abe7788

Please sign in to comment.