<commit_before>/** @file
 *
 * @ingroup foundationLibrary
 *
 * @brief #TTInterpolateTest is an class used for unit tests of the interpolation algorithms in #TTInterpolate.h.
 *
 * @details
 *
 * @authors Trond Lossius
 *
 * @copyright Copyright © 2008, Timothy Place @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTInterpolate.test.h"

#define thisTTClass			TTInterpolateTest
#define thisTTClassName		"interpolate.test"
#define thisTTClassTags		"test, foundation"

/** Constructor macro
 */
TT_OBJECT_CONSTRUCTOR
{;}

/** Destructor
 */
TTInterpolateTest::~TTInterpolateTest()
{;}

#pragma mark -
#pragma mark Test for the various interpolation algorithms
#pragma mark -

/** Perform one linear interpolation and compare the outcome to expected value.
 @param x0				Sample value at prior integer index
 @param x1				Sample value at next integer index
 @param delta			The fractional value for which we want to perform the interpolation.
						delta=0 => x0 @n
						delta=1 => x1
 @param expectedValue	The expected outcome of the interpolation
 @return				TRUE if the interpolat returnes the expected value, else FALSE
 */
TTFloat64 InterpolateAndTestLinear(const TTFloat64 x0, const TTFloat64 x1, const TTFloat64& aDelta, TTFloat64 anExpectedValue)
{
	TTFloat64 interpolatedValue = TTInterpolateLinear(x0, x1, aDelta);
	TTBoolean result = TTTestFloatEquivalence(interpolatedValue , anExpectedValue);
	if (!result)
		TTTestLog("BAD INTERPOLATION @ delta=%.5f  ( value=%.10f   expected=%.10f )", aDelta, interpolatedValue, anExpectedValue);
	return result;
}

/** Test for correct linear interpolations performance.
 @param anErrorCount			The number of asserts that failed
 @param aTestAssertionCount		The numebr of asserts carried out
 */
void TestLinear(int& anErrorCount, int& aTestAssertionCount)
{
	int			badSampleCount = 0;

	TTFloat64	x0 =  3.0;
	TTFloat64	x1 = -1.0;

	TTTestLog("");
	TTTestLog("Testing linear interpolation");

	badSampleCount += !InterpolateAndTestLinear(x0, x1, 0.00,  3.0);
	badSampleCount += !InterpolateAndTestLinear(x0, x1, 0.25,  2.0);
	badSampleCount += !InterpolateAndTestLinear(x0, x1, 0.50,  1.0);
	badSampleCount += !InterpolateAndTestLinear(x0, x1, 0.75,  0.0);
	badSampleCount += !InterpolateAndTestLinear(x0, x1, 1.00, -1.0);

	TTTestAssertion("Produces expected results with linear interpolation",
					badSampleCount == 0,
					aTestAssertionCount,
					anErrorCount);
}

/** Perform one cosine interpolation and compare the outcome to expected value.
 @param x0				Sample value at prior integer index
 @param x1				Sample value at next integer index
 @param aDelta			The fractional value for which we want to perform the interpolation.
 aDelta=0 => x0 @n
 aDelta=1 => x1
 @param expectedValue	The expected outcome of the interpolation
 @return				TRUE if the interpolat returnes the expected value, else FALSE
 */
TTFloat64 InterpolateAndTestCosine(const TTFloat64 x0, const TTFloat64 x1, const TTFloat64& aDelta, TTFloat64 anExpectedValue)
{
	TTFloat64 interpolatedValue = TTInterpolateCosine(x0, x1, aDelta);
	TTBoolean result = TTTestFloatEquivalence(interpolatedValue , anExpectedValue);
	if (!result)
		TTTestLog("BAD INTERPOLATION @ delta=%.5f  ( value=%.10f   expected=%.10f )", aDelta, interpolatedValue, anExpectedValue);
	return result;
}

/** Test for correct cosine interpolations performance.
 @param anErrorCount			The number of asserts that failed
 @param aTestAssertionCount		The numebr of asserts carried out
 */
void TestCosine(int& anErrorCount, int& aTestAssertionCount)
{
	int			badSampleCount = 0;

	TTFloat64	x0 =  3.0;
	TTFloat64	x1 = -1.0;

	TTTestLog("");
	TTTestLog("Testing cosine interpolation");

	badSampleCount += !InterpolateAndTestCosine(x0, x1, 0.00,     3.0);
	badSampleCount += !InterpolateAndTestCosine(x0, x1, (1./3.),  2.0);
	badSampleCount += !InterpolateAndTestCosine(x0, x1, 0.50,     1.0);
	badSampleCount += !InterpolateAndTestCosine(x0, x1, (2./3.),  0.0);
	badSampleCount += !InterpolateAndTestCosine(x0, x1, 1.00,    -1.0);

	TTTestAssertion("Produces expected results with linear interpolation",
					badSampleCount == 0,
					aTestAssertionCount,
					anErrorCount);
}

/** Perform one cubic interpolation and compare the outcome to expected value.
 @param x0				Sample value at integer index prior to x0
 @param x1				Sample value at prior integer index
 @param x2				Sample value at next integer index
 @param x3				Sample value at integer index after y
 @param aDelta			Fractional location between x1 (0) and x2 (1)
 @param delta			The fractional value for which we want to perform the interpolation.
 aDelta=0 => x0 @n
 aDelta=1 => x1
 @param expectedValue	The expected outcome of the interpolation
 @return				TRUE if the interpolat returnes the expected value, else FALSE
 */
TTFloat64 InterpolateAndTestCubic(const TTFloat64 x0, const TTFloat64 x1, const TTFloat64 x2, const TTFloat64 x3, const TTFloat64& aDelta, TTFloat64 anExpectedValue)
{
	TTFloat64 interpolatedValue = TTInterpolateCubic(x0, x1, x2, x3, aDelta);
	TTBoolean result = TTTestFloatEquivalence(interpolatedValue , anExpectedValue);
	if (!result)
		TTTestLog("BAD INTERPOLATION @ delta=%.5f  ( value=%.10f   expected=%.10f )", aDelta, interpolatedValue, anExpectedValue);
	return result;
}

/** Test for correct cubic interpolations performance.
 @param anErrorCount			The number of asserts that failed
 @param aTestAssertionCount		The numebr of asserts carried out
 */
void TestCubic(int& anErrorCount, int& aTestAssertionCount)
{
	/* x(delta) = cos (PI*delta) + delta + 1
	 This gives the following input values to the interpolating function:
	 x(-1) = -1
	 x( 0) =  2
	 x( 1) =  1
	 x( 2) =  4

	 The difference is calculated as
	 ∆x(delta) = (x(delta+1)-x(delta-1)) / 2

	 This leads to:

	 ∆x(0) = ( 1 -(-1) )/2 = 1
	 ∆x(1) = ( 4 - 2)/2 = 1

	 The cubic interpolation function is then required to fullfil the following four conditions:

	 (A) f( 0) =  2
	 (B) f( 1) =  1
	 (C) f'(0) = 1
	 (D) f'(1) = 1

	 Analytically, when solved, these four conditions are fulfilled by the following 3rd order polynomial:
	 f(x) = 4 x^3 - 6 x^2 + x + 2

	 The following test compares interpolated values to expected values for this function.
	 */

	int badSampleCount = 0;

	TTFloat64 x0 = -1.0;
	TTFloat64 x1 =  2.0;
	TTFloat64 x2 =  1.0;
	TTFloat64 x3 =  4.0;

	TTTestLog("");
	TTTestLog("Testing cubic interpolation");

	// Test for delta = -1 => f(delta) = -9
	badSampleCount += !InterpolateAndTestCubic(x0, x1, x2, x3, -1.00, -9.0);
	// Test for delta = 0 => f(delta) = 2
	badSampleCount += !InterpolateAndTestCubic(x0, x1, x2, x3,  0.00,  2.0);
	// Test for delta = 1 => f(delta) = 1
	badSampleCount += !InterpolateAndTestCubic(x0, x1, x2, x3,  1.00,  1.0);
	// Test for delta = 2 => f(delta) = 12
	badSampleCount += !InterpolateAndTestCubic(x0, x1, x2, x3,  2.00, 12.0);

	TTTestAssertion("Produces expected results with cubic interpolation",
					badSampleCount == 0,
					aTestAssertionCount,
					anErrorCount);
}

#pragma mark -
#pragma mark The main function
#pragma mark -

// The main test method
TTErr TTInterpolateTest::test(TTValue& returnedTestInfo)
{
	int	errorCount = 0;
	int testAssertionCount = 0;

	TestLinear(errorCount, testAssertionCount);
	TestCosine(errorCount, testAssertionCount);
	TestCubic(errorCount, testAssertionCount);

	return TTTestFinish(testAssertionCount, errorCount, returnedTestInfo);
}

<commit_msg>Improving/clarifying documentation comments for the cubic test<commit_after>/** @file
 *
 * @ingroup foundationLibrary
 *
 * @brief #TTInterpolateTest is an class used for unit tests of the interpolation algorithms in #TTInterpolate.h.
 *
 * @details
 *
 * @authors Trond Lossius
 *
 * @copyright Copyright © 2008, Timothy Place @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTInterpolate.test.h"

#define thisTTClass			TTInterpolateTest
#define thisTTClassName		"interpolate.test"
#define thisTTClassTags		"test, foundation"

/** Constructor macro
 */
TT_OBJECT_CONSTRUCTOR
{;}

/** Destructor
 */
TTInterpolateTest::~TTInterpolateTest()
{;}

#pragma mark -
#pragma mark Test for the various interpolation algorithms
#pragma mark -

/** Perform one linear interpolation and compare the outcome to expected value.
 @param x0				Sample value at prior integer index
 @param x1				Sample value at next integer index
 @param delta			The fractional value for which we want to perform the interpolation.
						delta=0 => x0 @n
						delta=1 => x1
 @param expectedValue	The expected outcome of the interpolation
 @return				TRUE if the interpolat returnes the expected value, else FALSE
 */
TTFloat64 InterpolateAndTestLinear(const TTFloat64 x0, const TTFloat64 x1, const TTFloat64& aDelta, TTFloat64 anExpectedValue)
{
	TTFloat64 interpolatedValue = TTInterpolateLinear(x0, x1, aDelta);
	TTBoolean result = TTTestFloatEquivalence(interpolatedValue , anExpectedValue);
	if (!result)
		TTTestLog("BAD INTERPOLATION @ delta=%.5f  ( value=%.10f   expected=%.10f )", aDelta, interpolatedValue, anExpectedValue);
	return result;
}

/** Test for correct linear interpolations performance.
 @param anErrorCount			The number of asserts that failed
 @param aTestAssertionCount		The numebr of asserts carried out
 */
void TestLinear(int& anErrorCount, int& aTestAssertionCount)
{
	int			badSampleCount = 0;

	TTFloat64	x0 =  3.0;
	TTFloat64	x1 = -1.0;

	TTTestLog("");
	TTTestLog("Testing linear interpolation");

	badSampleCount += !InterpolateAndTestLinear(x0, x1, 0.00,  3.0);
	badSampleCount += !InterpolateAndTestLinear(x0, x1, 0.25,  2.0);
	badSampleCount += !InterpolateAndTestLinear(x0, x1, 0.50,  1.0);
	badSampleCount += !InterpolateAndTestLinear(x0, x1, 0.75,  0.0);
	badSampleCount += !InterpolateAndTestLinear(x0, x1, 1.00, -1.0);

	TTTestAssertion("Produces expected results with linear interpolation",
					badSampleCount == 0,
					aTestAssertionCount,
					anErrorCount);
}

