<commit_before>#include <random>
#include <chrono>

#include <vendor/gmock/gmock.h>

#include <core/rendering/vertex/StaticIndexData.h>
#include <core/rendering/vertex/DynamicIndexData.h>

#include "mock/MockGpuBuffer.h"
#include "mock/MockVertexData.h"
#include "mock/MockGpuBufferFactory.h"

using ::testing::Return;
using ::testing::_;

namespace glove {
TEST(StaticIndexDataTest, ConstructorStoresGpuBufferAndNumverOfIndices) {
    std::default_random_engine generator(
            static_cast<ulong>(std::chrono::system_clock::now().time_since_epoch().count()));
    std::uniform_int_distribution<int> distribution(0, 1000);

    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());
    std::size_t numIndices = static_cast<std::size_t>(distribution(generator));

    StaticIndexData indexData(gpuBuffer, numIndices);

    EXPECT_EQ(gpuBuffer, indexData.GetGpuBuffer());
    EXPECT_EQ(numIndices, indexData.GetIndexCount());
}

TEST(StaticIndexDataTest, BindBufferBindsUnderlyingGpuBuffer) {
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());
    EXPECT_CALL(*(MockGpuBuffer*)gpuBuffer.get(), Bind()).Times(1);

    StaticIndexData indexData(gpuBuffer, 10);
    indexData.BindBuffer();
}

TEST(DynamicIndexDataTest, ConstructorCreatesGpuBufferAndEmptyIndexList) {
    IGpuBufferFactoryPtr gpuBufferFactory(new MockGpuBufferFactory());
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());

    EXPECT_CALL(*(MockGpuBufferFactory*)gpuBufferFactory.get(), CreateIndexBuffer()).Times(1).WillOnce(Return(gpuBuffer));

    DynamicIndexData<unsigned int> indexData(gpuBufferFactory);

    EXPECT_EQ(gpuBuffer, indexData.GetGpuBuffer());
    EXPECT_TRUE(indexData.GetIndices().empty());
    EXPECT_EQ(0, indexData.GetIndexCount());
}

TEST(DynamicIndexDataTest, BindBufferBindsUnderlyingGpuBuffer) {
    IGpuBufferFactoryPtr gpuBufferFactory(new MockGpuBufferFactory());
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());

    EXPECT_CALL(*(MockGpuBufferFactory*)gpuBufferFactory.get(), CreateIndexBuffer()).Times(1).WillOnce(Return(gpuBuffer));
    EXPECT_CALL(*(MockGpuBuffer*)gpuBuffer.get(), Bind()).Times(1);

    DynamicIndexData<unsigned int> indexData(gpuBufferFactory);
    indexData.BindBuffer();
}

TEST(DynamicIndexDataTest, FlushWritesToUnderlyingGpuBuffer) {
    IGpuBufferFactoryPtr gpuBufferFactory(new MockGpuBufferFactory());
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());

    EXPECT_CALL(*(MockGpuBufferFactory*)gpuBufferFactory.get(), CreateIndexBuffer()).Times(1).WillOnce(Return(gpuBuffer));
    EXPECT_CALL(*(MockGpuBuffer*)gpuBuffer.get(), WriteData(0, _)).Times(1);

    DynamicIndexData<unsigned int> indexData(gpuBufferFactory);
    indexData.FlushBuffer();
}

TEST(DynamicIndexDataTest, GetIndexCountReturnsSizeOfBackingIndexListr) {
    IGpuBufferFactoryPtr gpuBufferFactory(new MockGpuBufferFactory());
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());

    EXPECT_CALL(*(MockGpuBufferFactory*)gpuBufferFactory.get(), CreateIndexBuffer()).Times(1).WillOnce(Return(gpuBuffer));

    DynamicIndexData<unsigned int> indexData(gpuBufferFactory);

    EXPECT_EQ(0, indexData.GetIndexCount());

    indexData.GetIndices().push_back(5);
    EXPECT_EQ(1, indexData.GetIndexCount());

    indexData.GetIndices().push_back(2);
    EXPECT_EQ(2, indexData.GetIndexCount());
}

TEST(DynamicIndexDataTest, CanSetIndexList) {
    IGpuBufferFactoryPtr gpuBufferFactory(new MockGpuBufferFactory());
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());

    EXPECT_CALL(*(MockGpuBufferFactory*)gpuBufferFactory.get(), CreateIndexBuffer()).Times(1).WillOnce(Return(gpuBuffer));

    DynamicIndexData<unsigned int> indexData(gpuBufferFactory);
    DynamicIndexData<unsigned int>::IndexList indices;

    indices.push_back(1);
    indices.push_back(2);
    indices.push_back(3);

    indexData.SetIndices(indices);

    EXPECT_EQ(3, indexData.GetIndexCount());
    EXPECT_EQ(indices, indexData.GetIndices());
}
}<commit_msg>Updated render interface tests to also check if DynamicIndexData::Flush calls the buffer's WriteData with proper size argument<commit_after>#include <random>
#include <chrono>

#include <vendor/gmock/gmock.h>

#include <core/rendering/vertex/StaticIndexData.h>
#include <core/rendering/vertex/DynamicIndexData.h>

#include "mock/MockGpuBuffer.h"
#include "mock/MockVertexData.h"
#include "mock/MockGpuBufferFactory.h"

using ::testing::Return;
using ::testing::_;

namespace glove {
TEST(StaticIndexDataTest, ConstructorStoresGpuBufferAndNumverOfIndices) {
    std::default_random_engine generator(
            static_cast<ulong>(std::chrono::system_clock::now().time_since_epoch().count()));
    std::uniform_int_distribution<int> distribution(0, 1000);

    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());
    std::size_t numIndices = static_cast<std::size_t>(distribution(generator));

    StaticIndexData indexData(gpuBuffer, numIndices);

    EXPECT_EQ(gpuBuffer, indexData.GetGpuBuffer());
    EXPECT_EQ(numIndices, indexData.GetIndexCount());
}

TEST(StaticIndexDataTest, BindBufferBindsUnderlyingGpuBuffer) {
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());
    EXPECT_CALL(*(MockGpuBuffer*)gpuBuffer.get(), Bind()).Times(1);

    StaticIndexData indexData(gpuBuffer, 10);
    indexData.BindBuffer();
}

TEST(DynamicIndexDataTest, ConstructorCreatesGpuBufferAndEmptyIndexList) {
    IGpuBufferFactoryPtr gpuBufferFactory(new MockGpuBufferFactory());
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());

    EXPECT_CALL(*(MockGpuBufferFactory*)gpuBufferFactory.get(), CreateIndexBuffer()).Times(1).WillOnce(Return(gpuBuffer));

    DynamicIndexData<unsigned int> indexData(gpuBufferFactory);

    EXPECT_EQ(gpuBuffer, indexData.GetGpuBuffer());
    EXPECT_TRUE(indexData.GetIndices().empty());
    EXPECT_EQ(0, indexData.GetIndexCount());
}

TEST(DynamicIndexDataTest, BindBufferBindsUnderlyingGpuBuffer) {
    IGpuBufferFactoryPtr gpuBufferFactory(new MockGpuBufferFactory());
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());

    EXPECT_CALL(*(MockGpuBufferFactory*)gpuBufferFactory.get(), CreateIndexBuffer()).Times(1).WillOnce(Return(gpuBuffer));
    EXPECT_CALL(*(MockGpuBuffer*)gpuBuffer.get(), Bind()).Times(1);

    DynamicIndexData<unsigned int> indexData(gpuBufferFactory);
    indexData.BindBuffer();
}

TEST(DynamicIndexDataTest, FlushCallsWriteDataOfUnderlyingBuffer) {
    IGpuBufferFactoryPtr gpuBufferFactory(new MockGpuBufferFactory());
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());

    EXPECT_CALL(*(MockGpuBufferFactory*)gpuBufferFactory.get(), CreateIndexBuffer()).Times(1).WillOnce(Return(gpuBuffer));
    EXPECT_CALL(*(MockGpuBuffer*)gpuBuffer.get(), WriteData(0, _)).Times(1);

    DynamicIndexData<unsigned int> indexData(gpuBufferFactory);
    indexData.FlushBuffer();
}

TEST(DynamicIndexDataTest, FlushWritesDataToUnderlyingBuffer) {
    IGpuBufferFactoryPtr gpuBufferFactory(new MockGpuBufferFactory());
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());

    EXPECT_CALL(*(MockGpuBufferFactory*)gpuBufferFactory.get(), CreateIndexBuffer()).Times(1).WillOnce(Return(gpuBuffer));

    DynamicIndexData<unsigned int>::IndexList indices;

    indices.push_back(1);
    indices.push_back(2);
    indices.push_back(3);

    EXPECT_CALL(*(MockGpuBuffer*)gpuBuffer.get(), WriteData(indices.size() * sizeof(unsigned int), _)).Times(1);

    DynamicIndexData<unsigned int> indexData(gpuBufferFactory);
    indexData.SetIndices(indices);
    indexData.FlushBuffer();
}

TEST(DynamicIndexDataTest, GetIndexCountReturnsSizeOfBackingIndexListr) {
    IGpuBufferFactoryPtr gpuBufferFactory(new MockGpuBufferFactory());
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());

    EXPECT_CALL(*(MockGpuBufferFactory*)gpuBufferFactory.get(), CreateIndexBuffer()).Times(1).WillOnce(Return(gpuBuffer));

    DynamicIndexData<unsigned int> indexData(gpuBufferFactory);

    EXPECT_EQ(0, indexData.GetIndexCount());

    indexData.GetIndices().push_back(5);
    EXPECT_EQ(1, indexData.GetIndexCount());

    indexData.GetIndices().push_back(2);
    EXPECT_EQ(2, indexData.GetIndexCount());
}

TEST(DynamicIndexDataTest, CanSetIndexList) {
    IGpuBufferFactoryPtr gpuBufferFactory(new MockGpuBufferFactory());
    IGpuBufferPtr gpuBuffer(new MockGpuBuffer());

    EXPECT_CALL(*(MockGpuBufferFactory*)gpuBufferFactory.get(), CreateIndexBuffer()).Times(1).WillOnce(Return(gpuBuffer));

    DynamicIndexData<unsigned int> indexData(gpuBufferFactory);
    DynamicIndexData<unsigned int>::IndexList indices;

    indices.push_back(1);
    indices.push_back(2);
    indices.push_back(3);

    indexData.SetIndices(indices);

    EXPECT_EQ(3, indexData.GetIndexCount());
    EXPECT_EQ(indices, indexData.GetIndices());
}
}<|endoftext|>


<commit_before>#include "boost/filesystem.hpp"
#include "boost/program_options.hpp"

#include <assert.h>
#include "itkCenteredSimilarity2DTransform.h"

// my files
#include "Stack.hpp"
#include "NormalizeImages.hpp"
#include "StackInitializers.hpp"
#include "RegistrationBuilder.hpp"
#include "StackAligner.hpp"
#include "StackIOHelpers.hpp"
#include "IOHelpers.hpp"
#include "Dirs.hpp"
#include "Parameters.hpp"
#include "StackTransforms.hpp"
#include "OptimizerConfig.hpp"
#include "Profiling.hpp"

