/**
  * Read the file designated by @a filename and fill @a output.
  */
 void ANGFileIO::Read(const std::string& filename, Acquisition::Pointer output)
 {
   output->Reset();
   IEEELittleEndianBinaryFileStream bifs;
   bifs.SetExceptions(BinaryFileStream::EndFileBit | BinaryFileStream::FailBit | BinaryFileStream::BadBit);
   try
   {
     bifs.Open(filename, BinaryFileStream::In);
     ReadEliteHeader_p(output, &bifs);
     ReadEliteMarkersValues_p(output, &bifs);
     // Labels
     std::vector<AngleLabelConverter> labels = std::vector<AngleLabelConverter>(8);
     labels[0] = AngleLabelConverter("R_PELV", "RPelvisAngle", "Pelvis relative to Global/Body axes (Right)");
     labels[1] = AngleLabelConverter("R_HIP", "RHipAngle", "Right Hip Rotation");
     labels[2] = AngleLabelConverter("L_HIP", "LHipAngle", "Left Hip Rotation");
     labels[3] = AngleLabelConverter("R_KNEE", "RKneeAngle", "Right Knee Rotation");
     labels[4] = AngleLabelConverter("L_KNEE", "LKneeAngle", "Left Knee Rotation");
     labels[5] = AngleLabelConverter("R_SHOU", "RShoulderAngle", "Right Shoulder Rotation");
     labels[6] = AngleLabelConverter("L_PELV", "LPelvisAngle", "Pelvis relative to Global/Body axes (Left)");
     labels[7] = AngleLabelConverter("L_SHOU", "LShoulderAngle", "Left Shoulder Rotation");
     
     btk::Point::Pointer RFPA, LFPA;
     for (Acquisition::PointIterator it = output->BeginPoint() ; it != output->EndPoint() ; ++it)
     {
       bifs.SeekRead(10, BinaryFileStream::Current);
       std::string label = btkTrimString(btkTrimString(bifs.ReadString(6)), static_cast<char>(0x00));
       // Known case
       size_t j = 0;
       for (j = 0 ; j < labels.size() ; ++j)
       {
         if (label.compare(labels[j].current) == 0)
         {
           (*it)->SetLabel(labels[j].future);
           (*it)->SetDescription(labels[j].description);
           break;
         }
       }
       // Special *_ANKL
       if (j >= labels.size())
       {
         if (label.compare("R_ANKL") == 0)
         {
           (*it)->SetLabel("RAnkleAngle");
           (*it)->SetDescription("Right Ankle Rotation");
           RFPA = btk::Point::New("RFootProgressAngle", output->GetPointFrameNumber(), Point::Angle, "Right Foot relative to Global/Body axes");
           RFPA->GetValues().col(1) = (*it)->GetValues().col(1);
           RFPA->GetResiduals() = (*it)->GetResiduals();
           (*it)->GetValues().col(1).setZero();
           // Clean the -9999 which were not on the 3 coordinates
           // The column #0 contains only -9999
           (*it)->GetValues().col(0).setZero();
           for (int i = 0 ; i < output->GetPointFrameNumber() ; ++i)
           {
             if (((*it)->GetValues().coeff(i, 2) + 9999.0) < std::numeric_limits<double>::epsilon())
             {
               (*it)->GetValues().coeffRef(i, 2) = 0.0;
               (*it)->GetResiduals().coeffRef(i) = -1.0;
             }
             if ((RFPA->GetValues().coeff(i, 1) + 9999.0) < std::numeric_limits<double>::epsilon())
             {
               RFPA->GetValues().coeffRef(i, 1) = 0.0;
               RFPA->GetResiduals().coeffRef(i) = -1.0;
             }
           }
         }
         else if (label.compare("L_ANKL") == 0)
         {
           (*it)->SetLabel("LAnkleAngle");
           (*it)->SetDescription("Left Ankle Rotation");
           LFPA = btk::Point::New("LFootProgressAngle", output->GetPointFrameNumber(), Point::Angle, "Left Foot relative to Global/Body axes");
           LFPA->GetValues().col(1) = (*it)->GetValues().col(1);
           LFPA->GetResiduals() = (*it)->GetResiduals();
           (*it)->GetValues().col(1).setZero();
           // Clean the -9999 which were not on the 3 coordinates
           // The column #0 contains only -9999
           (*it)->GetValues().col(0).setZero();
           for (int i = 0 ; i < output->GetPointFrameNumber() ; ++i)
           {
             if (((*it)->GetValues().coeff(i, 2) + 9999.0) < std::numeric_limits<double>::epsilon())
             {
               (*it)->GetValues().coeffRef(i, 2) = 0.0;
               (*it)->GetResiduals().coeffRef(i) = -1.0;
             }
             if ((LFPA->GetValues().coeff(i, 1) + 9999.0) < std::numeric_limits<double>::epsilon())
             {
               LFPA->GetValues().coeffRef(i, 1) = 0.0;
               LFPA->GetResiduals().coeffRef(i) = -1.0;
             }
           }
         }
         // No known translation
         else
           (*it)->SetLabel(label);
       }
       (*it)->SetType(Point::Angle);
     }
     if (RFPA != Point::Null)
       output->AppendPoint(RFPA);
     if (LFPA != Point::Null)
       output->AppendPoint(LFPA);
     
   }
   catch (BinaryFileStreamFailure& )
   {
     std::string excmsg; 
     if (bifs.EndFile())
       excmsg = "Unexpected end of file.";
     else if (!bifs.IsOpen())
       excmsg = "Invalid file path.";
     else if(bifs.Bad())
       excmsg = "Loss of integrity of the file stream.";
     else if(bifs.Fail())
       excmsg = "Internal logic operation error on the stream associated with the file.";
     else
       excmsg = "Unknown error associated with the file stream.";
     
     if (bifs.IsOpen()) bifs.Close();
     throw(ANGFileIOException(excmsg));
   }
   catch (ANGFileIOException& )
   {
     if (bifs.IsOpen()) bifs.Close();
     throw;
   }
   catch (std::exception& e)
   {
     if (bifs.IsOpen()) bifs.Close();
     throw(ANGFileIOException("Unexpected exception occurred: " + std::string(e.what())));
   }
   catch(...)
   {
     if (bifs.IsOpen()) bifs.Close();
     throw(ANGFileIOException("Unknown exception"));
   }
 };
 /**
  * Read the file designated by @a filename and fill @a output.
  */
 void GRxFileIO::Read(const std::string& filename, Acquisition::Pointer output)
 {
   output->Reset();
   IEEELittleEndianBinaryFileStream bifs;
   bifs.SetExceptions(BinaryFileStream::EndFileBit | BinaryFileStream::FailBit | BinaryFileStream::BadBit);
   try
   {
     bifs.Open(filename, BinaryFileStream::In);
     uint16_t numFra = bifs.ReadU16();
     double freq = static_cast<double>(bifs.ReadU16());
     // Some values between the bytes 0x05 and 0x49...
     // Bytes 50-51: Number of frames in the main acquisition + 1 and multiplied by 10...
     // Bytes 52-53: 0x00
     bifs.SeekRead(50, BinaryFileStream::Current);
     // Bytes 54-55: First frame 
     double ff = bifs.ReadU16();
     // Bytes 56-57: 0x00
     // Bytes 58-59: Last frame
     // Bytes 60-135 Other values ...
     bifs.SeekRead(80, BinaryFileStream::Current);
     // Bytes 136-139: Length
     double length = bifs.ReadFloat();
     // Bytes 140-143: Width
     double width = bifs.ReadFloat();
     // Bytes 144-147: Height
     double height = bifs.ReadFloat();
     // Corners 1,2,3,4: coordinates X,Y,Z
     std::vector<float> cornersData = bifs.ReadFloat(3*4);
     
     output->Init(0, numFra, 6, 1);
     output->SetFirstFrame(static_cast<int>(ceil(ff / 1000.0 * freq + 1.0)));
     output->SetPointFrequency(freq);
     // Metadata FORCE_PLATFORM
     MetaData::Pointer fp = MetaDataCreateChild(output->GetMetaData(), "FORCE_PLATFORM");
     // Metadata FORCE_PLATFORM:USED
     MetaDataCreateChild(fp, "USED", (int16_t)1);
     // Metadata FORCE_PLATFORM:ZERO
     std::vector<int16_t> zeros = std::vector<int16_t>(2,0);
     MetaDataCreateChild(fp, "ZERO", zeros);
     // Metadata FORCE_PLATFORM:TYPE
     MetaDataCreateChild(fp, "TYPE")->SetInfo(MetaDataInfo::New(std::vector<uint8_t>(1,1), std::vector<int16_t>(1,1)));
     // Metadata FORCE_PLATFORM:CORNERS
     std::vector<uint8_t> cornersDim = std::vector<uint8_t>(3, 1); cornersDim[0] = 3; cornersDim[1] = 4;
     MetaDataCreateChild(fp, "CORNERS")->SetInfo(MetaDataInfo::New(cornersDim, cornersData));
     // Metadata FORCE_PLATFORM:ORIGIN
     std::vector<uint8_t> originDim = std::vector<uint8_t>(2, 1); originDim[0] = 3;
     std::vector<float> originVal = std::vector<float>(3);
     originVal[0] = static_cast<float>(length / 2.0);
     originVal[1] = static_cast<float>(width / 2.0);
     originVal[2] = static_cast<float>(-1.0 * height / 2.0);
     MetaDataCreateChild(fp, "ORIGIN")->SetInfo(MetaDataInfo::New(originDim, originVal));
     // Metadata FORCE_PLATFORM:CHANNEL
     std::vector<uint8_t> channelDim = std::vector<uint8_t>(2, 1); channelDim[0] = 6;
     std::vector<int16_t> channelData = std::vector<int16_t>(6,0);
     channelData[0] = 1; channelData[1] = 2; channelData[2] = 3; channelData[3] = 4; channelData[4] = 5; channelData[5] = 6;
     MetaDataCreateChild(fp, "CHANNEL")->SetInfo(MetaDataInfo::New(channelDim, channelData));
     
     bifs.SeekRead(512, BinaryFileStream::Begin);
     btk::Wrench::Pointer fpw = btk::Wrench::New(numFra);
     for (int i = 0 ; i < output->GetPointFrameNumber() ; ++i)
     {
       output->GetAnalog(1)->GetValues().coeffRef(i) = bifs.ReadFloat();
       output->GetAnalog(0)->GetValues().coeffRef(i) = -1.0 * bifs.ReadFloat();
       output->GetAnalog(2)->GetValues().coeffRef(i) = -1.0 * bifs.ReadFloat();
       output->GetAnalog(4)->GetValues().coeffRef(i) = bifs.ReadFloat() - width / 2.0;
       output->GetAnalog(3)->GetValues().coeffRef(i) = -1.0 * bifs.ReadFloat() + length / 2.0;
       output->GetAnalog(5)->GetValues().coeffRef(i) = bifs.ReadFloat();
     }
     
     // Label channels
     std::string str = std::string(1, 0x00); str[0] = *(filename.rbegin());
     output->GetAnalog(0)->SetLabel("Fx" + str);
     output->GetAnalog(1)->SetLabel("Fy" + str);
     output->GetAnalog(2)->SetLabel("Fz" + str);
     output->GetAnalog(3)->SetLabel("Px" + str);
     output->GetAnalog(4)->SetLabel("Py" + str);
     output->GetAnalog(5)->SetLabel("Mz" + str);
   }
   catch (BinaryFileStreamFailure& )
   {
     std::string excmsg; 
     if (bifs.EndFile())
       excmsg = "Unexpected end of file.";
     else if (!bifs.IsOpen())
       excmsg = "Invalid file path.";
     else if(bifs.Bad())
       excmsg = "Loss of integrity of the file stream.";
     else if(bifs.Fail())
       excmsg = "Internal logic operation error on the stream associated with the file.";
     else
       excmsg = "Unknown error associated with the file stream.";
     
     if (bifs.IsOpen()) bifs.Close();    
     throw(GRxFileIOException(excmsg));
   }
   catch (GRxFileIOException& )
   {
     if (bifs.IsOpen()) bifs.Close(); 
     throw;
   }
   catch (std::exception& e)
   {
     if (bifs.IsOpen()) bifs.Close(); 
     throw(GRxFileIOException("Unexpected exception occurred: " + std::string(e.what())));
   }
   catch(...)
   {
     if (bifs.IsOpen()) bifs.Close(); 
     throw(GRxFileIOException("Unknown exception"));
   }
 };