/** Perform one cosine interpolation and compare the outcome to expected value.
 @param x0				Sample value at prior integer index
 @param x1				Sample value at next integer index
 @param aDelta			The fractional value for which we want to perform the interpolation.
 aDelta=0 => x0 @n
 aDelta=1 => x1
 @param expectedValue	The expected outcome of the interpolation
 @return				TRUE if the interpolat returnes the expected value, else FALSE
 */
TTFloat64 InterpolateAndTestCosine(const TTFloat64 x0, const TTFloat64 x1, const TTFloat64& aDelta, TTFloat64 anExpectedValue)
{
	TTFloat64 interpolatedValue = TTInterpolateCosine(x0, x1, aDelta);
	TTBoolean result = TTTestFloatEquivalence(interpolatedValue , anExpectedValue);
	if (!result)
		TTTestLog("BAD INTERPOLATION @ delta=%.5f  ( value=%.10f   expected=%.10f )", aDelta, interpolatedValue, anExpectedValue);
	return result;
}

/** Test for correct cosine interpolations performance.
 @param anErrorCount			The number of asserts that failed
 @param aTestAssertionCount		The numebr of asserts carried out
 */
void TestCosine(int& anErrorCount, int& aTestAssertionCount)
{
	int			badSampleCount = 0;

	TTFloat64	x0 =  3.0;
	TTFloat64	x1 = -1.0;

	TTTestLog("");
	TTTestLog("Testing cosine interpolation");

	badSampleCount += !InterpolateAndTestCosine(x0, x1, 0.00,     3.0);
	badSampleCount += !InterpolateAndTestCosine(x0, x1, (1./3.),  2.0);
	badSampleCount += !InterpolateAndTestCosine(x0, x1, 0.50,     1.0);
	badSampleCount += !InterpolateAndTestCosine(x0, x1, (2./3.),  0.0);
	badSampleCount += !InterpolateAndTestCosine(x0, x1, 1.00,    -1.0);

	TTTestAssertion("Produces expected results with linear interpolation",
					badSampleCount == 0,
					aTestAssertionCount,
					anErrorCount);
}

/** Perform one cubic interpolation and compare the outcome to expected value.
 @param x0				Sample value at integer index prior to x0
 @param x1				Sample value at prior integer index
 @param x2				Sample value at next integer index
 @param x3				Sample value at integer index after y
 @param aDelta			Fractional location between x1 (0) and x2 (1)
 @param delta			The fractional value for which we want to perform the interpolation.
 aDelta=0 => x0 @n
 aDelta=1 => x1
 @param expectedValue	The expected outcome of the interpolation
 @return				TRUE if the interpolat returnes the expected value, else FALSE
 */
TTFloat64 InterpolateAndTestCubic(const TTFloat64 x0, const TTFloat64 x1, const TTFloat64 x2, const TTFloat64 x3, const TTFloat64& aDelta, TTFloat64 anExpectedValue)
{
	TTFloat64 interpolatedValue = TTInterpolateCubic(x0, x1, x2, x3, aDelta);
	TTBoolean result = TTTestFloatEquivalence(interpolatedValue , anExpectedValue);
	if (!result)
		TTTestLog("BAD INTERPOLATION @ delta=%.5f  ( value=%.10f   expected=%.10f )", aDelta, interpolatedValue, anExpectedValue);
	return result;
}

/** Test for correct cubic interpolations performance.
 @param anErrorCount			The number of asserts that failed
 @param aTestAssertionCount		The numebr of asserts carried out
 */
void TestCubic(int& anErrorCount, int& aTestAssertionCount)
{
	/* We perform the interpolation on four values of the following function:
	 g(delta) = cos (PI*delta) + delta + 1

	 This gives the following input values to the interpolating function:

	 g(-1) = -1
	 g( 0) =  2
	 g( 1) =  1
	 g( 2) =  4

	 The difference is calculated as
	 ∆g(delta) = (g(delta+1)-g(delta-1)) / 2

	 This leads to:

	 ∆g(0) = ( 1 -(-1) )/2 = 1
	 ∆g(1) = ( 4 - 2)/2 = 1

	 The cubic interpolation function f(delta) is then required to fullfil the following four conditions:

	 (A) f( 0) =  2
	 (B) f( 1) =  1
	 (C) f'(0) = 1
	 (D) f'(1) = 1

	 Analytically, when solved, these four conditions are fulfilled by the following 3rd order polynomial:
	 f(delta) = 4 delta^3 - 6 delta^2 + delta + 2

	 The following test compares interpolated values to expected values for this function.
	 */

	int badSampleCount = 0;

	TTFloat64 x0 = -1.0;
	TTFloat64 x1 =  2.0;
	TTFloat64 x2 =  1.0;
	TTFloat64 x3 =  4.0;

	TTTestLog("");
	TTTestLog("Testing cubic interpolation");

	// Test for delta = -1 => f(delta) = -9
	badSampleCount += !InterpolateAndTestCubic(x0, x1, x2, x3, -1.00, -9.0);
	// Test for delta = 0 => f(delta) = 2
	badSampleCount += !InterpolateAndTestCubic(x0, x1, x2, x3,  0.00,  2.0);
	// Test for delta = 1 => f(delta) = 1
	badSampleCount += !InterpolateAndTestCubic(x0, x1, x2, x3,  1.00,  1.0);
	// Test for delta = 2 => f(delta) = 12
	badSampleCount += !InterpolateAndTestCubic(x0, x1, x2, x3,  2.00, 12.0);

	TTTestAssertion("Produces expected results with cubic interpolation",
					badSampleCount == 0,
					aTestAssertionCount,
					anErrorCount);
}

#pragma mark -
#pragma mark The main function
#pragma mark -

// The main test method
TTErr TTInterpolateTest::test(TTValue& returnedTestInfo)
{
	int	errorCount = 0;
	int testAssertionCount = 0;

	TestLinear(errorCount, testAssertionCount);
	TestCosine(errorCount, testAssertionCount);
	TestCubic(errorCount, testAssertionCount);

	return TTTestFinish(testAssertionCount, errorCount, returnedTestInfo);
}

<|endoftext|>


<commit_before>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  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.
 *
 *  @file JPetTaskChainExecutor.cpp
 */

#include "JPetTaskChainExecutor.h"
#include <cassert>
#include "../JPetTaskInterface/JPetTaskInterface.h"
#include "../JPetParamGetterAscii/JPetParamGetterAscii.h"
#include "../JPetParamGetterAscii/JPetParamSaverAscii.h"
#include "../JPetLoggerInclude.h"
#include "JPetTaskChainExecutorUtils.h"
#include "../JPetOptionsGenerator/JPetOptionsTypeHandler.h"
#include <memory>
#include <chrono>

using boost::any_cast;

JPetTaskChainExecutor::JPetTaskChainExecutor(TaskGeneratorChain* taskGeneratorChain, int processedFileId, JPetOptions opt) :
  fInputSeqId(processedFileId),
  fParamManager(0),
  ftaskGeneratorChain(taskGeneratorChain),
  fOptions(opt)
{
  fParamManager = JPetTaskChainExecutorUtils::generateParamManager(fOptions);
  if (taskGeneratorChain) {
    for (auto taskGenerator : *ftaskGeneratorChain) {
      auto task = taskGenerator();
      ///@todo change it
      (dynamic_cast<JPetTaskIO*>(task))->setParamManager(fParamManager);
      fTasks.push_back(task);
    }
  } else {
    ERROR("taskGeneratorChain is null while constructing JPetTaskChainExecutor");
  }
}

bool JPetTaskChainExecutor::preprocessing(const JPetOptions& options, JPetParamManager* manager, std::list<JPetTaskRunnerInterface*>& tasks)
{
  JPetTaskChainExecutorUtils utils;
  return utils.process(options, manager, tasks);
}

bool JPetTaskChainExecutor::process()
{
  namespace stdc = std::chrono;
  std::vector<std::pair<std::string, stdc::seconds>> elapsedTime;
  auto startTime = stdc::system_clock::now();

  if (!preprocessing(fOptions, fParamManager, fTasks)) {
    ERROR("Error in preprocessing");
    return false;
  }

  elapsedTime.push_back(std::make_pair("Preprocessing", stdc::duration_cast< stdc::seconds > (stdc::system_clock::now() - startTime)));

  for (auto currentTask = fTasks.begin(); currentTask != fTasks.end(); currentTask++) {
    JPetOptions::Options currOpts = fOptions.getOptions();
    if (currentTask != fTasks.begin()) {
      /// Ignore the event range options for all but the first task.
      currOpts = JPetOptions::resetEventRange(currOpts);
      /// For all but the first task,
      /// the input path must be changed if
      /// the output path argument -o was given, because the input
      /// data for them will lay in the location defined by -o.
      auto outPath  = any_cast<std::string>(currOpts.at("outputPath_std::string"));
      if (!outPath.empty()) {
        currOpts.at("inputFile_std::string") = outPath + JPetCommonTools::extractPathFromFile(any_cast<std::string>(currOpts.at("inputFile_std::string"))) + JPetCommonTools::extractFileNameFromFullPath(any_cast<std::string>(currOpts.at("inputFile_std::string")));
      }
    }
    auto taskCurr = dynamic_cast<JPetTask*> (dynamic_cast<JPetTaskLoader*>(*currentTask)->getTask());
    //auto taskCurr = std::dynamic_pointer_cast<JPetTask>((*currentTask)->getTask());
    auto taskName = taskCurr->GetName();
    INFO(Form("Starting task: %s", taskName));
    JPetTaskChainExecutor::printCurrentOptionsToLog(currOpts);
    /// @todo fix it
    auto taskRunnerCurr =  dynamic_cast<JPetTaskIO*> (*currentTask);
    taskRunnerCurr->init(currOpts);
    taskRunnerCurr->exec();
    taskRunnerCurr->terminate();

    elapsedTime.push_back(std::make_pair("task " + std::string(taskName), stdc::duration_cast< stdc::seconds > (stdc::system_clock::now() - startTime)));
    INFO(Form("Finished task: %s", taskName));
  }
  for (auto& el : elapsedTime) {
    INFO("Elapsed time for " + el.first + ":" + el.second.count() + " [s]");
  }
  auto total = std::accumulate(elapsedTime.begin(),
                               elapsedTime.end(),
                               stdc::seconds (0),
  [](const stdc::seconds prev, const std::pair <std::string, stdc::seconds>& el) {
    return prev + el.second;
  }
                              );
  INFO(std::string("Total elapsed time:") + total.count() + " [s]");

  return true;
}

void JPetTaskChainExecutor::printCurrentOptionsToLog(const JPetOptions::Options& currOpts)
{
  INFO("Current options:");
  std::vector<std::string> allowedTypes;
  JPetOptionsTypeHandler forGettingAllowedTypes(allowedTypes);
  for (auto a : currOpts) {
    allowedTypes.push_back(forGettingAllowedTypes.getTypeOfOption(a.first));
  }
  JPetOptionsTypeHandler typeHandler(allowedTypes);
  auto stringOptions = typeHandler.anyMapToStringMap(currOpts);
  for (const auto& el : stringOptions) {
    INFO(el.first + "=" + el.second);
  }
}

void* JPetTaskChainExecutor::processProxy(void* runner)
{
  assert(runner);
  static_cast<JPetTaskChainExecutor*>(runner)->process();
  return 0;
}