namespace po = boost::program_options;
using namespace boost::filesystem;

po::variables_map parse_arguments(int argc, char *argv[]);

int main(int argc, char *argv[]) {
  // Parse command line arguments
  po::variables_map vm = parse_arguments(argc, argv);

  // Process command line arguments
  Dirs::SetDataSet( vm["dataSet"].as<string>() );
  Dirs::SetOutputDirName( vm["outputDir"].as<string>() );
  string blockDir = vm.count("blockDir") ? vm["blockDir"].as<string>() + "/" : Dirs::BlockDir();
  string sliceDir = vm.count("sliceDir") ? vm["sliceDir"].as<string>() + "/" : Dirs::SliceDir();
  const bool writeImages = vm["writeImages"].as<bool>();

  vector< string > LoResFileNames, HiResFileNames;
  if( vm.count("slice") )
  {
    LoResFileNames.push_back(blockDir + vm["slice"].as<string>());
    HiResFileNames.push_back(sliceDir + vm["slice"].as<string>());
  }
  else
  {
    LoResFileNames = getFilePaths(blockDir, Dirs::SliceFile());
    HiResFileNames = getFilePaths(sliceDir, Dirs::SliceFile());
  }

  // initialise stack objects with correct spacings, sizes etc
  typedef Stack< float, itk::ResampleImageFilter, itk::LinearInterpolateImageFunction > StackType;
  StackType::SliceVectorType LoResImages = readImages< StackType >(LoResFileNames);
  StackType::SliceVectorType HiResImages = readImages< StackType >(HiResFileNames);
  normalizeImages< StackType >(LoResImages);
  normalizeImages< StackType >(HiResImages);
  boost::shared_ptr< StackType > LoResStack = InitializeLoResStack<StackType>(LoResImages);
  boost::shared_ptr< StackType > HiResStack = InitializeHiResStack<StackType>(HiResImages);

  // Assert stacks have the same number of slices
  assert(LoResStack->GetSize() == HiResStack->GetSize());

  // initialize stacks' transforms so that 2D images line up at their centres.
  if( vm.count("blockDir") )
    // if working with segmentations already in the right coordinate system,
    // no need to apply transforms
    StackTransforms::InitializeToIdentity(*LoResStack);
  else
  {
    // if working from the original images, apply the necessary translation
    StackTransforms::InitializeWithTranslation( *LoResStack, StackTransforms::GetLoResTranslation("whole_heart") );
    ApplyAdjustments( *LoResStack, LoResFileNames, Dirs::ConfigDir() + "LoRes_adjustments/");
  }

  StackTransforms::InitializeToCommonCentre( *HiResStack );
  StackTransforms::SetMovingStackCenterWithFixedStack( *LoResStack, *HiResStack );

  // create output dir before write operations
  create_directory( Dirs::ResultsDir() );

  // Generate fixed images to register against
  LoResStack->updateVolumes();
  if( writeImages )
  {
    writeImage< StackType::VolumeType >( LoResStack->GetVolume(), Dirs::ResultsDir() + "LoResStack.mha" );
  }

  // initialise registration framework
  typedef RegistrationBuilder< StackType > RegistrationBuilderType;
  RegistrationBuilderType registrationBuilder;
  RegistrationBuilderType::RegistrationType::Pointer registration = registrationBuilder.GetRegistration();
  StackAligner< StackType > stackAligner(*LoResStack, *HiResStack, registration);

  // Scale parameter space
  OptimizerConfig::SetOptimizerScalesForCenteredRigid2DTransform( registration->GetOptimizer() );

  // Add time and memory probes
  itkProbesCreate();

  // perform centered rigid 2D registration on each pair of slices
  itkProbesStart( "Aligning stacks" );
  stackAligner.Update();
  itkProbesStop( "Aligning stacks" );

  // Report the time and memory taken by the registration
  itkProbesReport( std::cout );

  // write rigid transforms
  if( writeImages )
  {
    HiResStack->updateVolumes();
    writeImage< StackType::VolumeType >( HiResStack->GetVolume(), Dirs::ResultsDir() + "HiResRigidStack.mha" );
    // writeImage< StackType::MaskVolumeType >( HiResStack->Get3DMask()->GetImage(), Dirs::ResultsDir() + "HiResRigidMask.mha" );
  }
  StackTransforms::InitializeFromCurrentTransforms< StackType, itk::CenteredSimilarity2DTransform< double > >(*HiResStack);

  // Scale parameter space
  OptimizerConfig::SetOptimizerScalesForCenteredSimilarity2DTransform( registration->GetOptimizer() );

  // perform similarity rigid 2D registration
  stackAligner.Update();

  // write similarity transforms
  if( writeImages )
  {
    HiResStack->updateVolumes();
    writeImage< StackType::VolumeType >( HiResStack->GetVolume(), Dirs::ResultsDir() + "HiResSimilarityStack.mha" );
  }

  // repeat registration with affine transform
  StackTransforms::InitializeFromCurrentTransforms< StackType, itk::CenteredAffineTransform< double, 2 > >(*HiResStack);
  OptimizerConfig::SetOptimizerScalesForCenteredAffineTransform( registration->GetOptimizer() );
  stackAligner.Update();

  if( writeImages )
  {
    HiResStack->updateVolumes();
    writeImage< StackType::VolumeType >( HiResStack->GetVolume(), Dirs::ResultsDir() + "HiResAffineStack.mha" );
    // writeImage< StackType::MaskVolumeType >( HiResStack->Get3DMask()->GetImage(), Dirs::ResultsDir() + "HiResAffineMask.mha" );
  }

  // Update LoRes as the masks might have shrunk
  LoResStack->updateVolumes();

  // persist mask numberOfTimesTooBig
  vector< string > fileNames = getFileNames(Dirs::SliceFile());
  saveVectorToFiles(HiResStack->GetNumberOfTimesTooBig(), "number_of_times_too_big", fileNames );

  // persist final metric values
  saveVectorToFiles(stackAligner.GetFinalMetricValues(), "metric_values", fileNames );

  // write transforms to directories labeled by both ds ratios
  create_directory(Dirs::LoResTransformsDir());
  create_directory(Dirs::HiResTransformsDir());
  Save(*LoResStack, LoResFileNames, Dirs::LoResTransformsDir());
  Save(*HiResStack, HiResFileNames, Dirs::HiResTransformsDir());

  return EXIT_SUCCESS;
}

po::variables_map parse_arguments(int argc, char *argv[])
{
  // Declare the supported options.
  po::options_description opts("Options");
  opts.add_options()
      ("help,h", "produce help message")
      ("dataSet", po::value<string>(), "which rat to use")
      ("outputDir", po::value<string>(), "directory to place results")
      ("slice", po::value<string>(), "optional individual slice to register")
      ("blockDir", po::value<string>(), "directory containing LoRes originals")
      ("sliceDir", po::value<string>(), "directory containing HiRes originals")
      ("writeImages", po::bool_switch(), "output images and masks")
  ;

  po::positional_options_description p;
  p.add("dataSet", 1)
   .add("outputDir", 1)
   .add("slice", 1);

  // parse command line
  po::variables_map vm;
	try
	{
  po::store(po::command_line_parser(argc, argv)
            .options(opts)
            .positional(p)
            .run(),
            vm);
	}
	catch (std::exception& e)
	{
	  cerr << "caught command-line parsing error" << endl;
    std::cerr << e.what() << std::endl;
    exit(EXIT_FAILURE);
  }
  po::notify(vm);

  // if help is specified, or positional args aren't present
  if (vm.count("help") || !vm.count("dataSet") || !vm.count("outputDir")) {
    cerr << "Usage: "
      << argv[0] << " [--dataSet=]RatX [--outputDir=]my_dir [Options]"
      << endl << endl;
    cerr << opts << "\n";
    exit(EXIT_FAILURE);
  }

  return vm;
}
<commit_msg>Fixed BuildVolumes single slice bug and refactored image file paths vector.<commit_after>#include "boost/filesystem.hpp"
#include "boost/program_options.hpp"

#include <assert.h>
#include "itkCenteredSimilarity2DTransform.h"

// my files
#include "Stack.hpp"
#include "NormalizeImages.hpp"
#include "StackInitializers.hpp"
#include "RegistrationBuilder.hpp"
#include "StackAligner.hpp"
#include "StackIOHelpers.hpp"
#include "IOHelpers.hpp"
#include "Dirs.hpp"
#include "Parameters.hpp"
#include "StackTransforms.hpp"
#include "OptimizerConfig.hpp"
#include "Profiling.hpp"

namespace po = boost::program_options;
using namespace boost::filesystem;

po::variables_map parse_arguments(int argc, char *argv[]);