TThread* JPetTaskChainExecutor::run()
{
  TThread* thread = new TThread(std::to_string(fInputSeqId).c_str(), processProxy, (void*)this);
  assert(thread);
  thread->Run();
  return thread;
}

JPetTaskChainExecutor::~JPetTaskChainExecutor()
{
  for (auto& task : fTasks) {
    if (task) {
      delete task;
      task = 0;
    }
  }
}

<commit_msg>Remove unnecessary dynamic_cast from the JPetTaskChainExecutor<commit_after>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  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.
 *
 *  @file JPetTaskChainExecutor.cpp
 */

#include "JPetTaskChainExecutor.h"
#include <cassert>
#include "../JPetTaskInterface/JPetTaskInterface.h"
#include "../JPetParamGetterAscii/JPetParamGetterAscii.h"
#include "../JPetParamGetterAscii/JPetParamSaverAscii.h"
#include "../JPetLoggerInclude.h"
#include "JPetTaskChainExecutorUtils.h"
#include "../JPetOptionsGenerator/JPetOptionsTypeHandler.h"
#include <memory>
#include <chrono>

using boost::any_cast;

JPetTaskChainExecutor::JPetTaskChainExecutor(TaskGeneratorChain* taskGeneratorChain, int processedFileId, JPetOptions opt) :
  fInputSeqId(processedFileId),
  fParamManager(0),
  ftaskGeneratorChain(taskGeneratorChain),
  fOptions(opt)
{
  fParamManager = JPetTaskChainExecutorUtils::generateParamManager(fOptions);
  if (taskGeneratorChain) {
    for (auto taskGenerator : *ftaskGeneratorChain) {
      auto task = taskGenerator();
      ///@todo change it
      (dynamic_cast<JPetTaskIO*>(task))->setParamManager(fParamManager);
      fTasks.push_back(task);
    }
  } else {
    ERROR("taskGeneratorChain is null while constructing JPetTaskChainExecutor");
  }
}

bool JPetTaskChainExecutor::preprocessing(const JPetOptions& options, JPetParamManager* manager, std::list<JPetTaskRunnerInterface*>& tasks)
{
  JPetTaskChainExecutorUtils utils;
  return utils.process(options, manager, tasks);
}

bool JPetTaskChainExecutor::process()
{
  namespace stdc = std::chrono;
  std::vector<std::pair<std::string, stdc::seconds>> elapsedTime;
  auto startTime = stdc::system_clock::now();

  if (!preprocessing(fOptions, fParamManager, fTasks)) {
    ERROR("Error in preprocessing");
    return false;
  }

  elapsedTime.push_back(std::make_pair("Preprocessing", stdc::duration_cast< stdc::seconds > (stdc::system_clock::now() - startTime)));

  for (auto currentTask = fTasks.begin(); currentTask != fTasks.end(); currentTask++) {
    JPetOptions::Options currOpts = fOptions.getOptions();
    if (currentTask != fTasks.begin()) {
      /// Ignore the event range options for all but the first task.
      currOpts = JPetOptions::resetEventRange(currOpts);
      /// For all but the first task,
      /// the input path must be changed if
      /// the output path argument -o was given, because the input
      /// data for them will lay in the location defined by -o.
      auto outPath  = any_cast<std::string>(currOpts.at("outputPath_std::string"));
      if (!outPath.empty()) {
        currOpts.at("inputFile_std::string") = outPath + JPetCommonTools::extractPathFromFile(any_cast<std::string>(currOpts.at("inputFile_std::string"))) + JPetCommonTools::extractFileNameFromFullPath(any_cast<std::string>(currOpts.at("inputFile_std::string")));
      }
    }
    auto taskCurr = dynamic_cast<JPetTask*> ((*currentTask)->getTask());
    //auto taskCurr = std::dynamic_pointer_cast<JPetTask>((*currentTask)->getTask());
    auto taskName = taskCurr->GetName();
    INFO(Form("Starting task: %s", taskName));
    JPetTaskChainExecutor::printCurrentOptionsToLog(currOpts);
    /// @todo fix it
    auto taskRunnerCurr =  dynamic_cast<JPetTaskIO*> (*currentTask);
    taskRunnerCurr->init(currOpts);
    taskRunnerCurr->exec();
    taskRunnerCurr->terminate();

    elapsedTime.push_back(std::make_pair("task " + std::string(taskName), stdc::duration_cast< stdc::seconds > (stdc::system_clock::now() - startTime)));
    INFO(Form("Finished task: %s", taskName));
  }
  for (auto& el : elapsedTime) {
    INFO("Elapsed time for " + el.first + ":" + el.second.count() + " [s]");
  }
  auto total = std::accumulate(elapsedTime.begin(),
                               elapsedTime.end(),
                               stdc::seconds (0),
  [](const stdc::seconds prev, const std::pair <std::string, stdc::seconds>& el) {
    return prev + el.second;
  }
                              );
  INFO(std::string("Total elapsed time:") + total.count() + " [s]");

  return true;
}

void JPetTaskChainExecutor::printCurrentOptionsToLog(const JPetOptions::Options& currOpts)
{
  INFO("Current options:");
  std::vector<std::string> allowedTypes;
  JPetOptionsTypeHandler forGettingAllowedTypes(allowedTypes);
  for (auto a : currOpts) {
    allowedTypes.push_back(forGettingAllowedTypes.getTypeOfOption(a.first));
  }
  JPetOptionsTypeHandler typeHandler(allowedTypes);
  auto stringOptions = typeHandler.anyMapToStringMap(currOpts);
  for (const auto& el : stringOptions) {
    INFO(el.first + "=" + el.second);
  }
}

void* JPetTaskChainExecutor::processProxy(void* runner)
{
  assert(runner);
  static_cast<JPetTaskChainExecutor*>(runner)->process();
  return 0;
}

TThread* JPetTaskChainExecutor::run()
{
  TThread* thread = new TThread(std::to_string(fInputSeqId).c_str(), processProxy, (void*)this);
  assert(thread);
  thread->Run();
  return thread;
}

JPetTaskChainExecutor::~JPetTaskChainExecutor()
{
  for (auto& task : fTasks) {
    if (task) {
      delete task;
      task = 0;
    }
  }
}

<|endoftext|>


<commit_before>#include "BrainStdAfx.h"
#include "KF_ECEF.h"

#include "hal.def.h"
//#include "sz_KF_ECEF.hpp"

#include "Eigen/Dense"

namespace silk
{
namespace node
{

template<size_t St, size_t Me>
KF_ECEF::KF<St, Me>::KF()
{
    A.setIdentity();
    x.setZero();

    B.setIdentity();
    u.setZero();

    H.setIdentity();
    z.setZero();

    //error
    P.setIdentity();
    Q.setIdentity();

    K.setIdentity();
    R.setIdentity();

    I.setIdentity();

    I.setIdentity();
    B.setIdentity();
    H.setIdentity();
    P.setIdentity();
    K.setIdentity();
}

template<size_t St, size_t Me>
void KF_ECEF::KF<St, Me>::predict()
{
    x = A * x + B * u; //state prediction
    P = A * P * A.transpose() + Q; //covariance prediction
}

template<size_t St, size_t Me>
void KF_ECEF::KF<St, Me>::update()
{
    auto HT = H.transpose();

    Measurement_Vector y = z - H * x; //innovation

    auto S = H * P * HT + R; //innovation covariance

    K = P * HT * S.inverse(); //gain
    x = x + K * y; // state
    P = (I - K * H) * P; //covariance
}

template<size_t St, size_t Me>
void KF_ECEF::KF<St, Me>::process()
{
    predict();
    update();
}

///////////////////////////////////////////////////////////////////////

template<class Value>
void KF_ECEF::Delayer<Value>::init(float dt, float lag)
{
    QASSERT(dt > 0.f && lag >= 0.f);
    min_value_count = math::max(static_cast<size_t>(math::round(lag / dt)), size_t(1));
    values.clear();
}

template<class Value>
auto KF_ECEF::Delayer<Value>::get_value() -> Value const&
{
    QASSERT(!values.empty());
    return values.front();
}

template<class Value>
void KF_ECEF::Delayer<Value>::push_back(Value const& value)
{
    values.push_back(value);
    while (values.size() > min_value_count)
    {
        values.pop_front();
    }
}

///////////////////////////////////////////////////////////////////////

KF_ECEF::KF_ECEF(HAL& hal)
    : m_hal(hal)
    , m_descriptor(new hal::KF_ECEF_Descriptor())
    , m_config(new hal::KF_ECEF_Config())
{
    m_position_output_stream = std::make_shared<Position_Output_Stream>();
    m_velocity_output_stream = std::make_shared<Velocity_Output_Stream>();
    m_linear_acceleration_output_stream = std::make_shared<Linear_Acceleration_Output_Stream>();
}

ts::Result<void> KF_ECEF::init(hal::INode_Descriptor const& descriptor)
{
    QLOG_TOPIC("KF_ECEF::init");

    auto specialized = dynamic_cast<hal::KF_ECEF_Descriptor const*>(&descriptor);
    if (!specialized)
    {
        return make_error("Wrong descriptor type");
    }
    *m_descriptor = *specialized;

    return init();
}
ts::Result<void> KF_ECEF::init()
{
    m_position_output_stream->set_rate(m_descriptor->get_rate());
    m_velocity_output_stream->set_rate(m_descriptor->get_rate());
    m_linear_acceleration_output_stream->set_rate(m_descriptor->get_rate());

    m_dts = std::chrono::duration<double>(m_position_output_stream->get_dt()).count();
    double dt = m_dts;

    {
        m_kf_x.A << 1,      dt,     0.5*dt*dt,
                    0,      1,      dt,
                    0,      0,      1;

        m_kf_x.H << 1,      0,      0,
                    0,      1,      0,
                    0,      0,      1;

        double pn = 0.01;
        double dt4 = dt*dt*dt*dt;
        double dt3 = dt*dt*dt;
        double dt2 = dt*dt;
        m_kf_x.Q << pn*0.25*dt4,    pn*0.5*dt3, pn*0.5*dt2,
                    pn*0.5*dt3,     pn*dt2,     pn*dt,
                    pn*0.5*dt2,     pn*dt,      pn*1.0;
    }

    m_kf_y = m_kf_x;
    m_kf_z = m_kf_x;
//    m_kf_z = m_kf_x;

    return ts::success;
}

ts::Result<void> KF_ECEF::start(q::Clock::time_point tp)
{
    m_position_output_stream->set_tp(tp);
    m_velocity_output_stream->set_tp(tp);
    m_linear_acceleration_output_stream->set_tp(tp);
    return ts::success;
}

auto KF_ECEF::get_inputs() const -> std::vector<Input>
{
    std::vector<Input> inputs =
    {{
        { stream::IECEF_Position::TYPE, m_descriptor->get_rate(), "GPS Position (ecef)", m_accumulator.get_stream_path(0) },
        { stream::IECEF_Velocity::TYPE, m_descriptor->get_rate(), "GPS Velocity (ecef)", m_accumulator.get_stream_path(1) },
        { stream::IENU_Linear_Acceleration::TYPE, m_descriptor->get_rate(), "Linear Acceleration (enu)", m_accumulator.get_stream_path(2) },
    }};
    return inputs;
}
auto KF_ECEF::get_outputs() const -> std::vector<Output>
{
    std::vector<Output> outputs =
    {{
        { "position", m_position_output_stream },
        { "velocity", m_velocity_output_stream },
        { "linear_acceleration", m_linear_acceleration_output_stream },
    }};
    return outputs;
}

void KF_ECEF::process()
{
    QLOG_TOPIC("KF_ECEF::process");

    m_position_output_stream->clear();
    m_velocity_output_stream->clear();
    m_linear_acceleration_output_stream->clear();

    m_accumulator.process([this](stream::IECEF_Position::Sample const& gps_pos_sample,
                                  stream::IECEF_Velocity::Sample const& gps_vel_sample,
                                  stream::IENU_Linear_Acceleration::Sample const& la_sample)
    {
        if (gps_pos_sample.is_healthy & gps_vel_sample.is_healthy & la_sample.is_healthy)
        {
            util::coordinates::LLA lla_position = util::coordinates::ecef_to_lla(gps_pos_sample.value);
            math::mat3d enu_to_ecef_rotation = util::coordinates::enu_to_ecef_rotation(lla_position);
            math::vec3f ecef_la = math::vec3f(math::transform(enu_to_ecef_rotation, math::vec3d(la_sample.value)));

            stream::IECEF_Position::Sample const& last_gps_pos_sample = m_position_output_stream->get_last_sample();
            if (math::distance_sq(gps_pos_sample.value, last_gps_pos_sample.value) > math::square(20))
            {
                m_kf_x.x.setZero();
                m_kf_y.x.setZero();
                m_kf_z.x.setZero();
                m_kf_x.x(0) = gps_pos_sample.value.x;
                m_kf_y.x(0) = gps_pos_sample.value.y;
                m_kf_z.x(0) = gps_pos_sample.value.z;
            }

            {
                m_gps_position_delayer.push_back(gps_pos_sample.value);
                stream::IECEF_Position::Value const& pos = m_gps_position_delayer.get_value();
                m_kf_x.z(0) = pos.x;
                m_kf_y.z(0) = pos.y;
                m_kf_z.z(0) = pos.z;
            }

            {
                m_gps_velocity_delayer.push_back(gps_vel_sample.value);
                stream::IECEF_Velocity::Value const& vel = m_gps_velocity_delayer.get_value();
                m_kf_x.z(1) = vel.x;
                m_kf_y.z(1) = vel.y;
                m_kf_z.z(1) = vel.z;
            }

            {
                m_linear_acceleration_delayer.push_back(ecef_la);
                stream::IECEF_Linear_Acceleration::Value const& acc = m_linear_acceleration_delayer.get_value();
                m_kf_x.z(2) = acc.x;
                m_kf_y.z(2) = acc.y;
                m_kf_z.z(2) = acc.z;
            }

            m_kf_x.process();
            m_kf_y.process();
            m_kf_z.process();

            m_position_output_stream->push_sample(math::vec3d(m_kf_x.x(0), m_kf_y.x(0), m_kf_z.x(0)), true);
            m_velocity_output_stream->push_sample(math::vec3f(m_kf_x.x(1), m_kf_y.x(1), m_kf_z.x(1)), true);
            m_linear_acceleration_output_stream->push_sample(math::vec3f(m_kf_x.x(2), m_kf_y.x(2), m_kf_z.x(2)), true);
        }
        else
        {
            m_position_output_stream->push_last_sample(false);
            m_velocity_output_stream->push_last_sample(false);
            m_linear_acceleration_output_stream->push_last_sample(false);
        }
    });
}

ts::Result<void> KF_ECEF::set_input_stream_path(size_t idx, std::string const& path)
{
    return m_accumulator.set_stream_path(idx, path, m_descriptor->get_rate(), m_hal);
}

ts::Result<void> KF_ECEF::set_config(hal::INode_Config const& config)
{
    QLOG_TOPIC("KF_ECEF::set_config");

    auto specialized = dynamic_cast<hal::KF_ECEF_Config const*>(&config);
    if (!specialized)
    {
        return make_error("Wrong config type");
    }
    *m_config = *specialized;

    double gps_pos_acu = math::square(m_config->get_gps_position_accuracy());
    double gps_vel_acu = math::square(m_config->get_gps_velocity_accuracy());
    double acc_acu = math::square(m_config->get_acceleration_accuracy());

    m_kf_x.R << gps_pos_acu,    0,              0,
                0,              gps_vel_acu,    0,
                0,              0,              acc_acu;

    m_kf_y.R = m_kf_x.R;
    m_kf_z.R = m_kf_x.R;

    m_gps_position_delayer.init(m_dts, m_config->get_gps_position_lag());
    m_gps_velocity_delayer.init(m_dts, m_config->get_gps_velocity_lag());
    m_linear_acceleration_delayer.init(m_dts, m_config->get_acceleration_lag());

    return ts::success;
}
auto KF_ECEF::get_config() const -> std::shared_ptr<const hal::INode_Config>
{
    return m_config;
}

auto KF_ECEF::get_descriptor() const -> std::shared_ptr<const hal::INode_Descriptor>
{
    return m_descriptor;
}

//auto KF_ECEF::send_message(rapidjson::Value const& /*json*/) -> rapidjson::Document
//{
//    return rapidjson::Document();
//}

}
}
<commit_msg>optimization enabled for eigen functions as they are incredibly slow in debug<commit_after>#include "BrainStdAfx.h"
#include "KF_ECEF.h"

#include "hal.def.h"
//#include "sz_KF_ECEF.hpp"

#include "Eigen/Dense"

namespace silk
{
namespace node
{

template<size_t St, size_t Me>
KF_ECEF::KF<St, Me>::KF()
{
    A.setIdentity();
    x.setZero();

    B.setIdentity();
    u.setZero();

    H.setIdentity();
    z.setZero();

    //error
    P.setIdentity();
    Q.setIdentity();

    K.setIdentity();
    R.setIdentity();

    I.setIdentity();

    I.setIdentity();
    B.setIdentity();
    H.setIdentity();
    P.setIdentity();
    K.setIdentity();
}

template<size_t St, size_t Me>
__attribute__((optimize("O3"))) void KF_ECEF::KF<St, Me>::predict()
{
    x = A * x + B * u; //state prediction
    P = A * P * A.transpose() + Q; //covariance prediction
}

template<size_t St, size_t Me>
__attribute__((optimize("O3"))) void KF_ECEF::KF<St, Me>::update()
{
    auto HT = H.transpose();

    Measurement_Vector y = z - H * x; //innovation

    auto S = H * P * HT + R; //innovation covariance

    K = P * HT * S.inverse(); //gain
    x = x + K * y; // state
    P = (I - K * H) * P; //covariance
}

template<size_t St, size_t Me>
void KF_ECEF::KF<St, Me>::process()
{
    predict();
    update();
}

///////////////////////////////////////////////////////////////////////

template<class Value>
void KF_ECEF::Delayer<Value>::init(float dt, float lag)
{
    QASSERT(dt > 0.f && lag >= 0.f);
    min_value_count = math::max(static_cast<size_t>(math::round(lag / dt)), size_t(1));
    values.clear();
}

template<class Value>
auto KF_ECEF::Delayer<Value>::get_value() -> Value const&
{
    QASSERT(!values.empty());
    return values.front();
}

template<class Value>
void KF_ECEF::Delayer<Value>::push_back(Value const& value)
{
    values.push_back(value);
    while (values.size() > min_value_count)
    {
        values.pop_front();
    }
}

///////////////////////////////////////////////////////////////////////

KF_ECEF::KF_ECEF(HAL& hal)
    : m_hal(hal)
    , m_descriptor(new hal::KF_ECEF_Descriptor())
    , m_config(new hal::KF_ECEF_Config())
{
    m_position_output_stream = std::make_shared<Position_Output_Stream>();
    m_velocity_output_stream = std::make_shared<Velocity_Output_Stream>();
    m_linear_acceleration_output_stream = std::make_shared<Linear_Acceleration_Output_Stream>();
}

ts::Result<void> KF_ECEF::init(hal::INode_Descriptor const& descriptor)
{
    QLOG_TOPIC("KF_ECEF::init");

    auto specialized = dynamic_cast<hal::KF_ECEF_Descriptor const*>(&descriptor);
    if (!specialized)
    {
        return make_error("Wrong descriptor type");
    }
    *m_descriptor = *specialized;

    return init();
}
ts::Result<void> KF_ECEF::init()
{
    m_position_output_stream->set_rate(m_descriptor->get_rate());
    m_velocity_output_stream->set_rate(m_descriptor->get_rate());
    m_linear_acceleration_output_stream->set_rate(m_descriptor->get_rate());

    m_dts = std::chrono::duration<double>(m_position_output_stream->get_dt()).count();
    double dt = m_dts;

    {
        m_kf_x.A << 1,      dt,     0.5*dt*dt,
                    0,      1,      dt,
                    0,      0,      1;

        m_kf_x.H << 1,      0,      0,
                    0,      1,      0,
                    0,      0,      1;

        double pn = 0.01;
        double dt4 = dt*dt*dt*dt;
        double dt3 = dt*dt*dt;
        double dt2 = dt*dt;
        m_kf_x.Q << pn*0.25*dt4,    pn*0.5*dt3, pn*0.5*dt2,
                    pn*0.5*dt3,     pn*dt2,     pn*dt,
                    pn*0.5*dt2,     pn*dt,      pn*1.0;
    }

    m_kf_y = m_kf_x;
    m_kf_z = m_kf_x;
//    m_kf_z = m_kf_x;

    return ts::success;
}

ts::Result<void> KF_ECEF::start(q::Clock::time_point tp)
{
    m_position_output_stream->set_tp(tp);
    m_velocity_output_stream->set_tp(tp);
    m_linear_acceleration_output_stream->set_tp(tp);
    return ts::success;
}

auto KF_ECEF::get_inputs() const -> std::vector<Input>
{
    std::vector<Input> inputs =
    {{
        { stream::IECEF_Position::TYPE, m_descriptor->get_rate(), "GPS Position (ecef)", m_accumulator.get_stream_path(0) },
        { stream::IECEF_Velocity::TYPE, m_descriptor->get_rate(), "GPS Velocity (ecef)", m_accumulator.get_stream_path(1) },
        { stream::IENU_Linear_Acceleration::TYPE, m_descriptor->get_rate(), "Linear Acceleration (enu)", m_accumulator.get_stream_path(2) },
    }};
    return inputs;
}
auto KF_ECEF::get_outputs() const -> std::vector<Output>
{
    std::vector<Output> outputs =
    {{
        { "position", m_position_output_stream },
        { "velocity", m_velocity_output_stream },
        { "linear_acceleration", m_linear_acceleration_output_stream },
    }};
    return outputs;
}

void KF_ECEF::process()
{
    QLOG_TOPIC("KF_ECEF::process");

    m_position_output_stream->clear();
    m_velocity_output_stream->clear();
    m_linear_acceleration_output_stream->clear();

    m_accumulator.process([this](stream::IECEF_Position::Sample const& gps_pos_sample,
                                  stream::IECEF_Velocity::Sample const& gps_vel_sample,
                                  stream::IENU_Linear_Acceleration::Sample const& la_sample)
    {
        if (gps_pos_sample.is_healthy & gps_vel_sample.is_healthy & la_sample.is_healthy)
        {
            util::coordinates::LLA lla_position = util::coordinates::ecef_to_lla(gps_pos_sample.value);
            math::mat3d enu_to_ecef_rotation = util::coordinates::enu_to_ecef_rotation(lla_position);
            math::vec3f ecef_la = math::vec3f(math::transform(enu_to_ecef_rotation, math::vec3d(la_sample.value)));

            stream::IECEF_Position::Sample const& last_gps_pos_sample = m_position_output_stream->get_last_sample();
            if (math::distance_sq(gps_pos_sample.value, last_gps_pos_sample.value) > math::square(20))
            {
                m_kf_x.x.setZero();
                m_kf_y.x.setZero();
                m_kf_z.x.setZero();
                m_kf_x.x(0) = gps_pos_sample.value.x;
                m_kf_y.x(0) = gps_pos_sample.value.y;
                m_kf_z.x(0) = gps_pos_sample.value.z;
            }

            {
                m_gps_position_delayer.push_back(gps_pos_sample.value);
                stream::IECEF_Position::Value const& pos = m_gps_position_delayer.get_value();
                m_kf_x.z(0) = pos.x;
                m_kf_y.z(0) = pos.y;
                m_kf_z.z(0) = pos.z;
            }

            {
                m_gps_velocity_delayer.push_back(gps_vel_sample.value);
                stream::IECEF_Velocity::Value const& vel = m_gps_velocity_delayer.get_value();
                m_kf_x.z(1) = vel.x;
                m_kf_y.z(1) = vel.y;
                m_kf_z.z(1) = vel.z;
            }

            {
                m_linear_acceleration_delayer.push_back(ecef_la);
                stream::IECEF_Linear_Acceleration::Value const& acc = m_linear_acceleration_delayer.get_value();
                m_kf_x.z(2) = acc.x;
                m_kf_y.z(2) = acc.y;
                m_kf_z.z(2) = acc.z;
            }

            m_kf_x.process();
            m_kf_y.process();
            m_kf_z.process();

            m_position_output_stream->push_sample(math::vec3d(m_kf_x.x(0), m_kf_y.x(0), m_kf_z.x(0)), true);
            m_velocity_output_stream->push_sample(math::vec3f(m_kf_x.x(1), m_kf_y.x(1), m_kf_z.x(1)), true);
            m_linear_acceleration_output_stream->push_sample(math::vec3f(m_kf_x.x(2), m_kf_y.x(2), m_kf_z.x(2)), true);
        }
        else
        {
            m_position_output_stream->push_last_sample(false);
            m_velocity_output_stream->push_last_sample(false);
            m_linear_acceleration_output_stream->push_last_sample(false);
        }
    });
}

ts::Result<void> KF_ECEF::set_input_stream_path(size_t idx, std::string const& path)
{
    return m_accumulator.set_stream_path(idx, path, m_descriptor->get_rate(), m_hal);
}

ts::Result<void> KF_ECEF::set_config(hal::INode_Config const& config)
{
    QLOG_TOPIC("KF_ECEF::set_config");

    auto specialized = dynamic_cast<hal::KF_ECEF_Config const*>(&config);
    if (!specialized)
    {
        return make_error("Wrong config type");
    }
    *m_config = *specialized;

    double gps_pos_acu = math::square(m_config->get_gps_position_accuracy());
    double gps_vel_acu = math::square(m_config->get_gps_velocity_accuracy());
    double acc_acu = math::square(m_config->get_acceleration_accuracy());

    m_kf_x.R << gps_pos_acu,    0,              0,
                0,              gps_vel_acu,    0,
                0,              0,              acc_acu;

    m_kf_y.R = m_kf_x.R;
    m_kf_z.R = m_kf_x.R;

    m_gps_position_delayer.init(m_dts, m_config->get_gps_position_lag());
    m_gps_velocity_delayer.init(m_dts, m_config->get_gps_velocity_lag());
    m_linear_acceleration_delayer.init(m_dts, m_config->get_acceleration_lag());

    return ts::success;
}
auto KF_ECEF::get_config() const -> std::shared_ptr<const hal::INode_Config>
{
    return m_config;
}

auto KF_ECEF::get_descriptor() const -> std::shared_ptr<const hal::INode_Descriptor>
{
    return m_descriptor;
}

//auto KF_ECEF::send_message(rapidjson::Value const& /*json*/) -> rapidjson::Document
//{
//    return rapidjson::Document();
//}

}
}
<|endoftext|>