int main(int argc, char *argv[]) {
  // Parse command line arguments
  po::variables_map vm = parse_arguments(argc, argv);

  // Process command line arguments
  Dirs::SetDataSet( vm["dataSet"].as<string>() );
  Dirs::SetOutputDirName( vm["outputDir"].as<string>() );
  string blockDir = vm.count("blockDir") ? vm["blockDir"].as<string>() + "/" : Dirs::BlockDir();
  string sliceDir = vm.count("sliceDir") ? vm["sliceDir"].as<string>() + "/" : Dirs::SliceDir();
  const bool writeImages = vm["writeImages"].as<bool>();

  vector< string > LoResFilePaths, HiResFilePaths;
  if( vm.count("slice") )
  {
    LoResFilePaths.push_back(blockDir + vm["slice"].as<string>());
    HiResFilePaths.push_back(sliceDir + vm["slice"].as<string>());
  }
  else
  {
    LoResFilePaths = getFilePaths(blockDir, Dirs::SliceFile());
    HiResFilePaths = getFilePaths(sliceDir, Dirs::SliceFile());
  }

  // initialise stack objects with correct spacings, sizes etc
  typedef Stack< float, itk::ResampleImageFilter, itk::LinearInterpolateImageFunction > StackType;
  StackType::SliceVectorType LoResImages = readImages< StackType >(LoResFilePaths);
  StackType::SliceVectorType HiResImages = readImages< StackType >(HiResFilePaths);
  normalizeImages< StackType >(LoResImages);
  normalizeImages< StackType >(HiResImages);
  boost::shared_ptr< StackType > LoResStack = InitializeLoResStack<StackType>(LoResImages);
  boost::shared_ptr< StackType > HiResStack = InitializeHiResStack<StackType>(HiResImages);

  // Assert stacks have the same number of slices
  assert(LoResStack->GetSize() == HiResStack->GetSize());

  // initialize stacks' transforms so that 2D images line up at their centres.
  if( vm.count("blockDir") )
    // if working with segmentations already in the right coordinate system,
    // no need to apply transforms
    StackTransforms::InitializeToIdentity(*LoResStack);
  else
  {
    // if working from the original images, apply the necessary translation
    StackTransforms::InitializeWithTranslation( *LoResStack, StackTransforms::GetLoResTranslation("whole_heart") );
    ApplyAdjustments( *LoResStack, LoResFilePaths, Dirs::ConfigDir() + "LoRes_adjustments/");
  }

  StackTransforms::InitializeToCommonCentre( *HiResStack );
  StackTransforms::SetMovingStackCenterWithFixedStack( *LoResStack, *HiResStack );

  // create output dir before write operations
  create_directory( Dirs::ResultsDir() );

  // Generate fixed images to register against
  LoResStack->updateVolumes();
  if( writeImages )
  {
    writeImage< StackType::VolumeType >( LoResStack->GetVolume(), Dirs::ResultsDir() + "LoResStack.mha" );
  }

  // initialise registration framework
  typedef RegistrationBuilder< StackType > RegistrationBuilderType;
  RegistrationBuilderType registrationBuilder;
  RegistrationBuilderType::RegistrationType::Pointer registration = registrationBuilder.GetRegistration();
  StackAligner< StackType > stackAligner(*LoResStack, *HiResStack, registration);

  // Scale parameter space
  OptimizerConfig::SetOptimizerScalesForCenteredRigid2DTransform( registration->GetOptimizer() );

  // Add time and memory probes
  itkProbesCreate();

  // perform centered rigid 2D registration on each pair of slices
  itkProbesStart( "Aligning stacks" );
  stackAligner.Update();
  itkProbesStop( "Aligning stacks" );

  // Report the time and memory taken by the registration
  itkProbesReport( std::cout );

  // write rigid transforms
  if( writeImages )
  {
    HiResStack->updateVolumes();
    writeImage< StackType::VolumeType >( HiResStack->GetVolume(), Dirs::ResultsDir() + "HiResRigidStack.mha" );
    // writeImage< StackType::MaskVolumeType >( HiResStack->Get3DMask()->GetImage(), Dirs::ResultsDir() + "HiResRigidMask.mha" );
  }
  StackTransforms::InitializeFromCurrentTransforms< StackType, itk::CenteredSimilarity2DTransform< double > >(*HiResStack);

  // Scale parameter space
  OptimizerConfig::SetOptimizerScalesForCenteredSimilarity2DTransform( registration->GetOptimizer() );

  // perform similarity rigid 2D registration
  stackAligner.Update();

  // write similarity transforms
  if( writeImages )
  {
    HiResStack->updateVolumes();
    writeImage< StackType::VolumeType >( HiResStack->GetVolume(), Dirs::ResultsDir() + "HiResSimilarityStack.mha" );
  }

  // repeat registration with affine transform
  StackTransforms::InitializeFromCurrentTransforms< StackType, itk::CenteredAffineTransform< double, 2 > >(*HiResStack);
  OptimizerConfig::SetOptimizerScalesForCenteredAffineTransform( registration->GetOptimizer() );
  stackAligner.Update();

  if( writeImages )
  {
    HiResStack->updateVolumes();
    writeImage< StackType::VolumeType >( HiResStack->GetVolume(), Dirs::ResultsDir() + "HiResAffineStack.mha" );
    // writeImage< StackType::MaskVolumeType >( HiResStack->Get3DMask()->GetImage(), Dirs::ResultsDir() + "HiResAffineMask.mha" );
  }

  // Update LoRes as the masks might have shrunk
  LoResStack->updateVolumes();

  // persist mask numberOfTimesTooBig and final metric values
  saveVectorToFiles(HiResStack->GetNumberOfTimesTooBig(), "number_of_times_too_big", HiResFilePaths );
  saveVectorToFiles(stackAligner.GetFinalMetricValues(), "metric_values", HiResFilePaths );

  // write transforms to directories labeled by both ds ratios
  create_directory(Dirs::LoResTransformsDir());
  create_directory(Dirs::HiResTransformsDir());
  Save(*LoResStack, LoResFilePaths, Dirs::LoResTransformsDir());
  Save(*HiResStack, HiResFilePaths, Dirs::HiResTransformsDir());

  return EXIT_SUCCESS;
}