<commit_before>//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#include <stdio.h>
#if HAVE_SYS_TYPES_H
#  include <sys/types.h>
#endif

// C++ Includes
#include <cstdlib>
#include <string>
#include <map>

#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/ClangExpressionParser.h"
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Expression/ASTResultSynthesizer.h"
#include "lldb/Expression/ClangUserExpression.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"

using namespace lldb_private;

ClangUserExpression::ClangUserExpression (const char *expr) :
    m_expr_text(expr),
    m_transformed_text(),
    m_jit_addr(LLDB_INVALID_ADDRESS),
    m_cplusplus(false),
    m_objectivec(false),
    m_needs_object_ptr(false)
{
}

ClangUserExpression::~ClangUserExpression ()
{
}

clang::ASTConsumer *
ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
{
    return new ASTResultSynthesizer(passthrough);
}

void
ClangUserExpression::ScanContext(ExecutionContext &exe_ctx)
{
    if (!exe_ctx.frame)
        return;

    VariableList *vars = exe_ctx.frame->GetVariableList(false);

    if (!vars)
        return;

    if (vars->FindVariable(ConstString("this")).get())
        m_cplusplus = true;
    else if (vars->FindVariable(ConstString("self")).get())
        m_objectivec = true;
}

bool
ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
{
    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);

    ScanContext(exe_ctx);

    StreamString m_transformed_stream;

    ////////////////////////////////////
    // Generate the expression
    //

    if (m_cplusplus)
    {
        m_transformed_stream.Printf("void                                   \n"
                                    "$__lldb_class::%s(void *$__lldb_arg) \n"
                                    "{                                      \n"
                                    "    %s;                                \n"
                                    "}                                      \n",
                                    FunctionName(),
                                    m_expr_text.c_str());

        m_needs_object_ptr = true;
    }
    else
    {
        m_transformed_stream.Printf("void                           \n"
                                    "%s(void *$__lldb_arg)         \n"
                                    "{                              \n"
                                    "    %s;                        \n"
                                    "}                              \n",
                                    FunctionName(),
                                    m_expr_text.c_str());
    }

    m_transformed_text = m_transformed_stream.GetData();

    if (log)
        log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());

    ////////////////////////////////////
    // Set up the target and compiler
    //

    Target *target = exe_ctx.target;

    if (!target)
    {
        error_stream.PutCString ("error: invalid target\n");
        return false;
    }

    ConstString target_triple;

    target->GetTargetTriple (target_triple);

    if (!target_triple)
        target_triple = Host::GetTargetTriple ();

    if (!target_triple)
    {
        error_stream.PutCString ("error: invalid target triple\n");
        return false;
    }

    //////////////////////////
    // Parse the expression
    //

    m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx));

    ClangExpressionParser parser(target_triple.GetCString(), *this);

    unsigned num_errors = parser.Parse (error_stream);

    if (num_errors)
    {
        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
        return false;
    }

    ///////////////////////////////////////////////
    // Convert the output of the parser to DWARF
    //

    m_dwarf_opcodes.reset(new StreamString);
    m_dwarf_opcodes->SetByteOrder (lldb::eByteOrderHost);
    m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);

    m_local_variables.reset(new ClangExpressionVariableStore());

    Error dwarf_error = parser.MakeDWARF ();

    if (dwarf_error.Success())
    {
        if (log)
            log->Printf("Code can be interpreted.");

        return true;
    }

    //////////////////////////////////
    // JIT the output of the parser
    //

    m_dwarf_opcodes.reset();

    lldb::addr_t jit_end;

    Error jit_error = parser.MakeJIT (m_jit_addr, jit_end, exe_ctx);

    if (jit_error.Success())
    {
        if (log)
        {
            log->Printf("Code can be run in the target.");

            StreamString disassembly_stream;

            Error err = parser.DisassembleFunction(disassembly_stream, exe_ctx);

            if (!err.Success())
            {
                log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
            }
            else
            {
                log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
            }
        }

        return true;
    }
    else
    {
        error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
        return false;
    }
}

bool
ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
                                                    ExecutionContext &exe_ctx,
                                                    lldb::addr_t &struct_address,
                                                    lldb::addr_t &object_ptr)
{
    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);

    if (m_jit_addr != LLDB_INVALID_ADDRESS)
    {

        Error materialize_error;

        if (m_needs_object_ptr && !(m_expr_decl_map->GetObjectPointer(object_ptr, &exe_ctx, materialize_error)))
        {
            error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
            return false;
        }

        if (!m_expr_decl_map->Materialize(&exe_ctx, struct_address, materialize_error))
        {
            error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
            return false;
        }

        if (log)
        {
            log->Printf("Function address  : 0x%llx", (uint64_t)m_jit_addr);

            if (m_needs_object_ptr)
                log->Printf("Object pointer    : 0x%llx", (uint64_t)object_ptr);

            log->Printf("Structure address : 0x%llx", (uint64_t)struct_address);

            StreamString args;

            Error dump_error;

            if (struct_address)
            {
                if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error))
                {
                    log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
                }
                else
                {
                    log->Printf("Structure contents:\n%s", args.GetData());
                }
            }
        }
    }
    return true;
}

ThreadPlan *
ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
                                       ExecutionContext &exe_ctx)
{
    lldb::addr_t struct_address;

    lldb::addr_t object_ptr = NULL;

    PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr);

    return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
                                        m_jit_addr,
                                        struct_address,
                                        error_stream,
                                        true,
                                        true,
                                        (m_needs_object_ptr ? &object_ptr : NULL));
}

bool
ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
                                           ExecutionContext &exe_ctx,
                                           ClangExpressionVariable *&result)
{
    Error expr_error;

    if (!m_expr_decl_map->Dematerialize(&exe_ctx, result, expr_error))
    {
        error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
        return false;
    }
    return true;
}

bool
ClangUserExpression::Execute (Stream &error_stream,
                              ExecutionContext &exe_ctx,
                              ClangExpressionVariable *&result)
{
    if (m_dwarf_opcodes.get())
    {
        // TODO execute the JITted opcodes

        error_stream.Printf("We don't currently support executing DWARF expressions");

        return false;
    }
    else if (m_jit_addr != LLDB_INVALID_ADDRESS)
    {
        lldb::addr_t struct_address;

        lldb::addr_t object_ptr = NULL;

        PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr);

        ClangFunction::ExecutionResults execution_result =
        ClangFunction::ExecuteFunction (exe_ctx,
                                        m_jit_addr,
                                        struct_address,
                                        true,
                                        true,
                                        10000000,
                                        error_stream,
                                        (m_needs_object_ptr ? &object_ptr : NULL));

        if (execution_result != ClangFunction::eExecutionCompleted)
        {
            const char *result_name;

            switch (execution_result)
            {
                case ClangFunction::eExecutionCompleted:
                    result_name = "eExecutionCompleted";
                    break;
                case ClangFunction::eExecutionDiscarded:
                    result_name = "eExecutionDiscarded";
                    break;
                case ClangFunction::eExecutionInterrupted:
                    result_name = "eExecutionInterrupted";
                    break;
                case ClangFunction::eExecutionSetupError:
                    result_name = "eExecutionSetupError";
                    break;
                case ClangFunction::eExecutionTimedOut:
                    result_name = "eExecutionTimedOut";
                    break;
            }

            error_stream.Printf ("Couldn't execute function; result was %s\n", result_name);
            return false;
        }

        return FinalizeJITExecution (error_stream, exe_ctx, result);
    }
    else
    {
        error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function are present");
        return false;
    }
}

StreamString &
ClangUserExpression::DwarfOpcodeStream ()
{
    if (!m_dwarf_opcodes.get())
        m_dwarf_opcodes.reset(new StreamString());

    return *m_dwarf_opcodes.get();
}

lldb::ValueObjectSP
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, const char *expr_cstr)
{
    Error error;
    lldb::ValueObjectSP result_valobj_sp;
    ClangUserExpression user_expression (expr_cstr);

    StreamString error_stream;

    if (!user_expression.Parse (error_stream, exe_ctx))
    {
        if (error_stream.GetString().empty())
            error.SetErrorString ("expression failed to parse, unknown error");
        else
            error.SetErrorString (error_stream.GetString().c_str());
    }
    else
    {
        ClangExpressionVariable *expr_result = NULL;

        error_stream.GetString().clear();

        if (!user_expression.Execute (error_stream, exe_ctx, expr_result))
        {
            if (error_stream.GetString().empty())
                error.SetErrorString ("expression failed to execute, unknown error");
            else
                error.SetErrorString (error_stream.GetString().c_str());
        }
        else
        {
            // TODO: seems weird to get a pointer to a result object back from
            // a function. Do we own it? Feels like we do, but from looking at the
            // code we don't. Might be best to make this a reference and state
            // explicitly that we don't own it when we get a reference back from
            // the execute?
            if (expr_result)
            {
                result_valobj_sp = expr_result->GetExpressionResult (&exe_ctx);
            }
            else
            {
                error.SetErrorString ("Expression did not return a result");
            }
        }
    }

    if (result_valobj_sp.get() == NULL)
        result_valobj_sp.reset (new ValueObjectConstResult (error));

    return result_valobj_sp;
}<commit_msg>Added a temporary hack to allow casting of Objective-C method results to int.  This will only last until we get accurate type information for Objective-C methods or some way of making their types inferred by the parser.<commit_after>//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#include <stdio.h>
#if HAVE_SYS_TYPES_H
#  include <sys/types.h>
#endif

// C++ Includes
#include <cstdlib>
#include <string>
#include <map>

#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/ClangExpressionParser.h"
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Expression/ASTResultSynthesizer.h"
#include "lldb/Expression/ClangUserExpression.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"

using namespace lldb_private;

ClangUserExpression::ClangUserExpression (const char *expr) :
    m_expr_text(expr),
    m_transformed_text(),
    m_jit_addr(LLDB_INVALID_ADDRESS),
    m_cplusplus(false),
    m_objectivec(false),
    m_needs_object_ptr(false)
{
}

ClangUserExpression::~ClangUserExpression ()
{
}

clang::ASTConsumer *
ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
{
    return new ASTResultSynthesizer(passthrough);
}

void
ClangUserExpression::ScanContext(ExecutionContext &exe_ctx)
{
    if (!exe_ctx.frame)
        return;

    VariableList *vars = exe_ctx.frame->GetVariableList(false);

    if (!vars)
        return;

    if (vars->FindVariable(ConstString("this")).get())
        m_cplusplus = true;
    else if (vars->FindVariable(ConstString("self")).get())
        m_objectivec = true;
}

// This is a really nasty hack, meant to fix Objective-C expressions of the form
// (int)[myArray count].  Right now, because the type information for count is
// not available, [myArray count] returns id, which can't be directly cast to
// int without causing a clang error.
static void
ApplyObjcCastHack(std::string &expr)
{
#define OBJC_CAST_HACK_FROM "(int)["
#define OBJC_CAST_HACK_TO   "(int)(long long)["

    size_t from_offset;

    while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
        expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);

#undef OBJC_CAST_HACK_TO
#undef OBJC_CAST_HACK_FROM
}

bool
ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
{
    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);

    ScanContext(exe_ctx);

    StreamString m_transformed_stream;

    ////////////////////////////////////
    // Generate the expression
    //

    ApplyObjcCastHack(m_expr_text);

    if (m_cplusplus)
    {
        m_transformed_stream.Printf("void                                   \n"
                                    "$__lldb_class::%s(void *$__lldb_arg)   \n"
                                    "{                                      \n"
                                    "    %s;                                \n"
                                    "}                                      \n",
                                    FunctionName(),
                                    m_expr_text.c_str());

        m_needs_object_ptr = true;
    }
    else
    {
        m_transformed_stream.Printf("void                           \n"
                                    "%s(void *$__lldb_arg)          \n"
                                    "{                              \n"
                                    "    %s;                        \n"
                                    "}                              \n",
                                    FunctionName(),
                                    m_expr_text.c_str());
    }

    m_transformed_text = m_transformed_stream.GetData();

    if (log)
        log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());

    ////////////////////////////////////
    // Set up the target and compiler
    //

    Target *target = exe_ctx.target;

    if (!target)
    {
        error_stream.PutCString ("error: invalid target\n");
        return false;
    }

    ConstString target_triple;

    target->GetTargetTriple (target_triple);

    if (!target_triple)
        target_triple = Host::GetTargetTriple ();

    if (!target_triple)
    {
        error_stream.PutCString ("error: invalid target triple\n");
        return false;
    }

    //////////////////////////
    // Parse the expression
    //

    m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx));

    ClangExpressionParser parser(target_triple.GetCString(), *this);

    unsigned num_errors = parser.Parse (error_stream);

    if (num_errors)
    {
        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
        return false;
    }

    ///////////////////////////////////////////////
    // Convert the output of the parser to DWARF
    //

    m_dwarf_opcodes.reset(new StreamString);
    m_dwarf_opcodes->SetByteOrder (lldb::eByteOrderHost);
    m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);

    m_local_variables.reset(new ClangExpressionVariableStore());

    Error dwarf_error = parser.MakeDWARF ();

    if (dwarf_error.Success())
    {
        if (log)
            log->Printf("Code can be interpreted.");

        return true;
    }

    //////////////////////////////////
    // JIT the output of the parser
    //

    m_dwarf_opcodes.reset();

    lldb::addr_t jit_end;

    Error jit_error = parser.MakeJIT (m_jit_addr, jit_end, exe_ctx);

    if (jit_error.Success())
    {
        if (log)
        {
            log->Printf("Code can be run in the target.");

            StreamString disassembly_stream;

            Error err = parser.DisassembleFunction(disassembly_stream, exe_ctx);

            if (!err.Success())
            {
                log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
            }
            else
            {
                log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
            }
        }

        return true;
    }
    else
    {
        error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
        return false;
    }
}

bool
ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
                                                    ExecutionContext &exe_ctx,
                                                    lldb::addr_t &struct_address,
                                                    lldb::addr_t &object_ptr)
{
    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);

    if (m_jit_addr != LLDB_INVALID_ADDRESS)
    {

        Error materialize_error;

        if (m_needs_object_ptr && !(m_expr_decl_map->GetObjectPointer(object_ptr, &exe_ctx, materialize_error)))
        {
            error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
            return false;
        }

        if (!m_expr_decl_map->Materialize(&exe_ctx, struct_address, materialize_error))
        {
            error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
            return false;
        }

        if (log)
        {
            log->Printf("Function address  : 0x%llx", (uint64_t)m_jit_addr);

            if (m_needs_object_ptr)
                log->Printf("Object pointer    : 0x%llx", (uint64_t)object_ptr);

            log->Printf("Structure address : 0x%llx", (uint64_t)struct_address);

            StreamString args;

            Error dump_error;

            if (struct_address)
            {
                if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error))
                {
                    log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
                }
                else
                {
                    log->Printf("Structure contents:\n%s", args.GetData());
                }
            }
        }
    }
    return true;
}

ThreadPlan *
ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
                                       ExecutionContext &exe_ctx)
{
    lldb::addr_t struct_address;

    lldb::addr_t object_ptr = NULL;

    PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr);

    return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
                                        m_jit_addr,
                                        struct_address,
                                        error_stream,
                                        true,
                                        true,
                                        (m_needs_object_ptr ? &object_ptr : NULL));
}

bool
ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
                                           ExecutionContext &exe_ctx,
                                           ClangExpressionVariable *&result)
{
    Error expr_error;

    if (!m_expr_decl_map->Dematerialize(&exe_ctx, result, expr_error))
    {
        error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
        return false;
    }
    return true;
}

bool
ClangUserExpression::Execute (Stream &error_stream,
                              ExecutionContext &exe_ctx,
                              ClangExpressionVariable *&result)
{
    if (m_dwarf_opcodes.get())
    {
        // TODO execute the JITted opcodes

        error_stream.Printf("We don't currently support executing DWARF expressions");

        return false;
    }
    else if (m_jit_addr != LLDB_INVALID_ADDRESS)
    {
        lldb::addr_t struct_address;

        lldb::addr_t object_ptr = NULL;

        PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr);

        ClangFunction::ExecutionResults execution_result =
        ClangFunction::ExecuteFunction (exe_ctx,
                                        m_jit_addr,
                                        struct_address,
                                        true,
                                        true,
                                        10000000,
                                        error_stream,
                                        (m_needs_object_ptr ? &object_ptr : NULL));

        if (execution_result != ClangFunction::eExecutionCompleted)
        {
            const char *result_name;

            switch (execution_result)
            {
                case ClangFunction::eExecutionCompleted:
                    result_name = "eExecutionCompleted";
                    break;
                case ClangFunction::eExecutionDiscarded:
                    result_name = "eExecutionDiscarded";
                    break;
                case ClangFunction::eExecutionInterrupted:
                    result_name = "eExecutionInterrupted";
                    break;
                case ClangFunction::eExecutionSetupError:
                    result_name = "eExecutionSetupError";
                    break;
                case ClangFunction::eExecutionTimedOut:
                    result_name = "eExecutionTimedOut";
                    break;
            }

            error_stream.Printf ("Couldn't execute function; result was %s\n", result_name);
            return false;
        }

        return FinalizeJITExecution (error_stream, exe_ctx, result);
    }
    else
    {
        error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function are present");
        return false;
    }
}

StreamString &
ClangUserExpression::DwarfOpcodeStream ()
{
    if (!m_dwarf_opcodes.get())
        m_dwarf_opcodes.reset(new StreamString());

    return *m_dwarf_opcodes.get();
}

lldb::ValueObjectSP
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, const char *expr_cstr)
{
    Error error;
    lldb::ValueObjectSP result_valobj_sp;
    ClangUserExpression user_expression (expr_cstr);

    StreamString error_stream;

    if (!user_expression.Parse (error_stream, exe_ctx))
    {
        if (error_stream.GetString().empty())
            error.SetErrorString ("expression failed to parse, unknown error");
        else
            error.SetErrorString (error_stream.GetString().c_str());
    }
    else
    {
        ClangExpressionVariable *expr_result = NULL;

        error_stream.GetString().clear();

        if (!user_expression.Execute (error_stream, exe_ctx, expr_result))
        {
            if (error_stream.GetString().empty())
                error.SetErrorString ("expression failed to execute, unknown error");
            else
                error.SetErrorString (error_stream.GetString().c_str());
        }
        else
        {
            // TODO: seems weird to get a pointer to a result object back from
            // a function. Do we own it? Feels like we do, but from looking at the
            // code we don't. Might be best to make this a reference and state
            // explicitly that we don't own it when we get a reference back from
            // the execute?
            if (expr_result)
            {
                result_valobj_sp = expr_result->GetExpressionResult (&exe_ctx);
            }
            else
            {
                error.SetErrorString ("Expression did not return a result");
            }
        }
    }

    if (result_valobj_sp.get() == NULL)
        result_valobj_sp.reset (new ValueObjectConstResult (error));

    return result_valobj_sp;
}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.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.
 */