po::variables_map parse_arguments(int argc, char *argv[])
{
  // Declare the supported options.
  po::options_description opts("Options");
  opts.add_options()
      ("help,h", "produce help message")
      ("dataSet", po::value<string>(), "which rat to use")
      ("outputDir", po::value<string>(), "directory to place results")
      ("slice", po::value<string>(), "optional individual slice to register")
      ("blockDir", po::value<string>(), "directory containing LoRes originals")
      ("sliceDir", po::value<string>(), "directory containing HiRes originals")
      ("writeImages", po::bool_switch(), "output images and masks")
  ;

  po::positional_options_description p;
  p.add("dataSet", 1)
   .add("outputDir", 1)
   .add("slice", 1);

  // parse command line
  po::variables_map vm;
	try
	{
  po::store(po::command_line_parser(argc, argv)
            .options(opts)
            .positional(p)
            .run(),
            vm);
	}
	catch (std::exception& e)
	{
	  cerr << "caught command-line parsing error" << endl;
    std::cerr << e.what() << std::endl;
    exit(EXIT_FAILURE);
  }
  po::notify(vm);

  // if help is specified, or positional args aren't present
  if (vm.count("help") || !vm.count("dataSet") || !vm.count("outputDir")) {
    cerr << "Usage: "
      << argv[0] << " [--dataSet=]RatX [--outputDir=]my_dir [Options]"
      << endl << endl;
    cerr << opts << "\n";
    exit(EXIT_FAILURE);
  }

  return vm;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#define BOOST_TEST_MAIN

#define BOOST_TEST_MODULE beadstructure_test
#include <boost/test/unit_test.hpp>
#include <stdexcept>
#include <votca/csg/basebead.h>
#include <votca/csg/beadstructure.h>  // IWYU pragma: keep

using namespace std;
using namespace votca::csg;

class TestBead : public BaseBead {
 public:
  TestBead() : BaseBead(){};
};

BOOST_AUTO_TEST_SUITE(beadstructure_test)

BOOST_AUTO_TEST_CASE(test_beadstructure_constructor) {
  BeadStructure<TestBead> beadstructure;
}

BOOST_AUTO_TEST_CASE(test_beadstructure_beadcount) {
  BeadStructure<TestBead> beadstructure;
  BOOST_CHECK_EQUAL(beadstructure.BeadCount(), 0);
}

BOOST_AUTO_TEST_CASE(test_beadstructure_add_and_getbead) {
  BeadStructure<TestBead> beadstructure;
  TestBead testbead;
  testbead.setId(2);
  beadstructure.AddBead(&testbead);
  BOOST_CHECK_EQUAL(beadstructure.BeadCount(), 1);
  auto testbead2 = beadstructure.getBead(2);
  BOOST_CHECK_EQUAL(testbead2->getId(), testbead.getId());
}

BOOST_AUTO_TEST_CASE(test_beadstructure_ConnectBeads) {
  BeadStructure<TestBead> beadstructure;
  TestBead testbead1;
  testbead1.setId(1);
  testbead1.setName("Carbon");
  TestBead testbead2;
  testbead2.setId(2);
  testbead2.setName("Carbon");
  beadstructure.AddBead(&testbead1);
  beadstructure.AddBead(&testbead2);
  beadstructure.ConnectBeads(1, 2);
}

BOOST_AUTO_TEST_CASE(test_beadstructure_isSingleStructure) {
  BeadStructure<TestBead> beadstructure;

  TestBead testbead1;
  testbead1.setName("Carbon");
  testbead1.setId(1);

  TestBead testbead2;
  testbead2.setName("Carbon");
  testbead2.setId(2);

  TestBead testbead3;
  testbead3.setName("Oxygen");
  testbead3.setId(3);

  TestBead testbead4;
  testbead4.setName("Hydrogen");
  testbead4.setId(4);

  TestBead testbead5;
  testbead5.setName("Hydrogen");
  testbead5.setId(5);

  beadstructure.AddBead(&testbead1);
  beadstructure.AddBead(&testbead2);
  BOOST_CHECK(!beadstructure.isSingleStructure());

  // C - C
  beadstructure.ConnectBeads(1, 2);
  BOOST_CHECK(beadstructure.isSingleStructure());

  // C - C  O
  beadstructure.AddBead(&testbead3);
  BOOST_CHECK(!beadstructure.isSingleStructure());

  // C - C - O
  beadstructure.ConnectBeads(2, 3);
  BOOST_CHECK(beadstructure.isSingleStructure());

  // C - C - O  H - H
  beadstructure.AddBead(&testbead4);
  beadstructure.AddBead(&testbead5);
  beadstructure.ConnectBeads(4, 5);
  BOOST_CHECK(!beadstructure.isSingleStructure());
}

BOOST_AUTO_TEST_CASE(test_beadstructure_isStructureEquivalent) {
  BeadStructure<TestBead> beadstructure1;
  BeadStructure<TestBead> beadstructure2;

  // Beads for bead structure 1
  TestBead testbead1;
  testbead1.setName("Carbon");
  testbead1.setId(1);

  TestBead testbead2;
  testbead2.setName("Carbon");
  testbead2.setId(2);

  TestBead testbead3;
  testbead3.setName("Oxygen");
  testbead3.setId(3);

  TestBead testbead4;
  testbead4.setName("Hydrogen");
  testbead4.setId(4);

  TestBead testbead5;
  testbead5.setName("Hydrogen");
  testbead5.setId(5);

  // Beads for bead structure 2
  TestBead testbead6;
  testbead6.setName("Carbon");
  testbead6.setId(6);

  TestBead testbead7;
  testbead7.setName("Carbon");
  testbead7.setId(7);

  TestBead testbead8;
  testbead8.setName("Oxygen");
  testbead8.setId(8);

  TestBead testbead9;
  testbead9.setName("Hydrogen");
  testbead9.setId(9);

  TestBead testbead10;
  testbead10.setName("Hydrogen");
  testbead10.setId(10);

  BOOST_CHECK(beadstructure1.isStructureEquivalent(beadstructure2));
  beadstructure1.AddBead(&testbead1);
  BOOST_CHECK(!beadstructure1.isStructureEquivalent(beadstructure2));
  beadstructure2.AddBead(&testbead6);
  BOOST_CHECK(beadstructure1.isStructureEquivalent(beadstructure2));

  beadstructure1.AddBead(&testbead2);
  beadstructure2.AddBead(&testbead7);

  beadstructure1.ConnectBeads(1, 2);
  BOOST_CHECK(!beadstructure1.isStructureEquivalent(beadstructure2));
  beadstructure2.ConnectBeads(6, 7);
  BOOST_CHECK(beadstructure1.isStructureEquivalent(beadstructure2));

  beadstructure1.AddBead(&testbead3);
  beadstructure1.AddBead(&testbead4);
  beadstructure1.AddBead(&testbead5);
  beadstructure1.ConnectBeads(2, 3);
  beadstructure1.ConnectBeads(4, 5);

  beadstructure2.AddBead(&testbead10);
  beadstructure2.AddBead(&testbead8);
  beadstructure2.AddBead(&testbead9);
  beadstructure2.ConnectBeads(7, 8);
  beadstructure2.ConnectBeads(9, 10);
  BOOST_CHECK(beadstructure1.isStructureEquivalent(beadstructure2));
}

BOOST_AUTO_TEST_CASE(test_beadstructure_getNeighBeads) {
  BeadStructure<TestBead> beadstructure1;

  // Beads for bead structure 1
  // Make a methane molecule
  //
  //     H
  //     |
  // H - C - H
  //     |
  //     H
  //
  TestBead testbead1;
  testbead1.setName("Hydrogen");
  testbead1.setId(1);

  TestBead testbead2;
  testbead2.setName("Carbon");
  testbead2.setId(2);

  TestBead testbead3;
  testbead3.setName("Hydrogen");
  testbead3.setId(3);

  TestBead testbead4;
  testbead4.setName("Hydrogen");
  testbead4.setId(4);

  TestBead testbead5;
  testbead5.setName("Hydrogen");
  testbead5.setId(5);

  // Make a Water molecule
  //
  // H - O - H
  //

  TestBead testbead6;
  testbead6.setName("Hydrogen");
  testbead6.setId(6);

  TestBead testbead7;
  testbead7.setName("Oxygen");
  testbead7.setId(7);

  TestBead testbead8;
  testbead8.setName("Hydrogen");
  testbead8.setId(8);

  beadstructure1.AddBead(&testbead1);
  beadstructure1.AddBead(&testbead2);
  beadstructure1.AddBead(&testbead3);
  beadstructure1.AddBead(&testbead4);
  beadstructure1.AddBead(&testbead5);
  beadstructure1.AddBead(&testbead6);
  beadstructure1.AddBead(&testbead7);
  beadstructure1.AddBead(&testbead8);

  // At this point non of the beads are connected so should return a vector of
  // size 0
  auto v1 = beadstructure1.getNeighBeads(1);
  BOOST_CHECK_EQUAL(v1.size(), 0);
  auto v2 = beadstructure1.getNeighBeads(2);
  BOOST_CHECK_EQUAL(v2.size(), 0);
  auto v3 = beadstructure1.getNeighBeads(3);
  BOOST_CHECK_EQUAL(v3.size(), 0);
  auto v4 = beadstructure1.getNeighBeads(4);
  BOOST_CHECK_EQUAL(v4.size(), 0);
  auto v5 = beadstructure1.getNeighBeads(5);
  BOOST_CHECK_EQUAL(v5.size(), 0);
  auto v6 = beadstructure1.getNeighBeads(1);
  BOOST_CHECK_EQUAL(v6.size(), 0);
  auto v7 = beadstructure1.getNeighBeads(7);
  BOOST_CHECK_EQUAL(v7.size(), 0);
  auto v8 = beadstructure1.getNeighBeads(8);
  BOOST_CHECK_EQUAL(v8.size(), 0);

  // Connect beads
  beadstructure1.ConnectBeads(1, 2);
  beadstructure1.ConnectBeads(3, 2);
  beadstructure1.ConnectBeads(4, 2);
  beadstructure1.ConnectBeads(5, 2);
  beadstructure1.ConnectBeads(6, 7);
  beadstructure1.ConnectBeads(7, 8);

  v1 = beadstructure1.getNeighBeads(1);
  BOOST_CHECK_EQUAL(v1.size(), 1);
  v2 = beadstructure1.getNeighBeads(2);
  BOOST_CHECK_EQUAL(v2.size(), 4);
  v3 = beadstructure1.getNeighBeads(3);
  BOOST_CHECK_EQUAL(v3.size(), 1);
  v4 = beadstructure1.getNeighBeads(4);
  BOOST_CHECK_EQUAL(v4.size(), 1);
  v5 = beadstructure1.getNeighBeads(5);
  BOOST_CHECK_EQUAL(v5.size(), 1);
  v6 = beadstructure1.getNeighBeads(1);
  BOOST_CHECK_EQUAL(v6.size(), 1);
  v7 = beadstructure1.getNeighBeads(7);
  BOOST_CHECK_EQUAL(v7.size(), 2);
  v8 = beadstructure1.getNeighBeads(8);
  BOOST_CHECK_EQUAL(v8.size(), 1);
}

BOOST_AUTO_TEST_CASE(test_beadstructure_catchError) {

  {
    TestBead testbead1;
    testbead1.setName("Hydrogen");
    testbead1.setId(1);

    TestBead testbead2;
    testbead2.setName("Carbon");
    testbead2.setId(2);

    TestBead testbead3;
    testbead3.setName("Hydrogen");
    testbead3.setId(3);

    TestBead testbead4;
    testbead4.setName("Hydrogen");
    testbead4.setId(4);

    TestBead testbead5;
    testbead5.setName("Hydrogen");
    testbead5.setId(5);

    TestBead testbead6;
    testbead6.setName("Hydrogen");
    testbead6.setId(5);

    BeadStructure<TestBead> beadstructure;
    beadstructure.AddBead(&testbead1);
    beadstructure.AddBead(&testbead2);
    beadstructure.AddBead(&testbead3);
    beadstructure.AddBead(&testbead4);
    beadstructure.AddBead(&testbead5);

    BOOST_CHECK_THROW(beadstructure.AddBead(&testbead6), invalid_argument);
    BOOST_CHECK_THROW(beadstructure.ConnectBeads(0, 1), invalid_argument);
    BOOST_CHECK_THROW(beadstructure.ConnectBeads(5, 6), invalid_argument);
    BOOST_CHECK_THROW(beadstructure.ConnectBeads(1, 1), invalid_argument);
  }
}
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Corrected use of AddBead to reference in beadstructure test<commit_after>/*
 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#define BOOST_TEST_MAIN

#define BOOST_TEST_MODULE beadstructure_test
#include <boost/test/unit_test.hpp>
#include <stdexcept>
#include <votca/csg/basebead.h>
#include <votca/csg/beadstructure.h>  // IWYU pragma: keep

using namespace std;
using namespace votca::csg;

class TestBead : public BaseBead {
 public:
  TestBead() : BaseBead(){};
};

BOOST_AUTO_TEST_SUITE(beadstructure_test)

BOOST_AUTO_TEST_CASE(test_beadstructure_constructor) {
  BeadStructure<TestBead> beadstructure;
}

BOOST_AUTO_TEST_CASE(test_beadstructure_beadcount) {
  BeadStructure<TestBead> beadstructure;
  BOOST_CHECK_EQUAL(beadstructure.BeadCount(), 0);
}

BOOST_AUTO_TEST_CASE(test_beadstructure_add_and_getbead) {
  BeadStructure<TestBead> beadstructure;
  TestBead testbead;
  testbead.setId(2);
  beadstructure.AddBead(testbead);
  BOOST_CHECK_EQUAL(beadstructure.BeadCount(), 1);
  auto testbead2 = beadstructure.getBead(2);
  BOOST_CHECK_EQUAL(testbead2.getId(), testbead.getId());
}

BOOST_AUTO_TEST_CASE(test_beadstructure_ConnectBeads) {
  BeadStructure<TestBead> beadstructure;
  TestBead testbead1;
  testbead1.setId(1);
  testbead1.setName("Carbon");
  TestBead testbead2;
  testbead2.setId(2);
  testbead2.setName("Carbon");
  beadstructure.AddBead(testbead1);
  beadstructure.AddBead(testbead2);
  beadstructure.ConnectBeads(1, 2);
}

BOOST_AUTO_TEST_CASE(test_beadstructure_isSingleStructure) {
  BeadStructure<TestBead> beadstructure;

  TestBead testbead1;
  testbead1.setName("Carbon");
  testbead1.setId(1);

  TestBead testbead2;
  testbead2.setName("Carbon");
  testbead2.setId(2);

  TestBead testbead3;
  testbead3.setName("Oxygen");
  testbead3.setId(3);

  TestBead testbead4;
  testbead4.setName("Hydrogen");
  testbead4.setId(4);

  TestBead testbead5;
  testbead5.setName("Hydrogen");
  testbead5.setId(5);

  beadstructure.AddBead(testbead1);
  beadstructure.AddBead(testbead2);
  BOOST_CHECK(!beadstructure.isSingleStructure());

  // C - C
  beadstructure.ConnectBeads(1, 2);
  BOOST_CHECK(beadstructure.isSingleStructure());

  // C - C  O
  beadstructure.AddBead(testbead3);
  BOOST_CHECK(!beadstructure.isSingleStructure());

  // C - C - O
  beadstructure.ConnectBeads(2, 3);
  BOOST_CHECK(beadstructure.isSingleStructure());

  // C - C - O  H - H
  beadstructure.AddBead(testbead4);
  beadstructure.AddBead(testbead5);
  beadstructure.ConnectBeads(4, 5);
  BOOST_CHECK(!beadstructure.isSingleStructure());
}

BOOST_AUTO_TEST_CASE(test_beadstructure_isStructureEquivalent) {
  BeadStructure<TestBead> beadstructure1;
  BeadStructure<TestBead> beadstructure2;

  // Beads for bead structure 1
  TestBead testbead1;
  testbead1.setName("Carbon");
  testbead1.setId(1);

  TestBead testbead2;
  testbead2.setName("Carbon");
  testbead2.setId(2);

  TestBead testbead3;
  testbead3.setName("Oxygen");
  testbead3.setId(3);

  TestBead testbead4;
  testbead4.setName("Hydrogen");
  testbead4.setId(4);

  TestBead testbead5;
  testbead5.setName("Hydrogen");
  testbead5.setId(5);

  // Beads for bead structure 2
  TestBead testbead6;
  testbead6.setName("Carbon");
  testbead6.setId(6);

  TestBead testbead7;
  testbead7.setName("Carbon");
  testbead7.setId(7);

  TestBead testbead8;
  testbead8.setName("Oxygen");
  testbead8.setId(8);

  TestBead testbead9;
  testbead9.setName("Hydrogen");
  testbead9.setId(9);

  TestBead testbead10;
  testbead10.setName("Hydrogen");
  testbead10.setId(10);

  BOOST_CHECK(beadstructure1.isStructureEquivalent(beadstructure2));
  beadstructure1.AddBead(testbead1);
  BOOST_CHECK(!beadstructure1.isStructureEquivalent(beadstructure2));
  beadstructure2.AddBead(testbead6);
  BOOST_CHECK(beadstructure1.isStructureEquivalent(beadstructure2));

  beadstructure1.AddBead(testbead2);
  beadstructure2.AddBead(testbead7);

  beadstructure1.ConnectBeads(1, 2);
  BOOST_CHECK(!beadstructure1.isStructureEquivalent(beadstructure2));
  beadstructure2.ConnectBeads(6, 7);
  BOOST_CHECK(beadstructure1.isStructureEquivalent(beadstructure2));

  beadstructure1.AddBead(testbead3);
  beadstructure1.AddBead(testbead4);
  beadstructure1.AddBead(testbead5);
  beadstructure1.ConnectBeads(2, 3);
  beadstructure1.ConnectBeads(4, 5);

  beadstructure2.AddBead(testbead10);
  beadstructure2.AddBead(testbead8);
  beadstructure2.AddBead(testbead9);
  beadstructure2.ConnectBeads(7, 8);
  beadstructure2.ConnectBeads(9, 10);
  BOOST_CHECK(beadstructure1.isStructureEquivalent(beadstructure2));
}

BOOST_AUTO_TEST_CASE(test_beadstructure_getNeighBeads) {
  BeadStructure<TestBead> beadstructure1;

  // Beads for bead structure 1
  // Make a methane molecule
  //
  //     H
  //     |
  // H - C - H
  //     |
  //     H
  //
  TestBead testbead1;
  testbead1.setName("Hydrogen");
  testbead1.setId(1);

  TestBead testbead2;
  testbead2.setName("Carbon");
  testbead2.setId(2);

  TestBead testbead3;
  testbead3.setName("Hydrogen");
  testbead3.setId(3);

  TestBead testbead4;
  testbead4.setName("Hydrogen");
  testbead4.setId(4);

  TestBead testbead5;
  testbead5.setName("Hydrogen");
  testbead5.setId(5);

  // Make a Water molecule
  //
  // H - O - H
  //

  TestBead testbead6;
  testbead6.setName("Hydrogen");
  testbead6.setId(6);

  TestBead testbead7;
  testbead7.setName("Oxygen");
  testbead7.setId(7);

  TestBead testbead8;
  testbead8.setName("Hydrogen");
  testbead8.setId(8);

  beadstructure1.AddBead(testbead1);
  beadstructure1.AddBead(testbead2);
  beadstructure1.AddBead(testbead3);
  beadstructure1.AddBead(testbead4);
  beadstructure1.AddBead(testbead5);
  beadstructure1.AddBead(testbead6);
  beadstructure1.AddBead(testbead7);
  beadstructure1.AddBead(testbead8);

  // At this point non of the beads are connected so should return a vector of
  // size 0
  auto v1 = beadstructure1.getNeighBeads(1);
  BOOST_CHECK_EQUAL(v1.size(), 0);
  auto v2 = beadstructure1.getNeighBeads(2);
  BOOST_CHECK_EQUAL(v2.size(), 0);
  auto v3 = beadstructure1.getNeighBeads(3);
  BOOST_CHECK_EQUAL(v3.size(), 0);
  auto v4 = beadstructure1.getNeighBeads(4);
  BOOST_CHECK_EQUAL(v4.size(), 0);
  auto v5 = beadstructure1.getNeighBeads(5);
  BOOST_CHECK_EQUAL(v5.size(), 0);
  auto v6 = beadstructure1.getNeighBeads(1);
  BOOST_CHECK_EQUAL(v6.size(), 0);
  auto v7 = beadstructure1.getNeighBeads(7);
  BOOST_CHECK_EQUAL(v7.size(), 0);
  auto v8 = beadstructure1.getNeighBeads(8);
  BOOST_CHECK_EQUAL(v8.size(), 0);

  // Connect beads
  beadstructure1.ConnectBeads(1, 2);
  beadstructure1.ConnectBeads(3, 2);
  beadstructure1.ConnectBeads(4, 2);
  beadstructure1.ConnectBeads(5, 2);
  beadstructure1.ConnectBeads(6, 7);
  beadstructure1.ConnectBeads(7, 8);

  v1 = beadstructure1.getNeighBeads(1);
  BOOST_CHECK_EQUAL(v1.size(), 1);
  v2 = beadstructure1.getNeighBeads(2);
  BOOST_CHECK_EQUAL(v2.size(), 4);
  v3 = beadstructure1.getNeighBeads(3);
  BOOST_CHECK_EQUAL(v3.size(), 1);
  v4 = beadstructure1.getNeighBeads(4);
  BOOST_CHECK_EQUAL(v4.size(), 1);
  v5 = beadstructure1.getNeighBeads(5);
  BOOST_CHECK_EQUAL(v5.size(), 1);
  v6 = beadstructure1.getNeighBeads(1);
  BOOST_CHECK_EQUAL(v6.size(), 1);
  v7 = beadstructure1.getNeighBeads(7);
  BOOST_CHECK_EQUAL(v7.size(), 2);
  v8 = beadstructure1.getNeighBeads(8);
  BOOST_CHECK_EQUAL(v8.size(), 1);
}

BOOST_AUTO_TEST_CASE(test_beadstructure_catchError) {

  {
    TestBead testbead1;
    testbead1.setName("Hydrogen");
    testbead1.setId(1);

    TestBead testbead2;
    testbead2.setName("Carbon");
    testbead2.setId(2);

    TestBead testbead3;
    testbead3.setName("Hydrogen");
    testbead3.setId(3);

    TestBead testbead4;
    testbead4.setName("Hydrogen");
    testbead4.setId(4);

    TestBead testbead5;
    testbead5.setName("Hydrogen");
    testbead5.setId(5);

    TestBead testbead6;
    testbead6.setName("Hydrogen");
    testbead6.setId(5);

    BeadStructure<TestBead> beadstructure;
    beadstructure.AddBead(testbead1);
    beadstructure.AddBead(testbead2);
    beadstructure.AddBead(testbead3);
    beadstructure.AddBead(testbead4);
    beadstructure.AddBead(testbead5);

    BOOST_CHECK_THROW(beadstructure.AddBead(testbead6), invalid_argument);
    BOOST_CHECK_THROW(beadstructure.ConnectBeads(0, 1), invalid_argument);
    BOOST_CHECK_THROW(beadstructure.ConnectBeads(5, 6), invalid_argument);
    BOOST_CHECK_THROW(beadstructure.ConnectBeads(1, 1), invalid_argument);
  }
}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
///
/// Peak detection routine.
///
/// The routine detects highest value on an array of values and calculates the
/// precise peak location as a mass-center of the 'hump' around the peak value.
///
/// Author        : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// Last changed  : $Date$
// File revision : $Revision: 4 $
//
// $Id$
//
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
//  SoundTouch audio processing library
//  Copyright (c) Olli Parviainen
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
////////////////////////////////////////////////////////////////////////////////

#include <math.h>
#include <assert.h>

#include "PeakFinder.h"

using namespace soundtouch;

#define max(x, y) (((x) > (y)) ? (x) : (y))

PeakFinder::PeakFinder()
{
    minPos = maxPos = 0;
}

// Finds real 'top' of a peak hump from neighnourhood of the given 'peakpos'.
int PeakFinder::findTop(const float *data, int peakpos) const
{
    int i;
    int start, end;
    float refvalue;

    refvalue = data[peakpos];

    // seek within 10 points
    start = peakpos - 10;
    if (start < minPos) start = minPos;
    end = peakpos + 10;
    if (end > maxPos) end = maxPos;

    for (i = start; i <= end; i ++)
    {
        if (data[i] > refvalue)
        {
            peakpos = i;
            refvalue = data[i];
        }
    }

    // failure if max value is at edges of seek range => it's not peak, it's at slope.
    if ((peakpos == start) || (peakpos == end)) return 0;

    return peakpos;
}

// Finds 'ground level' of a peak hump by starting from 'peakpos' and proceeding
// to direction defined by 'direction' until next 'hump' after minimum value will
// begin
int PeakFinder::findGround(const float *data, int peakpos, int direction) const
{
    int lowpos;
    int pos;
    int climb_count;
    float refvalue;
    float delta;

    climb_count = 0;
    refvalue = data[peakpos];
    lowpos = peakpos;

    pos = peakpos;

    while ((pos > minPos+1) && (pos < maxPos-1))
    {
        int prevpos;

        prevpos = pos;
        pos += direction;

        // calculate derivate
        delta = data[pos] - data[prevpos];
        if (delta <= 0)
        {
            // going downhill, ok
            if (climb_count)
            {
                climb_count --;  // decrease climb count
            }

            // check if new minimum found
            if (data[pos] < refvalue)
            {
                // new minimum found
                lowpos = pos;
                refvalue = data[pos];
            }
        }
        else
        {
            // going uphill, increase climbing counter
            climb_count ++;
            if (climb_count > 5) break;    // we've been climbing too long => it's next uphill => quit
        }
    }
    return lowpos;
}

// Find offset where the value crosses the given level, when starting from 'peakpos' and
// proceeds to direction defined in 'direction'
int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, int direction) const
{
    float peaklevel;
    int pos;

    peaklevel = data[peakpos];
    assert(peaklevel >= level);
    pos = peakpos;
    while ((pos >= minPos) && (pos < maxPos))
    {
        if (data[pos + direction] < level) return pos;   // crossing found
        pos += direction;
    }
    return -1;  // not found
}

// Calculates the center of mass location of 'data' array items between 'firstPos' and 'lastPos'
double PeakFinder::calcMassCenter(const float *data, int firstPos, int lastPos) const
{
    int i;
    float sum;
    float wsum;

    sum = 0;
    wsum = 0;
    for (i = firstPos; i <= lastPos; i ++)
    {
        sum += (float)i * data[i];
        wsum += data[i];
    }

    if (wsum < 1e-6) return 0;
    return sum / wsum;
}

/// get exact center of peak near given position by calculating local mass of center
double PeakFinder::getPeakCenter(const float *data, int peakpos) const
{
    float peakLevel;            // peak level
    int crosspos1, crosspos2;   // position where the peak 'hump' crosses cutting level
    float cutLevel;             // cutting value
    float groundLevel;          // ground level of the peak
    int gp1, gp2;               // bottom positions of the peak 'hump'

    // find ground positions.
    gp1 = findGround(data, peakpos, -1);
    gp2 = findGround(data, peakpos, 1);

    groundLevel = 0.5f * (data[gp1] + data[gp2]);
    peakLevel = data[peakpos];

    // calculate 70%-level of the peak
    cutLevel = 0.70f * peakLevel + 0.30f * groundLevel;
    // find mid-level crossings
    crosspos1 = findCrossingLevel(data, cutLevel, peakpos, -1);
    crosspos2 = findCrossingLevel(data, cutLevel, peakpos, 1);

    if ((crosspos1 < 0) || (crosspos2 < 0)) return 0;   // no crossing, no peak..

    // calculate mass center of the peak surroundings
    return calcMassCenter(data, crosspos1, crosspos2);
}

double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
{

    int i;
    int peakpos;                // position of peak level
    double highPeak, peak;

    this->minPos = aminPos;
    this->maxPos = amaxPos;

    // find absolute peak
    peakpos = minPos;
    peak = data[minPos];
    for (i = minPos + 1; i < maxPos; i ++)
    {
        if (data[i] > peak)
        {
            peak = data[i];
            peakpos = i;
        }
    }

    // Calculate exact location of the highest peak mass center
    highPeak = getPeakCenter(data, peakpos);
    peak = highPeak;

    // Now check if the highest peak were in fact harmonic of the true base beat peak
    // - sometimes the highest peak can be Nth harmonic of the true base peak yet
    // just a slightly higher than the true base

    int hp = (int)(highPeak + 0.5);

    for (i = 3; i < 10; i ++)
    {
        double peaktmp, harmonic;
        int i1,i2;

        harmonic = (double)i * 0.5;
        peakpos = (int)(highPeak / harmonic + 0.5f);
        if (peakpos < minPos) break;
        peakpos = findTop(data, peakpos);   // seek true local maximum index
        if (peakpos == 0) continue;         // no local max here

        // calculate mass-center of possible harmonic peak
        peaktmp = getPeakCenter(data, peakpos);

        // accept harmonic peak if
        // (a) it is found
        // (b) is within 4% of the expected harmonic interval
        // (c) has at least half x-corr value of the max. peak

        double diff = harmonic * peaktmp / highPeak;
        if ((diff < 0.96) || (diff > 1.04)) continue;   // peak too afar from expected

        // now compare to highest detected peak
        i1 = (int)(highPeak + 0.5);
        i2 = (int)(peaktmp + 0.5);
        if (data[i2] >= 0.4*data[i1])
        {
            // The harmonic is at least half as high primary peak,
            // thus use the harmonic peak instead
            peak = peaktmp;
        }
    }

    return peak;
}
<commit_msg>Removed piece of dead code<commit_after>////////////////////////////////////////////////////////////////////////////////
///
/// Peak detection routine.
///
/// The routine detects highest value on an array of values and calculates the
/// precise peak location as a mass-center of the 'hump' around the peak value.
///
/// Author        : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// Last changed  : $Date$
// File revision : $Revision: 4 $
//
// $Id$
//
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
//  SoundTouch audio processing library
//  Copyright (c) Olli Parviainen
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
////////////////////////////////////////////////////////////////////////////////

#include <math.h>
#include <assert.h>

#include "PeakFinder.h"

using namespace soundtouch;

#define max(x, y) (((x) > (y)) ? (x) : (y))

PeakFinder::PeakFinder()
{
    minPos = maxPos = 0;
}

// Finds real 'top' of a peak hump from neighnourhood of the given 'peakpos'.
int PeakFinder::findTop(const float *data, int peakpos) const
{
    int i;
    int start, end;
    float refvalue;

    refvalue = data[peakpos];

    // seek within 10 points
    start = peakpos - 10;
    if (start < minPos) start = minPos;
    end = peakpos + 10;
    if (end > maxPos) end = maxPos;

    for (i = start; i <= end; i ++)
    {
        if (data[i] > refvalue)
        {
            peakpos = i;
            refvalue = data[i];
        }
    }

    // failure if max value is at edges of seek range => it's not peak, it's at slope.
    if ((peakpos == start) || (peakpos == end)) return 0;

    return peakpos;
}

// Finds 'ground level' of a peak hump by starting from 'peakpos' and proceeding
// to direction defined by 'direction' until next 'hump' after minimum value will
// begin
int PeakFinder::findGround(const float *data, int peakpos, int direction) const
{
    int lowpos;
    int pos;
    int climb_count;
    float refvalue;
    float delta;

    climb_count = 0;
    refvalue = data[peakpos];
    lowpos = peakpos;

    pos = peakpos;

    while ((pos > minPos+1) && (pos < maxPos-1))
    {
        int prevpos;

        prevpos = pos;
        pos += direction;

        // calculate derivate
        delta = data[pos] - data[prevpos];
        if (delta <= 0)
        {
            // going downhill, ok
            if (climb_count)
            {
                climb_count --;  // decrease climb count
            }

            // check if new minimum found
            if (data[pos] < refvalue)
            {
                // new minimum found
                lowpos = pos;
                refvalue = data[pos];
            }
        }
        else
        {
            // going uphill, increase climbing counter
            climb_count ++;
            if (climb_count > 5) break;    // we've been climbing too long => it's next uphill => quit
        }
    }
    return lowpos;
}

// Find offset where the value crosses the given level, when starting from 'peakpos' and
// proceeds to direction defined in 'direction'
int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, int direction) const
{
    float peaklevel;
    int pos;

    peaklevel = data[peakpos];
    assert(peaklevel >= level);
    pos = peakpos;
    while ((pos >= minPos) && (pos < maxPos))
    {
        if (data[pos + direction] < level) return pos;   // crossing found
        pos += direction;
    }
    return -1;  // not found
}

// Calculates the center of mass location of 'data' array items between 'firstPos' and 'lastPos'
double PeakFinder::calcMassCenter(const float *data, int firstPos, int lastPos) const
{
    int i;
    float sum;
    float wsum;

    sum = 0;
    wsum = 0;
    for (i = firstPos; i <= lastPos; i ++)
    {
        sum += (float)i * data[i];
        wsum += data[i];
    }

    if (wsum < 1e-6) return 0;
    return sum / wsum;
}

/// get exact center of peak near given position by calculating local mass of center
double PeakFinder::getPeakCenter(const float *data, int peakpos) const
{
    float peakLevel;            // peak level
    int crosspos1, crosspos2;   // position where the peak 'hump' crosses cutting level
    float cutLevel;             // cutting value
    float groundLevel;          // ground level of the peak
    int gp1, gp2;               // bottom positions of the peak 'hump'

    // find ground positions.
    gp1 = findGround(data, peakpos, -1);
    gp2 = findGround(data, peakpos, 1);

    groundLevel = 0.5f * (data[gp1] + data[gp2]);
    peakLevel = data[peakpos];

    // calculate 70%-level of the peak
    cutLevel = 0.70f * peakLevel + 0.30f * groundLevel;
    // find mid-level crossings
    crosspos1 = findCrossingLevel(data, cutLevel, peakpos, -1);
    crosspos2 = findCrossingLevel(data, cutLevel, peakpos, 1);

    if ((crosspos1 < 0) || (crosspos2 < 0)) return 0;   // no crossing, no peak..

    // calculate mass center of the peak surroundings
    return calcMassCenter(data, crosspos1, crosspos2);
}

double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
{

    int i;
    int peakpos;                // position of peak level
    double highPeak, peak;

    this->minPos = aminPos;
    this->maxPos = amaxPos;

    // find absolute peak
    peakpos = minPos;
    peak = data[minPos];
    for (i = minPos + 1; i < maxPos; i ++)
    {
        if (data[i] > peak)
        {
            peak = data[i];
            peakpos = i;
        }
    }

    // Calculate exact location of the highest peak mass center
    highPeak = getPeakCenter(data, peakpos);
    peak = highPeak;

    // Now check if the highest peak were in fact harmonic of the true base beat peak
    // - sometimes the highest peak can be Nth harmonic of the true base peak yet
    // just a slightly higher than the true base

    for (i = 3; i < 10; i ++)
    {
        double peaktmp, harmonic;
        int i1,i2;

        harmonic = (double)i * 0.5;
        peakpos = (int)(highPeak / harmonic + 0.5f);
        if (peakpos < minPos) break;
        peakpos = findTop(data, peakpos);   // seek true local maximum index
        if (peakpos == 0) continue;         // no local max here

        // calculate mass-center of possible harmonic peak
        peaktmp = getPeakCenter(data, peakpos);

        // accept harmonic peak if
        // (a) it is found
        // (b) is within 4% of the expected harmonic interval
        // (c) has at least half x-corr value of the max. peak

        double diff = harmonic * peaktmp / highPeak;
        if ((diff < 0.96) || (diff > 1.04)) continue;   // peak too afar from expected

        // now compare to highest detected peak
        i1 = (int)(highPeak + 0.5);
        i2 = (int)(peaktmp + 0.5);
        if (data[i2] >= 0.4*data[i1])
        {
            // The harmonic is at least half as high primary peak,
            // thus use the harmonic peak instead
            peak = peaktmp;
        }
    }

    return peak;
}
<|endoftext|>


<commit_before>/**
 * @file Cosa/Driver/DHT11.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012-2013, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef __COSA_DRIVER_DHT11_HH__
#define __COSA_DRIVER_DHT11_HH__

#include "Cosa/Types.h"
#include "Cosa/Pins.hh"
#include "Cosa/Linkage.hh"

/**
 * DHT11 Humidity & Temperature Sensor device driver. Subclass
 * and implement the event handler, on_event(), to allow periodic
 * read of device (attach to watchdog timeout queue).
 *
 * @section Circuit
 * Connect DHT11 to pin, VCC and ground. A pullup resistor from
 * the pin to VCC should be used. Most DHT11 modules have a built-in
 * pullup resistor.
 *
 * @section Limitations
 * The driver will turn off interrupt handling during data read
 * from the device.
 *
 * @section See Also
 * [1] DHT11 Humidity & Temperature Sensor, Robotics UK,
 * www.droboticsonline.com, http://www.micro4you.com/files/sensor/DHT11.pdf

 * [2] DHTxx Sensor Tutorial, http://learn.adafruit.com/dht

 */
class DHT11 : private Link {
public:
  /** Size of data buffer */
  static const uint8_t DATA_MAX = 5;

  /** Last data elemement index */
  static const uint8_t DATA_LAST = DATA_MAX - 1;

protected:
  /**
   * Data read from the device.
   */
  union data_t {
    uint8_t as_byte[DATA_MAX];
    struct {
      int16_t humidity;
      int16_t temperature;
      uint8_t chksum;
    };
  };

  /**
   * Input/Output pin, data and offset buffer and latest pin level.
   */
  IOPin m_pin;
  data_t m_data;
  data_t m_offset;
  uint8_t m_latest;

  /**
   * Read the next bit from the device given number of level
   * changes. Return one(1) if the bit was set, zero(0) if clear,
   * otherwise a negative error code.
   * @param[in] changes number of level transitions.
   * @return one(1) if the bit was set, zero(0) if clear, otherwise
   * a negative error code(-1).
   */
  int8_t read_bit(uint8_t changes);

  /**
   * Read data from the device. Return true(1) if successful otherwise
   * false(0).
   * @return bool.
   */
  bool read_data();

  /**
   * Adjust data from the device.
   */
  virtual void adjust_data() {}

public:
  /**
   * Construct connection to a DHT11 device on given in/output-pin.
   * Set humidity and temperature calibration offsets to zero.
   * @param[in] pin data.
   */
  DHT11(Board::DigitalPin pin) :
    Link(),
    m_pin(pin)
  {
    m_offset.humidity = 0;
    m_offset.temperature = 0;
  }

  /**
   * Read temperature and humidity from the device. Return true(1) and
   * values if successful otherwise false(0).
   * @param[out] humidity reading.
   * @param[out] temperature reading.
   * @return bool.
   */
  bool read(int16_t& humidity, int16_t& temperature)
  {
    if (!read_data()) return (false);
    humidity = get_humidity();
    temperature = get_temperature();
    return (true);
  }

  /**
   * Return temperature from latest read.
   * @return temperature.
   */
  int16_t get_temperature()
  {
    return (m_data.temperature + m_offset.temperature);
  }

  /**
   * Return humidity from latest read.
   * @return humidity.
   */
  int16_t get_humidity()
  {
    return (m_data.humidity + m_offset.humidity);
  }

  /**
   * Set calibration offset for temperature and humidity readings.
   * The given values are added to the values read from the device.
   * @param[in] temperature.
   * @param[in] humidity.
   */
  void calibrate(int16_t humidity, int16_t temperature)
  {
    m_offset.humidity = humidity;
    m_offset.temperature = temperature;
  }

  /**
   * @override
   * Default device event handler function. Attach to watchdog
   * timer queue, Watchdog::attach(), to allow perodic reading.
   * @param[in] type the type of event.
   * @param[in] value the event value.
   */
  virtual void on_event(uint8_t type, uint16_t value)
  {
    read_data();
  }
};

#endif
<commit_msg>Fixed wrong visibility of const values.<commit_after>/**
 * @file Cosa/Driver/DHT11.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012-2013, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef __COSA_DRIVER_DHT11_HH__
#define __COSA_DRIVER_DHT11_HH__

#include "Cosa/Types.h"
#include "Cosa/Pins.hh"
#include "Cosa/Linkage.hh"

/**
 * DHT11 Humidity & Temperature Sensor device driver. Subclass
 * and implement the event handler, on_event(), to allow periodic
 * read of device (attach to watchdog timeout queue).
 *
 * @section Circuit
 * Connect DHT11 to pin, VCC and ground. A pullup resistor from
 * the pin to VCC should be used. Most DHT11 modules have a built-in
 * pullup resistor.
 *
 * @section Limitations
 * The driver will turn off interrupt handling during data read
 * from the device.
 *
 * @section See Also
 * [1] DHT11 Humidity & Temperature Sensor, Robotics UK,
 * www.droboticsonline.com, http://www.micro4you.com/files/sensor/DHT11.pdf

 * [2] DHTxx Sensor Tutorial, http://learn.adafruit.com/dht

 */
class DHT11 : private Link {
protected:
  /** Size of data buffer */
  static const uint8_t DATA_MAX = 5;

  /** Last data elemement index */
  static const uint8_t DATA_LAST = DATA_MAX - 1;

  /**
   * Data read from the device.
   */
  union data_t {
    uint8_t as_byte[DATA_MAX];
    struct {
      int16_t humidity;
      int16_t temperature;
      uint8_t chksum;
    };
  };

  /**
   * Input/Output pin, data and offset buffer and latest pin level.
   */
  IOPin m_pin;
  data_t m_data;
  data_t m_offset;
  uint8_t m_latest;

  /**
   * Read the next bit from the device given number of level
   * changes. Return one(1) if the bit was set, zero(0) if clear,
   * otherwise a negative error code.
   * @param[in] changes number of level transitions.
   * @return one(1) if the bit was set, zero(0) if clear, otherwise
   * a negative error code(-1).
   */
  int8_t read_bit(uint8_t changes);

  /**
   * Read data from the device. Return true(1) if successful otherwise
   * false(0).
   * @return bool.
   */
  bool read_data();

  /**
   * Adjust data from the device.
   */
  virtual void adjust_data() {}

public:
  /**
   * Construct connection to a DHT11 device on given in/output-pin.
   * Set humidity and temperature calibration offsets to zero.
   * @param[in] pin data.
   */
  DHT11(Board::DigitalPin pin) :
    Link(),
    m_pin(pin)
  {
    m_offset.humidity = 0;
    m_offset.temperature = 0;
  }

  /**
   * Read temperature and humidity from the device. Return true(1) and
   * values if successful otherwise false(0).
   * @param[out] humidity reading.
   * @param[out] temperature reading.
   * @return bool.
   */
  bool read(int16_t& humidity, int16_t& temperature)
  {
    if (!read_data()) return (false);
    humidity = get_humidity();
    temperature = get_temperature();
    return (true);
  }

  /**
   * Return temperature from latest read.
   * @return temperature.
   */
  int16_t get_temperature()
  {
    return (m_data.temperature + m_offset.temperature);
  }

  /**
   * Return humidity from latest read.
   * @return humidity.
   */
  int16_t get_humidity()
  {
    return (m_data.humidity + m_offset.humidity);
  }

  /**
   * Set calibration offset for temperature and humidity readings.
   * The given values are added to the values read from the device.
   * @param[in] temperature.
   * @param[in] humidity.
   */
  void calibrate(int16_t humidity, int16_t temperature)
  {
    m_offset.humidity = humidity;
    m_offset.temperature = temperature;
  }

  /**
   * @override
   * Default device event handler function. Attach to watchdog
   * timer queue, Watchdog::attach(), to allow perodic reading.
   * @param[in] type the type of event.
   * @param[in] value the event value.
   */
  virtual void on_event(uint8_t type, uint16_t value)
  {
    read_data();
  }
};

#endif
<|endoftext|>


<commit_before>#include "easyctrl.h"

Easyctrl_Class Easyctrl;

void MonitoredBase::init(const char *name, bool writeable) {
	this->name = name;
	this->writeable = writeable;

	// Add it to the linked list of known monitored variables
    this->next = Easyctrl.first;
    Easyctrl.first = this;
}

void Easyctrl_Class::writeManifest()  {
    stream->print(F(".fields "));
    stream->println(this->name);
    for(MonitoredBase *i = this->first; i != NULL; i = i->next) {
        i->describe(*this->stream);
    }
    stream->println(F(".endfields"));
}

template<>
void Monitored<int>::parse(const char *data) {
    this->value = strtol(data, NULL, 0);
}

template<>
void Monitored<int>::printTypeName(Stream &stream) {
	stream.print(F("int"));
}

template<>
void Monitored<unsigned int>::parse(const char *data) {
    this->value = strtoul(data, NULL, 0);
}

template<>
void Monitored<unsigned int>::printTypeName(Stream &stream) {
	stream.print(F("uint"));
}

template<>
void Monitored<long>::parse(const char *data) {
    this->value = strtol(data, NULL, 0);
}

template<>
void Monitored<long>::printTypeName(Stream &stream) {
	stream.print(F("long"));
}

template<>
void Monitored<unsigned long>::parse(const char *data) {
    this->value = strtoul(data, NULL, 0);
}

template<>
void Monitored<unsigned long>::printTypeName(Stream &stream) {
	stream.print(F("ulong"));
}

template<>
void Monitored<float>::parse(const char *data) {
    this->value = strtod(data, NULL);
}

template<>
void Monitored<float>::printTypeName(Stream &stream) {
	stream.print(F("float"));
}

template<>
void Monitored<double>::parse(const char *data) {
    this->value = strtod(data, NULL);
}

template<>
void Monitored<double>::printTypeName(Stream &stream) {
	stream.print(F("double"));
}
<commit_msg>Added support for monitored booleans<commit_after>#include "easyctrl.h"

Easyctrl_Class Easyctrl;

void MonitoredBase::init(const char *name, bool writeable) {
	this->name = name;
	this->writeable = writeable;

	// Add it to the linked list of known monitored variables
    this->next = Easyctrl.first;
    Easyctrl.first = this;
}

void Easyctrl_Class::writeManifest()  {
    stream->print(F(".fields "));
    stream->println(this->name);
    for(MonitoredBase *i = this->first; i != NULL; i = i->next) {
        i->describe(*this->stream);
    }
    stream->println(F(".endfields"));
}

template<>
void Monitored<int>::parse(const char *data) {
    this->value = strtol(data, NULL, 0);
}

template<>
void Monitored<int>::printTypeName(Stream &stream) {
	stream.print(F("int"));
}

template<>
void Monitored<unsigned int>::parse(const char *data) {
    this->value = strtoul(data, NULL, 0);
}

template<>
void Monitored<unsigned int>::printTypeName(Stream &stream) {
	stream.print(F("uint"));
}

template<>
void Monitored<long>::parse(const char *data) {
    this->value = strtol(data, NULL, 0);
}

template<>
void Monitored<long>::printTypeName(Stream &stream) {
	stream.print(F("long"));
}

template<>
void Monitored<unsigned long>::parse(const char *data) {
    this->value = strtoul(data, NULL, 0);
}

template<>
void Monitored<unsigned long>::printTypeName(Stream &stream) {
	stream.print(F("ulong"));
}

template<>
void Monitored<float>::parse(const char *data) {
    this->value = strtod(data, NULL);
}

template<>
void Monitored<float>::printTypeName(Stream &stream) {
	stream.print(F("float"));
}

template<>
void Monitored<double>::parse(const char *data) {
    this->value = strtod(data, NULL);
}

template<>
void Monitored<double>::printTypeName(Stream &stream) {
	stream.print(F("double"));
}

template<>
void Monitored<bool>::format(Stream &stream) {
    if(this->value) {
        stream.print(F("true"));
    } else {
        stream.print(F("false"));
    }
}

template<>
void Monitored<bool>::parse(const char *data) {
    if(strncasecmp_P(data, PSTR("true"), 4) == 0 || atoi(data) != 0) {
        this->value = true;
    } else {
        this->value = false;
    }
}

template<>
void Monitored<bool>::printTypeName(Stream &stream) {
    stream.print(F("bool"));
}
<|endoftext|>


<commit_before>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2010, Rice University
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Rice University nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: Elizabeth Fudge */

#include <ompl/base/goals/GoalState.h>
#include <ompl/base/spaces/SE2StateSpace.h>
#include <ompl/base/spaces/DiscreteStateSpace.h>
#include <ompl/control/spaces/RealVectorControlSpace.h>
#include <ompl/control/SimpleSetup.h>
#include <ompl/config.h>
#include <iostream>
#include <limits>
#include <boost/math/constants/constants.hpp>

namespace ob = ompl::base;
namespace oc = ompl::control;

void propagate(const oc::SpaceInformation *si, const ob::State *state,
    const oc::Control* control, const double duration, ob::State *result)
{
    static double timeStep = .01;
    static double carLength = 20.;
    int nsteps = ceil(duration / timeStep);
    double dt = duration / nsteps;
    const double *u = control->as<oc::RealVectorControlSpace::ControlType>()->values;

    ob::CompoundStateSpace::StateType& s = *result->as<ob::CompoundStateSpace::StateType>();
    ob::SE2StateSpace::StateType& se2 = *s.as<ob::SE2StateSpace::StateType>(0);
    ob::RealVectorStateSpace::StateType& velocity = *s.as<ob::RealVectorStateSpace::StateType>(1);
    ob::DiscreteStateSpace::StateType& gear = *s.as<ob::DiscreteStateSpace::StateType>(2);

    si->getStateSpace()->copyState(result, state);
    for(int i=0; i<nsteps; i++)
    {
        se2.setX(se2.getX() + timeStep * velocity.values[0] * cos(se2.getYaw()));
        se2.setY(se2.getY() + timeStep * velocity.values[0] * sin(se2.getYaw()));
        se2.setYaw(se2.getYaw() + timeStep * u[0]);
        velocity.values[0] = velocity.values[0] + timeStep * (u[1]*gear.value);

        // 'guards' - conditions to change gears
        if (gear.value > 0)
        {
            if (gear.value < 3 && velocity.values[0] > 10*(gear.value + 1))
                gear.value++;
            else if (gear.value > 1 && velocity.values[0] < 10*gear.value)
                gear.value--;
        }
        if (!si->satisfiesBounds(result))
            return;
    }
}

// The free space consists of two narrow corridors connected at right angle.
// To make the turn, the car will have to downshift.
bool isStateValid(const oc::SpaceInformation *si, const ob::State *state)
{
  const ob::SE2StateSpace::StateType *se2 =
      state->as<ob::CompoundState>()->as<ob::SE2StateSpace::StateType>(0);
  return si->satisfiesBounds(state) && (se2->getX() < -80. || se2->getY() > 80.);
}

int main(int argc, char* argv[])
{
    // plan for hybrid car in SE(2) with discrete gears
    ob::StateSpacePtr SE2(new ob::SE2StateSpace());
    ob::StateSpacePtr velocity(new ob::RealVectorStateSpace(1));
    // set the range for gears: [-1,3] inclusive
    ob::StateSpacePtr gear(new ob::DiscreteStateSpace(-1,3));
    ob::StateSpacePtr stateSpace = SE2 + velocity + gear;

    // set the bounds for the R^2 part of SE(2)
    ob::RealVectorBounds bounds(2);
    bounds.setLow(-100);
    bounds.setHigh(100);
    SE2->as<ob::SE2StateSpace>()->setBounds(bounds);

    // set the bounds for the velocity
    ob::RealVectorBounds velocityBound(1);
    velocityBound.setLow(0);
    velocityBound.setHigh(60);
    velocity->as<ob::RealVectorStateSpace>()->setBounds(velocityBound);

    // create start and goal states
    ob::ScopedState<> start(stateSpace);
    ob::ScopedState<> goal(stateSpace);

    // Both start and goal are states with high velocity with the car in third gear.
    // However, to make the turn, the car cannot stay in third gear and will have to
    // shift to first gear.
    start[0] = start[1] = -90.; // position
    start[2] = boost::math::constants::pi<double>()/2; // orientation
    start[3] = 40.; // velocity
    start->as<ob::CompoundState>()->as<ob::DiscreteStateSpace::StateType>(2)->value = 3; // gear

    goal[0] = goal[1] = 90.; // position
    goal[2] = 0.; // orientation
    goal[3] = 40.; // velocity
    goal->as<ob::CompoundState>()->as<ob::DiscreteStateSpace::StateType>(2)->value = 3; // gear

    oc::ControlSpacePtr cmanifold(new oc::RealVectorControlSpace(stateSpace, 2));

    // set the bounds for the control manifold
    ob::RealVectorBounds cbounds(2);
    // bounds for steering input
    cbounds.setLow(0, -1.);
    cbounds.setHigh(0, 1.);
    // bounds for brake/gas input
    cbounds.setLow(1, -20.);
    cbounds.setHigh(1, 20.);
    cmanifold->as<oc::RealVectorControlSpace>()->setBounds(cbounds);

    oc::SimpleSetup setup(cmanifold);
    setup.setStartAndGoalStates(start, goal, 5.);
    setup.setStateValidityChecker(boost::bind(
        &isStateValid, setup.getSpaceInformation().get(), _1));
    setup.setStatePropagator(boost::bind(
        &propagate, setup.getSpaceInformation().get(), _1, _2, _3, _4));
    setup.getSpaceInformation()->setPropagationStepSize(.1);
    setup.getSpaceInformation()->setMinMaxControlDuration(2, 3);

    // try to solve the problem
    if (setup.solve(30))
    {
        // print the (approximate) solution path: print states along the path
        // and controls required to get from one state to the next
        oc::PathControl& path(setup.getSolutionPath());

        // print out full state on solution path
        // (format: x, y, theta, v, u0, u1, dt)
        for(unsigned int i=0; i<path.getStateCount(); ++i)
        {
            const ob::State* state = path.getState(i);
            const ob::SE2StateSpace::StateType *se2 =
                state->as<ob::CompoundState>()->as<ob::SE2StateSpace::StateType>(0);
            const ob::RealVectorStateSpace::StateType *velocity =
                state->as<ob::CompoundState>()->as<ob::RealVectorStateSpace::StateType>(1);
            const ob::DiscreteStateSpace::StateType *gear =
                state->as<ob::CompoundState>()->as<ob::DiscreteStateSpace::StateType>(2);
            std::cout << se2->getX() << ' ' << se2->getY() << ' ' << se2->getYaw()
                << ' ' << velocity->values[0] << ' ' << gear->value << ' ';
            if (i==0)
                // null controls applied for zero seconds to get to start state
                std::cout << "0 0 0";
            else
            {
                // print controls and control duration needed to get from state i-1 to state i
                const double* u =
                    path.getControl(i-1)->as<oc::RealVectorControlSpace::ControlType>()->values;
                std::cout << u[0] << ' ' << u[1] << ' ' << path.getControlDuration(i-1);
            }
            std::cout << std::endl;
        }
        if (!setup.haveExactSolutionPath())
        {
            std::cout << "Solution is approximate. Distance to actual goal is " <<
                setup.getProblemDefinition()->getSolutionDifference() << std::endl;
        }
    }

    return 0;
}
<commit_msg>fix trivial bug<commit_after>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2010, Rice University
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Rice University nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: Elizabeth Fudge */

#include <ompl/base/goals/GoalState.h>
#include <ompl/base/spaces/SE2StateSpace.h>
#include <ompl/base/spaces/DiscreteStateSpace.h>
#include <ompl/control/spaces/RealVectorControlSpace.h>
#include <ompl/control/SimpleSetup.h>
#include <ompl/config.h>
#include <iostream>
#include <limits>
#include <boost/math/constants/constants.hpp>

namespace ob = ompl::base;
namespace oc = ompl::control;

void propagate(const oc::SpaceInformation *si, const ob::State *state,
    const oc::Control* control, const double duration, ob::State *result)
{
    static double timeStep = .01;
    static double carLength = 20.;
    int nsteps = ceil(duration / timeStep);
    double dt = duration / nsteps;
    const double *u = control->as<oc::RealVectorControlSpace::ControlType>()->values;

    ob::CompoundStateSpace::StateType& s = *result->as<ob::CompoundStateSpace::StateType>();
    ob::SE2StateSpace::StateType& se2 = *s.as<ob::SE2StateSpace::StateType>(0);
    ob::RealVectorStateSpace::StateType& velocity = *s.as<ob::RealVectorStateSpace::StateType>(1);
    ob::DiscreteStateSpace::StateType& gear = *s.as<ob::DiscreteStateSpace::StateType>(2);

    si->getStateSpace()->copyState(result, state);
    for(int i=0; i<nsteps; i++)
    {
        se2.setX(se2.getX() + dt * velocity.values[0] * cos(se2.getYaw()));
        se2.setY(se2.getY() + dt * velocity.values[0] * sin(se2.getYaw()));
        se2.setYaw(se2.getYaw() + dt * u[0]);
        velocity.values[0] = velocity.values[0] + dt * (u[1]*gear.value);

        // 'guards' - conditions to change gears
        if (gear.value > 0)
        {
            if (gear.value < 3 && velocity.values[0] > 10*(gear.value + 1))
                gear.value++;
            else if (gear.value > 1 && velocity.values[0] < 10*gear.value)
                gear.value--;
        }
        if (!si->satisfiesBounds(result))
            return;
    }
}

// The free space consists of two narrow corridors connected at right angle.
// To make the turn, the car will have to downshift.
bool isStateValid(const oc::SpaceInformation *si, const ob::State *state)
{
  const ob::SE2StateSpace::StateType *se2 =
      state->as<ob::CompoundState>()->as<ob::SE2StateSpace::StateType>(0);
  return si->satisfiesBounds(state) && (se2->getX() < -80. || se2->getY() > 80.);
}

int main(int argc, char* argv[])
{
    // plan for hybrid car in SE(2) with discrete gears
    ob::StateSpacePtr SE2(new ob::SE2StateSpace());
    ob::StateSpacePtr velocity(new ob::RealVectorStateSpace(1));
    // set the range for gears: [-1,3] inclusive
    ob::StateSpacePtr gear(new ob::DiscreteStateSpace(-1,3));
    ob::StateSpacePtr stateSpace = SE2 + velocity + gear;

    // set the bounds for the R^2 part of SE(2)
    ob::RealVectorBounds bounds(2);
    bounds.setLow(-100);
    bounds.setHigh(100);
    SE2->as<ob::SE2StateSpace>()->setBounds(bounds);

    // set the bounds for the velocity
    ob::RealVectorBounds velocityBound(1);
    velocityBound.setLow(0);
    velocityBound.setHigh(60);
    velocity->as<ob::RealVectorStateSpace>()->setBounds(velocityBound);

    // create start and goal states
    ob::ScopedState<> start(stateSpace);
    ob::ScopedState<> goal(stateSpace);

    // Both start and goal are states with high velocity with the car in third gear.
    // However, to make the turn, the car cannot stay in third gear and will have to
    // shift to first gear.
    start[0] = start[1] = -90.; // position
    start[2] = boost::math::constants::pi<double>()/2; // orientation
    start[3] = 40.; // velocity
    start->as<ob::CompoundState>()->as<ob::DiscreteStateSpace::StateType>(2)->value = 3; // gear

    goal[0] = goal[1] = 90.; // position
    goal[2] = 0.; // orientation
    goal[3] = 40.; // velocity
    goal->as<ob::CompoundState>()->as<ob::DiscreteStateSpace::StateType>(2)->value = 3; // gear

    oc::ControlSpacePtr cmanifold(new oc::RealVectorControlSpace(stateSpace, 2));

    // set the bounds for the control manifold
    ob::RealVectorBounds cbounds(2);
    // bounds for steering input
    cbounds.setLow(0, -1.);
    cbounds.setHigh(0, 1.);
    // bounds for brake/gas input
    cbounds.setLow(1, -20.);
    cbounds.setHigh(1, 20.);
    cmanifold->as<oc::RealVectorControlSpace>()->setBounds(cbounds);

    oc::SimpleSetup setup(cmanifold);
    setup.setStartAndGoalStates(start, goal, 5.);
    setup.setStateValidityChecker(boost::bind(
        &isStateValid, setup.getSpaceInformation().get(), _1));
    setup.setStatePropagator(boost::bind(
        &propagate, setup.getSpaceInformation().get(), _1, _2, _3, _4));
    setup.getSpaceInformation()->setPropagationStepSize(.1);
    setup.getSpaceInformation()->setMinMaxControlDuration(2, 3);

    // try to solve the problem
    if (setup.solve(30))
    {
        // print the (approximate) solution path: print states along the path
        // and controls required to get from one state to the next
        oc::PathControl& path(setup.getSolutionPath());

        // print out full state on solution path
        // (format: x, y, theta, v, u0, u1, dt)
        for(unsigned int i=0; i<path.getStateCount(); ++i)
        {
            const ob::State* state = path.getState(i);
            const ob::SE2StateSpace::StateType *se2 =
                state->as<ob::CompoundState>()->as<ob::SE2StateSpace::StateType>(0);
            const ob::RealVectorStateSpace::StateType *velocity =
                state->as<ob::CompoundState>()->as<ob::RealVectorStateSpace::StateType>(1);
            const ob::DiscreteStateSpace::StateType *gear =
                state->as<ob::CompoundState>()->as<ob::DiscreteStateSpace::StateType>(2);
            std::cout << se2->getX() << ' ' << se2->getY() << ' ' << se2->getYaw()
                << ' ' << velocity->values[0] << ' ' << gear->value << ' ';
            if (i==0)
                // null controls applied for zero seconds to get to start state
                std::cout << "0 0 0";
            else
            {
                // print controls and control duration needed to get from state i-1 to state i
                const double* u =
                    path.getControl(i-1)->as<oc::RealVectorControlSpace::ControlType>()->values;
                std::cout << u[0] << ' ' << u[1] << ' ' << path.getControlDuration(i-1);
            }
            std::cout << std::endl;
        }
        if (!setup.haveExactSolutionPath())
        {
            std::cout << "Solution is approximate. Distance to actual goal is " <<
                setup.getProblemDefinition()->getSolutionDifference() << std::endl;
        }
    }

    return 0;
}
<|endoftext|>