#include "otbWrapperChoiceParameter.h"
#include "otbWrapperListViewParameter.h"
#include "otbWrapperBoolParameter.h"
#include "otbWrapperApplicationRegistry.h"

#include <iostream>
#include <cassert>
#include <fstream>

int main(int argc, char* argv[])
{
  if (argc < 3)
    {
    std::cerr << "Usage : " << argv[0] << " name OTB_APPLICATION_PATH [out_dir]" << std::endl;
    return EXIT_FAILURE;
    }

  using namespace otb::Wrapper;

  const std::string module(argv[1]);

  /* TestApplication is removed in CMakeLists.txt */
#if 0
  if (module == "TestApplication")
    return EXIT_SUCCESS;
#endif

  ApplicationRegistry::AddApplicationPath(argv[2]);
  Application::Pointer appli =  ApplicationRegistry::CreateApplicationFaster(module);

  assert(!appli.IsNull());

  const std::string group = appli->GetDocTags().size() > 0 ? appli->GetDocTags()[0] : "";
  assert(!group.empty());

  std::map<ParameterType, std::string> parameterTypeToString;
  parameterTypeToString[ParameterType_Bool] = "QgsProcessingParameterBoolean";
  parameterTypeToString[ParameterType_Int] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Float] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_RAM] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Radius] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Choice] = "OTBParameterChoice";
  parameterTypeToString[ParameterType_String] = "QgsProcessingParameterString";
  parameterTypeToString[ParameterType_InputImage] = "QgsProcessingParameterRasterLayer";
  parameterTypeToString[ParameterType_InputFilename] = "QgsProcessingParameterFile";
  parameterTypeToString[ParameterType_InputImageList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_InputVectorData] = "QgsProcessingParameterVectorLayer";
  parameterTypeToString[ParameterType_InputFilenameList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_InputVectorDataList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_OutputImage] = "QgsProcessingParameterRasterDestination";
  parameterTypeToString[ParameterType_OutputVectorData] = "QgsProcessingParameterVectorDestination";
  parameterTypeToString[ParameterType_OutputFilename] = "QgsProcessingParameterFileDestination";
  parameterTypeToString[ParameterType_Directory] = "QgsProcessingParameterFile";
  parameterTypeToString[ParameterType_ComplexInputImage] = "QgsProcessingParameterRasterLayer";
  parameterTypeToString[ParameterType_ComplexOutputImage] = "QgsProcessingParameterRasterDestination";
  // TODO
  parameterTypeToString[ParameterType_StringList] = "QgsProcessingParameterString";
  // ListView parameters are treated as plain string (QLineEdit) in qgis processing ui.
  // This seems rather unpleasant when comparing Qgis processing with Monteverdi/Mapla in OTB
  // We tried to push something simple with checkboxes but its too risky for this version
  // and clock is ticking...

  parameterTypeToString[ParameterType_ListView] = "QgsProcessingParameterString";

  // For next update of plugin code ListView should use a custom widget wrapper and behave
  // exactly like OTB Mapla. And this #if 0 block is our TODO remainder.
  #if 0
  parameterTypeToString[ParameterType_ListView] = "OTBParameterListView";
  #endif

  const std::vector<std::string> appKeyList = appli->GetParametersKeys(true);
  const unsigned int nbOfParam = appKeyList.size();

  std::string output_file = module + ".txt";
  std::string  algs_txt = "algs.txt";
  if (argc > 3)
    {
    output_file = std::string(argv[3]) + module + ".txt";
    algs_txt = std::string(argv[3])  +  "algs.txt";
    }
  std::ofstream dFile;
  dFile.open (output_file, std::ios::out);

  std::string output_parameter_name;
  bool hasRasterOutput = false;
  {
  for (unsigned int i = 0; i < nbOfParam; i++)
    {
    Parameter::Pointer param = appli->GetParameterByKey(appKeyList[i]);
    if (param->GetMandatory())
      {
	if (appli->GetParameterType(appKeyList[i]) == ParameterType_OutputImage)
	  {
	    output_parameter_name = appKeyList[i];
	    hasRasterOutput = true;
	  }
      }
    }
  }

  if(output_parameter_name.empty())
    dFile << module << std::endl;
  else
    dFile << module << "|" <<  output_parameter_name << std::endl;

  dFile << appli->GetDescription() << std::endl;
  dFile << group << std::endl;

  for (unsigned int i = 0; i < nbOfParam; i++)
    {
    const std::string name = appKeyList[i];
    const Parameter::Pointer param = appli->GetParameterByKey(name);
    const ParameterType type = appli->GetParameterType(name);
    const std::string description = appli->GetParameterName(name);
    if (  type == ParameterType_Group  ||
          type == ParameterType_OutputProcessXML  ||
          type == ParameterType_InputProcessXML  ||
          type == ParameterType_RAM ||
          param->GetRole() == Role_Output )
      {
      // group parameter cannot have any value.
      // outxml and inxml parameters are not relevant for QGIS and is considered a bit noisy
      // ram is added by qgis-otb processing provider plugin as an advanced parameter for all apps
      // parameter role cannot be of type Role_Output
      continue;
      }
    auto it = parameterTypeToString.find(type);
    assert(  it != parameterTypeToString.end() );
    if( it == parameterTypeToString.end() )
      {
      std::cerr << "No mapping found for parameter '" <<name <<"' type=" << type << std::endl;
      return EXIT_FAILURE;
      }
    std::string qgis_type = it->second;
#if 0
      if (type == ParameterType_ListView)
	{
	  ListViewParameter *lv_param = dynamic_cast<ListViewParameter*>(param.GetPointer());
	  std::cerr << "lv_param->GetSingleSelection()" << lv_param->GetSingleSelection() << std::endl;
	  if (lv_param->GetSingleSelection())
	    {

	      qgis_type = "QgsProcessingParameterEnum";
	      std::vector<std::string>  key_list  = appli->GetChoiceKeys(name);
	      std::string values = "";
	      for( auto k : key_list)
		values += k + ";";
	      values.pop_back();
	      dFile << "|" << values ;
	    }
	}
#endif

    bool isDestination = false;
    bool isEpsgCode = false;

    // use QgsProcessingParameterCrs if required.
    // TODO: do a regex on name to match ==epsg || *\.epsg.\*
    if ( name == "epsg"
	      || name == "map.epsg.code"
	      || name == "mapproj.epsg.code"
	      || name == "mode.epsg.code")
        {
        qgis_type = "QgsProcessingParameterCrs";
        isEpsgCode = true;
        }

    dFile << qgis_type << "|" << name << "|" << description;

      std::string default_value = "None";
    if (type == ParameterType_Int)
      {
      if (isEpsgCode)
        {
          if (param->HasValue() && appli->GetParameterInt(name) < 1)
    	default_value =  "EPSG: " + appli->GetParameterAsString(name);
          else
    	default_value =  "ProjectCrs";
        }
      else
        {
        dFile << "|QgsProcessingParameterNumber.Integer";
        default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
        }
      }
    else if (type == ParameterType_Float)
      {
      dFile << "|QgsProcessingParameterNumber.Double";
      default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
      }
    else if (type == ParameterType_Radius)
      {
      dFile << "|QgsProcessingParameterNumber.Integer";
      default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
      }
    else if(type == ParameterType_InputFilename)
      {
      // TODO: if parameter InputFilename can give supported extensions
      // we can use it gitlab #1559
      dFile << "|QgsProcessingParameterFile.File|None";
      }
    else if(type == ParameterType_Directory)
      {
      dFile << "|QgsProcessingParameterFile.Folder|False";
      }
    else if (type == ParameterType_InputImageList)
      {
      dFile << "|3"; //QgsProcessing.TypeRaster
      }
    else if (type == ParameterType_InputVectorDataList)
      {
      dFile << "|-1"; //QgsProcessing.TypeVectorAnyGeometry
      }
    else if (type == ParameterType_InputVectorData)
      {
      dFile << "|-1"; //QgsProcessing.TypeVectorAnyGeometry
      }
    else if(type == ParameterType_InputFilenameList)
      {
      dFile << "|4"; //QgsProcessing.TypeFile"
      }
    else if(type == ParameterType_String)
      {
      // Below line is interpreted in qgis processing as
      // 1. default_value = None
      // 2. multiLine = False
      // For more details,
      // please refer to documetation of QgsProcessingParameterString.
      default_value = "None|False";
      }
    else if(type == ParameterType_StringList)
      {
      // Below line is interpreted in qgis processing as
      // 1. default_value = None
      // 2. multiLine = True
      // For more details,
      // please refer to documetation of QgsProcessingParameterString.
      // setting default_value this way is an exception for ParameterType_StringList and ParameterType_String
      default_value = "None|True";
      }
    else if (type == ParameterType_InputImage ||
             type == ParameterType_ComplexInputImage)
      {
      // default is None and nothing to add to dFile
      }
    else if(type == ParameterType_ListView)
      {
      // default is None and nothing to add to dFile
      }
    else if(type == ParameterType_Bool)
      {
      default_value = appli->GetParameterAsString(name);
      }
    else if(type == ParameterType_Choice)
      {
      std::vector<std::string>  key_list  = appli->GetChoiceKeys(name);
      std::string values = "";
      for( auto k : key_list)
        values += k + ";";

  	  values.pop_back();
  	  dFile << "|" << values ;
  	  ChoiceParameter *cparam = dynamic_cast<ChoiceParameter*>(param.GetPointer());
  	  default_value = std::to_string(cparam->GetValue());
      }
    else if(type == ParameterType_OutputVectorData ||
	          type == ParameterType_OutputImage ||
	          type == ParameterType_OutputFilename ||
	          type == ParameterType_ComplexOutputImage)
      {
      // No need for default_value, optional and extra fields in dFile.
      // If parameter is a destination type. qgis_type|name|description is enough.
      // So we simply set isDestination to true and skip to end to append a new line.
      isDestination =  true;
      }
    else
      {
      std::cout << "ERROR: default_value is empty for '" << name << "' type='" << qgis_type << "'" << std::endl;
      return EXIT_FAILURE;
      }

    std::string optional;
    if (param->GetMandatory())
      {
      // TODO: avoid workaround for stringlist types (fix appengine)
      // type == ParameterType_StringList check is needed because:
      // If parameter is mandatory it can have no value
      // It is accepted in OTB that, string list could be generated dynamically
      // qgis has no such option to handle dynamic values yet..
      // So mandatory parameters whose type is StringList is considered optional
      optional = param->HasValue() || type == ParameterType_StringList  ? "True" : "False";
      }
    else
      {
      optional = "True";
      }
              #if 0
    	  std::cerr << name;
    	  std::cerr << " mandatory=" << param->GetMandatory();
    	  std::cerr << " HasValue=" << param->HasValue();
    	  std::cerr << " qgis_type=" << qgis_type;
    	  std::cerr << " optional=" << optional << std::endl;
              #endif
    dFile << "|" << default_value << "|" << optional;
    dFile << std::endl;
    }

  if(hasRasterOutput)
    {
    dFile << "*QgsProcessingParameterEnum|outputpixeltype|Output pixel type|uint8;int;float;double|False|2|True" << std::endl;
    }

  std::cerr << "Writing " << output_file << std::endl;
  dFile.close();

  std::ofstream indexFile;
  indexFile.open (algs_txt, std::ios::out | std::ios::app );
  indexFile << group << "|" << module << std::endl;
  indexFile.close();
  std::cerr << "Updated " << algs_txt << std::endl;

  appli = nullptr;
  ApplicationRegistry::CleanRegistry();

  return EXIT_SUCCESS;
  }

<commit_msg>REFAC: refactor and add option for vector data<commit_after>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.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.
 */

#include "otbWrapperChoiceParameter.h"
#include "otbWrapperListViewParameter.h"
#include "otbWrapperBoolParameter.h"
#include "otbWrapperApplicationRegistry.h"

#include <iostream>
#include <cassert>
#include <fstream>

int main(int argc, char* argv[])
{
  if (argc < 3)
    {
    std::cerr << "Usage : " << argv[0] << " name OTB_APPLICATION_PATH [out_dir]" << std::endl;
    return EXIT_FAILURE;
    }

  using namespace otb::Wrapper;

  const std::string module(argv[1]);

  /* TestApplication is removed in CMakeLists.txt */
#if 0
  if (module == "TestApplication")
    return EXIT_SUCCESS;
#endif

  ApplicationRegistry::AddApplicationPath(argv[2]);
  Application::Pointer appli =  ApplicationRegistry::CreateApplicationFaster(module);

  assert(!appli.IsNull());

  const std::string group = appli->GetDocTags().size() > 0 ? appli->GetDocTags()[0] : "";
  assert(!group.empty());

  std::map<ParameterType, std::string> parameterTypeToString;
  parameterTypeToString[ParameterType_Bool] = "QgsProcessingParameterBoolean";
  parameterTypeToString[ParameterType_Int] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Float] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_RAM] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Radius] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Choice] = "OTBParameterChoice";
  parameterTypeToString[ParameterType_String] = "QgsProcessingParameterString";
  parameterTypeToString[ParameterType_InputImage] = "QgsProcessingParameterRasterLayer";
  parameterTypeToString[ParameterType_InputFilename] = "QgsProcessingParameterFile";
  parameterTypeToString[ParameterType_InputImageList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_InputVectorData] = "QgsProcessingParameterVectorLayer";
  parameterTypeToString[ParameterType_InputFilenameList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_InputVectorDataList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_OutputImage] = "QgsProcessingParameterRasterDestination";
  parameterTypeToString[ParameterType_OutputVectorData] = "QgsProcessingParameterVectorDestination";
  parameterTypeToString[ParameterType_OutputFilename] = "QgsProcessingParameterFileDestination";
  parameterTypeToString[ParameterType_Directory] = "QgsProcessingParameterFile";
  parameterTypeToString[ParameterType_ComplexInputImage] = "QgsProcessingParameterRasterLayer";
  parameterTypeToString[ParameterType_ComplexOutputImage] = "QgsProcessingParameterRasterDestination";
  // TODO
  parameterTypeToString[ParameterType_StringList] = "QgsProcessingParameterString";
  // ListView parameters are treated as plain string (QLineEdit) in qgis processing ui.
  // This seems rather unpleasant when comparing Qgis processing with Monteverdi/Mapla in OTB
  // We tried to push something simple with checkboxes but its too risky for this version
  // and clock is ticking...

  parameterTypeToString[ParameterType_ListView] = "QgsProcessingParameterString";

  // For next update of plugin code ListView should use a custom widget wrapper and behave
  // exactly like OTB Mapla. And this #if 0 block is our TODO remainder.
  #if 0
  parameterTypeToString[ParameterType_ListView] = "OTBParameterListView";
  #endif

  const std::vector<std::string> appKeyList = appli->GetParametersKeys(true);
  const unsigned int nbOfParam = appKeyList.size();

  std::string output_file = module + ".txt";
  std::string  algs_txt = "algs.txt";
  if ( argc > 3 )
    {
    output_file = std::string(argv[3]) + module + ".txt";
    algs_txt = std::string(argv[3])  +  "algs.txt";
    }
  std::ofstream dFile;
  dFile.open (output_file, std::ios::out);

  std::string output_parameter_name;
  bool hasRasterOutput = false;
  {
  for ( unsigned int i = 0; i < nbOfParam; i++ )
    {
    Parameter::Pointer param = appli->GetParameterByKey( appKeyList[i] );
    if ( param->GetMandatory() )
      {
	if ( appli->GetParameterType( appKeyList[i] ) == ParameterType_OutputImage )
	  {
	    output_parameter_name = appKeyList[i];
	    hasRasterOutput = true;
	  }
      }
    }
  }

  if( output_parameter_name.empty() )
    dFile << module << std::endl;
  else
    dFile << module << "|" <<  output_parameter_name << std::endl;

  dFile << appli->GetDescription() << std::endl;
  dFile << group << std::endl;

  for ( unsigned int i = 0; i < nbOfParam; i++ )
    {
    const std::string name = appKeyList[i];
    const Parameter::Pointer param = appli->GetParameterByKey(name);
    const ParameterType type = appli->GetParameterType(name);
    const std::string description = appli->GetParameterName(name);
    if (  type == ParameterType_Group  ||
          type == ParameterType_OutputProcessXML  ||
          type == ParameterType_InputProcessXML  ||
          type == ParameterType_RAM ||
          param->GetRole() == Role_Output )
      {
      // group parameter cannot have any value.
      // outxml and inxml parameters are not relevant for QGIS and is considered a bit noisy
      // ram is added by qgis-otb processing provider plugin as an advanced parameter for all apps
      // parameter role cannot be of type Role_Output
      continue;
      }
    auto it = parameterTypeToString.find(type);
    assert(  it != parameterTypeToString.end() );
    if( it == parameterTypeToString.end() )
      {
      std::cerr << "No mapping found for parameter '" <<name <<"' type=" << type << std::endl;
      return EXIT_FAILURE;
      }
    std::string qgis_type = it->second;
#if 0
      if (type == ParameterType_ListView)
	{
	  ListViewParameter *lv_param = dynamic_cast<ListViewParameter*>(param.GetPointer());
	  std::cerr << "lv_param->GetSingleSelection()" << lv_param->GetSingleSelection() << std::endl;
	  if (lv_param->GetSingleSelection())
	    {

	      qgis_type = "QgsProcessingParameterEnum";
	      std::vector<std::string>  key_list  = appli->GetChoiceKeys(name);
	      std::string values = "";
	      for( auto k : key_list)
		values += k + ";";
	      values.pop_back();
	      dFile << "|" << values ;
	    }
	}
#endif

    bool isEpsgCode = false;

    // use QgsProcessingParameterCrs if required.
    // TODO: do a regex on name to match ==epsg || *\.epsg.\*
    if ( name == "epsg"
	    || name == "map.epsg.code"
	    || name == "mapproj.epsg.code"
	    || name == "mode.epsg.code" )
        {
        qgis_type = "QgsProcessingParameterCrs";
        isEpsgCode = true;
        }

    dFile << qgis_type << "|" << name << "|" << description;

      std::string default_value = "None";
    if ( type == ParameterType_Int )
      {
      if ( isEpsgCode )
        {
          if (param->HasValue() && appli->GetParameterInt(name) < 1)
    	default_value =  "EPSG: " + appli->GetParameterAsString(name);
          else
    	default_value =  "ProjectCrs";
        }
      else
        {
        dFile << "|QgsProcessingParameterNumber.Integer";
        default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
        }
      }
    else if ( type == ParameterType_Float )
      {
      dFile << "|QgsProcessingParameterNumber.Double";
      default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
      }
    else if ( type == ParameterType_Radius )
      {
      dFile << "|QgsProcessingParameterNumber.Integer";
      default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
      }
    else if ( type == ParameterType_InputFilename )
      {
      // TODO: if parameter InputFilename can give supported extensions
      // we can use it gitlab #1559
      dFile << "|QgsProcessingParameterFile.File|None";
      }
    else if( type == ParameterType_Directory )
      {
      dFile << "|QgsProcessingParameterFile.Folder|False";
      }
    else if ( type == ParameterType_InputImageList )
      {
      dFile << "|3"; //QgsProcessing.TypeRaster
      }
    else if ( type == ParameterType_InputVectorDataList
           || type == ParameterType_InputVectorData
           || type == ParameterType_OutputVectorData )
      {
      dFile << "|-1"; //QgsProcessing.TypeVectorAnyGeometry
      }
    else if ( type == ParameterType_InputFilenameList )
      {
      dFile << "|4"; //QgsProcessing.TypeFile"
      }
    else if ( type == ParameterType_String )
      {
      // Below line is interpreted in qgis processing as
      // 1. default_value = None
      // 2. multiLine = False
      // For more details,
      // please refer to documetation of QgsProcessingParameterString.
      default_value = "None|False";
      }
    else if(type == ParameterType_StringList)
      {
      // Below line is interpreted in qgis processing as
      // 1. default_value = None
      // 2. multiLine = True
      // For more details,
      // please refer to documetation of QgsProcessingParameterString.
      // setting default_value this way is an exception for ParameterType_StringList and ParameterType_String
      default_value = "None|True";
      }
    else if (type == ParameterType_InputImage
          || type == ParameterType_ComplexInputImage
          || type == ParameterType_OutputImage
          || type == ParameterType_OutputFilename
          || type == ParameterType_ComplexOutputImage)
      {
      // default is None and nothing to add to dFile
      }
    else if(type == ParameterType_ListView)
      {
      // default is None and nothing to add to dFile
      }
    else if(type == ParameterType_Bool)
      {
      default_value = appli->GetParameterAsString(name);
      }
    else if(type == ParameterType_Choice)
      {
      std::vector<std::string>  key_list  = appli->GetChoiceKeys(name);
      std::string values = "";
      for( auto k : key_list)
        values += k + ";";

  	  values.pop_back();
  	  dFile << "|" << values ;
  	  ChoiceParameter *cparam = dynamic_cast<ChoiceParameter*>(param.GetPointer());
  	  default_value = std::to_string(cparam->GetValue());
      }
    else
      {
      std::cout << "ERROR: default_value is empty for '" << name << "' type='" << qgis_type << "'" << std::endl;
      return EXIT_FAILURE;
      }

    std::string optional;
    if ( param->GetMandatory() )
      {
      // TODO: avoid workaround for stringlist types (fix appengine)
      // type == ParameterType_StringList check is needed because:
      // If parameter is  mandatory it can have no value
      // It is accepted in OTB that, string list could be generated dynamically
      // qgis has no such option to handle dynamic values yet..
      // So mandatory parameters whose type is StringList is considered optional
      optional = param->HasValue() || type == ParameterType_StringList  ? "True" : "False";
      }
    else
      {
      optional = "True";
      }
              #if 0
    	  std::cerr << name;
    	  std::cerr << " mandatory=" << param->GetMandatory();
    	  std::cerr << " HasValue=" << param->HasValue();
    	  std::cerr << " qgis_type=" << qgis_type;
    	  std::cerr << " optional=" << optional << std::endl;
              #endif
    dFile << "|" << default_value << "|" << optional;
    dFile << std::endl;
    }

  if(hasRasterOutput)
    {
    dFile << "*QgsProcessingParameterEnum|outputpixeltype|Output pixel type|uint8;int;float;double|False|2|True" << std::endl;
    }

  std::cerr << "Writing " << output_file << std::endl;
  dFile.close();

  std::ofstream indexFile;
  indexFile.open (algs_txt, std::ios::out | std::ios::app );
  indexFile << group << "|" << module << std::endl;
  indexFile.close();
  std::cerr << "Updated " << algs_txt << std::endl;

  appli = nullptr;
  ApplicationRegistry::CleanRegistry();

  return EXIT_SUCCESS;
  }

<|endoftext|>