<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// 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.

/** @file
 * Tests for SURGSIM_ASSERT() and SURGSIM_FAILURE().
 */

#include <gtest/gtest.h>
#include <SurgSim/Framework/Assert.h>

class MockOutput : public SurgSim::Framework::LogOutput
{
public:
	MockOutput() {};
	~MockOutput() {};

	bool writeMessage(const std::string& message)
	{
		logMessage = message;
		return true;
	}
	void reset()
	{
		logMessage = "";
	}

	std::string logMessage;
};

class AssertTest : public ::testing::Test
{
public:
	void SetUp()
	{
		logOutput = std::make_shared<MockOutput>();
		testLogger = std::unique_ptr<SurgSim::Framework::Logger>(new SurgSim::Framework::Logger("test", logOutput));
		// testLogger will be used for assertions in most tests, due to the definition of SURGSIM_ASSERT_LOGGER below.
		savedCallback = SurgSim::Framework::AssertMessage::getFailureCallback();
	}

	void TearDown()
	{
		SurgSim::Framework::AssertMessage::setFailureCallback(savedCallback);
		testLogger.reset();
		logOutput.reset();
	}

	std::shared_ptr<MockOutput> logOutput;
	std::unique_ptr<SurgSim::Framework::Logger> testLogger;
	SurgSim::Framework::AssertMessage::DeathCallback savedCallback;
};

TEST_F(AssertTest, DefaultAssertLogger)
{
	std::cout << "=== You should see an assertion message to cout/cerr:" << std::endl;
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "extra information would go here", SurgSim::Framework::AssertionFailure);
	std::cout << "=== The test is now complete." << std::endl;
}

#undef SURGSIM_ASSERT_LOGGER   // override the default definition
#define SURGSIM_ASSERT_LOGGER testLogger   // defined in the test fixture, above

inline bool stringContains(const std::string& string, const std::string& fragment)
{
	return string.find(fragment) != std::string::npos;
}

static int numIgnoredAssertions = 0;

static void ignoreAssertionKeepGoing(const std::string& message)
{
	++numIgnoredAssertions;
}

TEST_F(AssertTest, Assertion)
{
	logOutput->reset();
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "extra information would go here", SurgSim::Framework::AssertionFailure);
	EXPECT_TRUE(stringContains(logOutput->logMessage, "1 == 2")) <<
		"message: '" << logOutput->logMessage << "'";
	EXPECT_TRUE(stringContains(logOutput->logMessage, "AssertTest.cpp")) <<
		"message: '" << logOutput->logMessage << "'";
	EXPECT_TRUE(stringContains(logOutput->logMessage, "extra information")) <<
		"message: '" << logOutput->logMessage << "'";

	logOutput->reset();
	EXPECT_NO_THROW({SURGSIM_ASSERT(3 == 3) << "extra information would go here";});
	EXPECT_EQ("", logOutput->logMessage) <<
		"message: '" << logOutput->logMessage << "'";
}

TEST_F(AssertTest, Failure)
{
	logOutput->reset();
	EXPECT_THROW(SURGSIM_FAILURE() << "extra information would go here", SurgSim::Framework::AssertionFailure);
	EXPECT_TRUE(stringContains(logOutput->logMessage, "AssertTest.cpp")) <<
		"message: '" << logOutput->logMessage << "'";
	EXPECT_TRUE(stringContains(logOutput->logMessage, "extra information")) <<
		"message: '" << logOutput->logMessage << "'";
}

TEST_F(AssertTest, Manipulators)
{
	logOutput->reset();
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "aAa" << std::endl << "bBb", SurgSim::Framework::AssertionFailure);
	EXPECT_TRUE(stringContains(logOutput->logMessage, "aAa\nbBb") ||
				stringContains(logOutput->logMessage, "aAa\r\n\bBb")) <<
		"message: '" << logOutput->logMessage << "'";

	logOutput->reset();
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "[" << std::hex << std::setw(5) << std::setfill('0') << 0x1234 << "]",
				 SurgSim::Framework::AssertionFailure);
	EXPECT_TRUE(stringContains(logOutput->logMessage, "[01234]")) <<
		"message: '" << logOutput->logMessage << "'";

	logOutput->reset();
	// The next message should not show any evidence of previous manipulators.
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "[" << 987 << "]", SurgSim::Framework::AssertionFailure);
	EXPECT_TRUE(stringContains(logOutput->logMessage, "[987]")) <<
		"message: '" << logOutput->logMessage << "'";
}

TEST_F(AssertTest, ExceptionBehavior)
{
	logOutput->reset();

	SurgSim::Framework::AssertMessage::setFailureBehaviorToThrow();
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "extra information would go here", SurgSim::Framework::AssertionFailure);
	EXPECT_NO_THROW({SURGSIM_ASSERT(3 == 3) << "extra information would go here";});

	EXPECT_THROW(SURGSIM_FAILURE() << "extra information would go here", SurgSim::Framework::AssertionFailure);
}

TEST_F(AssertTest, Callback)
{
	logOutput->reset();

	typedef SurgSim::Framework::AssertMessage::DeathCallback CallbackType;
	const CallbackType defaultCallback = SurgSim::Framework::AssertMessage::getFailureCallback();

	SurgSim::Framework::AssertMessage::setFailureBehaviorToThrow();
	const CallbackType throwCallback = SurgSim::Framework::AssertMessage::getFailureCallback();
	EXPECT_EQ(throwCallback, defaultCallback);

	SurgSim::Framework::AssertMessage::setFailureCallback(ignoreAssertionKeepGoing);
	EXPECT_EQ(static_cast<CallbackType>(ignoreAssertionKeepGoing), SurgSim::Framework::AssertMessage::getFailureCallback());
	numIgnoredAssertions = 0;
	EXPECT_NO_THROW(SURGSIM_ASSERT(1 == 2) << "extra information would go here");
	EXPECT_EQ(1, numIgnoredAssertions);
	EXPECT_NO_THROW({SURGSIM_ASSERT(3 == 3) << "extra information would go here";});
	EXPECT_EQ(1, numIgnoredAssertions);
	EXPECT_NO_THROW(SURGSIM_FAILURE() << "extra information would go here");
	EXPECT_EQ(2, numIgnoredAssertions);

	SurgSim::Framework::AssertMessage::setFailureBehaviorToThrow();
	EXPECT_EQ(throwCallback, SurgSim::Framework::AssertMessage::getFailureCallback());
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "extra information would go here", SurgSim::Framework::AssertionFailure);
	EXPECT_EQ(2, numIgnoredAssertions);
}

TEST_F(AssertTest, DebuggerBehaviorSuccess)
{
	logOutput->reset();
	SurgSim::Framework::AssertMessage::setFailureBehaviorToDebugger();
	EXPECT_NO_THROW({SURGSIM_ASSERT(3 == 3) << "extra information would go here";});
}

TEST_F(AssertTest, DebuggerBehaviorAssertFailedDeathTest)
{
	logOutput->reset();
	SurgSim::Framework::AssertMessage::setFailureBehaviorToDebugger();
	// The assertion should die with no output to stdout.
	ASSERT_DEATH_IF_SUPPORTED({SURGSIM_ASSERT(1 == 2) << "extra information would go here";}, "^$");
}

TEST_F(AssertTest, DebuggerBehaviorFailureDeathTest)
{
	logOutput->reset();
	SurgSim::Framework::AssertMessage::setFailureBehaviorToDebugger();
	// The assertion should die with no output to stdout.
	ASSERT_DEATH_IF_SUPPORTED({SURGSIM_FAILURE() << "extra information would go here";}, "^$");
}
<commit_msg>Follow instructions on death tests *correctly* this time.<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// 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.

/** @file
 * Tests for SURGSIM_ASSERT() and SURGSIM_FAILURE().
 */

#include <gtest/gtest.h>
#include <SurgSim/Framework/Assert.h>

class MockOutput : public SurgSim::Framework::LogOutput
{
public:
	MockOutput() {};
	~MockOutput() {};

	bool writeMessage(const std::string& message)
	{
		logMessage = message;
		return true;
	}
	void reset()
	{
		logMessage = "";
	}

	std::string logMessage;
};

class AssertTest : public ::testing::Test
{
public:
	void SetUp()
	{
		logOutput = std::make_shared<MockOutput>();
		testLogger = std::unique_ptr<SurgSim::Framework::Logger>(new SurgSim::Framework::Logger("test", logOutput));
		// testLogger will be used for assertions in most tests, due to the definition of SURGSIM_ASSERT_LOGGER below.
		savedCallback = SurgSim::Framework::AssertMessage::getFailureCallback();
	}

	void TearDown()
	{
		SurgSim::Framework::AssertMessage::setFailureCallback(savedCallback);
		testLogger.reset();
		logOutput.reset();
	}

	std::shared_ptr<MockOutput> logOutput;
	std::unique_ptr<SurgSim::Framework::Logger> testLogger;
	SurgSim::Framework::AssertMessage::DeathCallback savedCallback;
};

typedef AssertTest AssertDeathTest;

TEST_F(AssertTest, DefaultAssertLogger)
{
	std::cout << "=== You should see an assertion message to cout/cerr:" << std::endl;
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "extra information would go here", SurgSim::Framework::AssertionFailure);
	std::cout << "=== The test is now complete." << std::endl;
}

#undef SURGSIM_ASSERT_LOGGER   // override the default definition
#define SURGSIM_ASSERT_LOGGER testLogger   // defined in the test fixture, above

inline bool stringContains(const std::string& string, const std::string& fragment)
{
	return string.find(fragment) != std::string::npos;
}

static int numIgnoredAssertions = 0;

static void ignoreAssertionKeepGoing(const std::string& message)
{
	++numIgnoredAssertions;
}

TEST_F(AssertTest, Assertion)
{
	logOutput->reset();
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "extra information would go here", SurgSim::Framework::AssertionFailure);
	EXPECT_TRUE(stringContains(logOutput->logMessage, "1 == 2")) <<
		"message: '" << logOutput->logMessage << "'";
	EXPECT_TRUE(stringContains(logOutput->logMessage, "AssertTest.cpp")) <<
		"message: '" << logOutput->logMessage << "'";
	EXPECT_TRUE(stringContains(logOutput->logMessage, "extra information")) <<
		"message: '" << logOutput->logMessage << "'";

	logOutput->reset();
	EXPECT_NO_THROW({SURGSIM_ASSERT(3 == 3) << "extra information would go here";});
	EXPECT_EQ("", logOutput->logMessage) <<
		"message: '" << logOutput->logMessage << "'";
}

TEST_F(AssertTest, Failure)
{
	logOutput->reset();
	EXPECT_THROW(SURGSIM_FAILURE() << "extra information would go here", SurgSim::Framework::AssertionFailure);
	EXPECT_TRUE(stringContains(logOutput->logMessage, "AssertTest.cpp")) <<
		"message: '" << logOutput->logMessage << "'";
	EXPECT_TRUE(stringContains(logOutput->logMessage, "extra information")) <<
		"message: '" << logOutput->logMessage << "'";
}

TEST_F(AssertTest, Manipulators)
{
	logOutput->reset();
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "aAa" << std::endl << "bBb", SurgSim::Framework::AssertionFailure);
	EXPECT_TRUE(stringContains(logOutput->logMessage, "aAa\nbBb") ||
				stringContains(logOutput->logMessage, "aAa\r\n\bBb")) <<
		"message: '" << logOutput->logMessage << "'";

	logOutput->reset();
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "[" << std::hex << std::setw(5) << std::setfill('0') << 0x1234 << "]",
				 SurgSim::Framework::AssertionFailure);
	EXPECT_TRUE(stringContains(logOutput->logMessage, "[01234]")) <<
		"message: '" << logOutput->logMessage << "'";

	logOutput->reset();
	// The next message should not show any evidence of previous manipulators.
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "[" << 987 << "]", SurgSim::Framework::AssertionFailure);
	EXPECT_TRUE(stringContains(logOutput->logMessage, "[987]")) <<
		"message: '" << logOutput->logMessage << "'";
}

TEST_F(AssertTest, ExceptionBehavior)
{
	logOutput->reset();

	SurgSim::Framework::AssertMessage::setFailureBehaviorToThrow();
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "extra information would go here", SurgSim::Framework::AssertionFailure);
	EXPECT_NO_THROW({SURGSIM_ASSERT(3 == 3) << "extra information would go here";});

	EXPECT_THROW(SURGSIM_FAILURE() << "extra information would go here", SurgSim::Framework::AssertionFailure);
}

TEST_F(AssertTest, Callback)
{
	logOutput->reset();

	typedef SurgSim::Framework::AssertMessage::DeathCallback CallbackType;
	const CallbackType defaultCallback = SurgSim::Framework::AssertMessage::getFailureCallback();

	SurgSim::Framework::AssertMessage::setFailureBehaviorToThrow();
	const CallbackType throwCallback = SurgSim::Framework::AssertMessage::getFailureCallback();
	EXPECT_EQ(throwCallback, defaultCallback);

	SurgSim::Framework::AssertMessage::setFailureCallback(ignoreAssertionKeepGoing);
	EXPECT_EQ(static_cast<CallbackType>(ignoreAssertionKeepGoing), SurgSim::Framework::AssertMessage::getFailureCallback());
	numIgnoredAssertions = 0;
	EXPECT_NO_THROW(SURGSIM_ASSERT(1 == 2) << "extra information would go here");
	EXPECT_EQ(1, numIgnoredAssertions);
	EXPECT_NO_THROW({SURGSIM_ASSERT(3 == 3) << "extra information would go here";});
	EXPECT_EQ(1, numIgnoredAssertions);
	EXPECT_NO_THROW(SURGSIM_FAILURE() << "extra information would go here");
	EXPECT_EQ(2, numIgnoredAssertions);

	SurgSim::Framework::AssertMessage::setFailureBehaviorToThrow();
	EXPECT_EQ(throwCallback, SurgSim::Framework::AssertMessage::getFailureCallback());
	EXPECT_THROW(SURGSIM_ASSERT(1 == 2) << "extra information would go here", SurgSim::Framework::AssertionFailure);
	EXPECT_EQ(2, numIgnoredAssertions);
}

TEST_F(AssertDeathTest, DebuggerBehaviorAssertFailed)
{
	logOutput->reset();
	SurgSim::Framework::AssertMessage::setFailureBehaviorToDebugger();
	// The assertion should die with no output to stdout.
	ASSERT_DEATH_IF_SUPPORTED({SURGSIM_ASSERT(1 == 2) << "extra information would go here";}, "^$");
}

TEST_F(AssertDeathTest, DebuggerBehaviorAssertSucceded)
{
	logOutput->reset();
	SurgSim::Framework::AssertMessage::setFailureBehaviorToDebugger();
	EXPECT_NO_THROW({SURGSIM_ASSERT(3 == 3) << "extra information would go here";});
}

TEST_F(AssertDeathTest, DebuggerBehaviorFailure)
{
	logOutput->reset();
	SurgSim::Framework::AssertMessage::setFailureBehaviorToDebugger();
	// The assertion should die with no output to stdout.
	ASSERT_DEATH_IF_SUPPORTED({SURGSIM_FAILURE() << "extra information would go here";}, "^$");
}
<|endoftext|>


<commit_before>/* ----------------------------------------------------------------------- *//**
 *
 * @file linear.cpp
 *
 * @brief Linear-regression functions
 *
 *//* ----------------------------------------------------------------------- */

#include <dbconnector/dbconnector.hpp>
#include <modules/shared/HandleTraits_proto.hpp>
#include <modules/prob/prob.hpp>

namespace madlib {

namespace modules {

// Import names from other MADlib modules
using prob::studentT_CDF;

namespace regress {

#include "linear.hpp"

/**
 * @brief Transition state for linear-regression functions
 *
 * TransitionState encapsulates the transition state during the
 * linear-regression aggregate functions. To the database, the state is exposed
 * as a single DOUBLE PRECISION array, to the C++ code it is a proper object
 * containing scalars, a vector, and a matrix.
 *
 * Note: We assume that the DOUBLE PRECISION array is initialized by the
 * database with length at least 5, and all elemenets are 0.
 */
template <class Handle, class LinAlgTypes = DefaultLinAlgTypes>
class LinRegrTransitionState : public AbstractionLayer {
    // By §14.5.3/9: "Friend declarations shall not declare partial
    // specializations." We do access protected members in operator+=().
    template <class OtherHandle, class OtherLinAlgTypes>
    friend class LinRegrTransitionState;

public:
    LinRegrTransitionState(const AnyType &inArray)
      : mStorage(inArray.getAs<Handle>()) {

        rebind(mStorage[1]);
    }

    /**
     * @brief Convert to backend representation
     *
     * We define this function so that we can use TransitionState in the argument
     * list and as a return type.
     */
    inline operator AnyType() const {
        return mStorage;
    }

    /**
     * @brief Initialize the transition state. Only called for first row.
     *
     * @param inAllocator Allocator for the memory transition state. Must fill
     *     the memory block with zeros.
     * @param inWidthOfX Number of independent variables. The first row of data
     *     determines the size of the transition state. This size is a quadratic
     *     function of inWidthOfX.
     */
    inline void initialize(const Allocator &inAllocator, uint16_t inWidthOfX) {
        mStorage = inAllocator.allocateArray<double>(arraySize(inWidthOfX));
        rebind(inWidthOfX);
        widthOfX = inWidthOfX;
    }

    /**
     * @brief Merge with another TransitionState object
     */
    template <class OtherHandle>
    LinRegrTransitionState &operator+=(
        const LinRegrTransitionState<OtherHandle, LinAlgTypes> &inOtherState) {

        if (mStorage.size() != inOtherState.mStorage.size())
            throw std::logic_error("Internal error: Incompatible transition states");

        for (size_t i = 0; i < mStorage.size(); i++)
            mStorage[i] += inOtherState.mStorage[i];

        // Undo the addition of widthOfX
        widthOfX = inOtherState.widthOfX;
        return *this;
    }

private:
    static inline size_t arraySize(const uint16_t inWidthOfX) {
        return 4 + inWidthOfX + inWidthOfX % 2 + inWidthOfX * inWidthOfX;
    }

    /**
     * @brief Rebind to a new storage array
     *
     * @param inWidthOfX The number of independent variables.
     *
     * Array layout:
     * - 0: numRows (number of rows seen so far)
     * - 1: widthOfX (number of coefficients)
     * - 2: y_sum (sum of independent variables seen so far)
     * - 3: y_square_sum (sum of squares of independent variables seen so far)
     * - 4: X_transp_Y (X^T y, for that parts of X and y seen so far)
     * - 4 + widthOfX + widthOfX % 2: (X^T X, as seen so far)
     *
     * Note that we want 16-byte alignment for all vectors and matrices. We
     * therefore ensure that X_transp_Y and X_transp_X begin at even positions.
     */
    void rebind(uint16_t inWidthOfX) {
        numRows.rebind(&mStorage[0]);
        widthOfX.rebind(&mStorage[1]);
        y_sum.rebind(&mStorage[2]);
        y_square_sum.rebind(&mStorage[3]);
        X_transp_Y.rebind(&mStorage[4], inWidthOfX);
        X_transp_X.rebind(&mStorage[4 + inWidthOfX + (inWidthOfX % 2)],
            inWidthOfX, inWidthOfX);
    }

    Handle mStorage;

public:
    typename HandleTraits<Handle, LinAlgTypes>::ReferenceToUInt64 numRows;
    typename HandleTraits<Handle, LinAlgTypes>::ReferenceToUInt16 widthOfX;
    typename HandleTraits<Handle, LinAlgTypes>::ReferenceToDouble y_sum;
    typename HandleTraits<Handle, LinAlgTypes>::ReferenceToDouble y_square_sum;
    typename HandleTraits<Handle, LinAlgTypes>::ColumnVectorTransparentHandleMap X_transp_Y;
    typename HandleTraits<Handle, LinAlgTypes>::MatrixTransparentHandleMap X_transp_X;
};

/**
 * @brief Perform the linear-regression transition step
 *
 * We update: the number of rows \f$ n \f$, the partial sums
 * \f$ \sum_{i=1}^n y_i \f$ and \f$ \sum_{i=1}^n y_i^2 \f$, the matrix
 * \f$ X^T X \f$, and the vector \f$ X^T \boldsymbol y \f$.
 */
AnyType
linregr_transition::run(AnyType &args) {
    // Arguments from SQL call. Immutable values passed by reference should be
    // instantiated from the respective <tt>_const</tt> class. Otherwise, the
    // abstraction layer will perform a deep copy (i.e., waste unnecessary
    // processor cycles).
    LinRegrTransitionState<MutableArrayHandle<double> > state = args[0];
    double y = args[1].getAs<double>();
    HandleMap<const ColumnVector> x = args[2].getAs<ArrayHandle<double> >();

    // The following check was added with MADLIB-138.
    if (!std::isfinite(y))
        throw std::invalid_argument("Dependent variables are not finite.");
    else if (!isfinite(x))
        throw std::invalid_argument("Design matrix is not finite.");

    // Now do the transition step.
    if (state.numRows == 0) {
        if (x.size() > std::numeric_limits<uint16_t>::max())
            throw std::domain_error("Number of independent variables cannot be "
                "larger than 65535.");

        state.initialize(*this, x.size());
    }
    state.numRows++;
    state.y_sum += y;
    state.y_square_sum += y * y;
    state.X_transp_Y.noalias() += x * y;
    // FIXME: The following line is Eigen-specific
    // X^T X is symmetric, so it is sufficient to only fill a triangular part
    // of the matrix
    state.X_transp_X.triangularView<Eigen::Lower>() += x * trans(x);

    return state;
}

/**
 * @brief Perform the perliminary aggregation function: Merge transition states
 */
AnyType
linregr_merge_states::run(AnyType &args) {
    LinRegrTransitionState<MutableArrayHandle<double> > stateLeft = args[0];
    LinRegrTransitionState<ArrayHandle<double> > stateRight = args[1];

    // We first handle the trivial case where this function is called with one
    // of the states being the initial state
    if (stateLeft.numRows == 0)
        return stateRight;
    else if (stateRight.numRows == 0)
        return stateLeft;

    // Merge states together and return
    stateLeft += stateRight;
    return stateLeft;
}

/**
 * @brief Perform the linear-regression final step
 */
AnyType
linregr_final::run(AnyType &args) {
    LinRegrTransitionState<ArrayHandle<double> > state = args[0];

    // See MADLIB-138. At least on certain platforms and with certain versions,
    // LAPACK will run into an infinite loop if pinv() is called for non-finite
    // matrices. We extend the check also to the dependent variables.
    if (!isfinite(state.X_transp_X) || !isfinite(state.X_transp_Y))
        throw std::invalid_argument("Design matrix is not finite.");

    SymmetricPositiveDefiniteEigenDecomposition<Matrix> decomposition(
        state.X_transp_X, EigenvaluesOnly, ComputePseudoInverse);

    // Precompute (X^T * X)^+
    Matrix inverse_of_X_transp_X = decomposition.pseudoInverse();

    // Vector of coefficients: For efficiency reasons, we want to return this
    // by reference, so we need to bind to db memory
    HandleMap<ColumnVector> coef(allocateArray<double>(state.widthOfX));
    coef.noalias() = inverse_of_X_transp_X * state.X_transp_Y;

    // explained sum of squares (regression sum of squares)
    double ess
        = dot(state.X_transp_Y, coef)
            - ((state.y_sum * state.y_sum) / state.numRows);

    // total sum of squares
    double tss
        = state.y_square_sum
            - ((state.y_sum * state.y_sum) / state.numRows);

    // With infinite precision, the following checks are pointless. But due to
    // floating-point arithmetic, this need not hold at this point.
    // Without a formal proof convincing us of the contrary, we should
    // anticipate that numerical peculiarities might occur.
    if (tss < 0)
        tss = 0;
    if (ess < 0)
        ess = 0;
    // Since we know tss with greater accuracy than ess, we do the following
    // sanity adjustment to ess:
    if (ess > tss)
        ess = tss;

    // coefficient of determination
    // If tss == 0, then the regression perfectly fits the data, so the
    // coefficient of determination is 1.
    double r2 = (tss == 0 ? 1 : ess / tss);

    // In the case of linear regression:
    // residual sum of squares (rss) = total sum of squares (tss) - explained
    // sum of squares (ess)
    // Proof: http://en.wikipedia.org/wiki/Sum_of_squares
    double rss = tss - ess;

    // Variance is also called the mean square error
	double variance = rss / (state.numRows - state.widthOfX);

    // Vector of standard errors and t-statistics: For efficiency reasons, we
    // want to return these by reference, so we need to bind to db memory
    HandleMap<ColumnVector> stdErr(allocateArray<double>(state.widthOfX));
    HandleMap<ColumnVector> tStats(allocateArray<double>(state.widthOfX));
    for (int i = 0; i < state.widthOfX; i++) {
        // In an abundance of caution, we see a tiny possibility that numerical
        // instabilities in the pinv operation can lead to negative values on
        // the main diagonal of even a SPD matrix
        if (inverse_of_X_transp_X(i,i) < 0) {
            stdErr(i) = 0;
        } else {
            stdErr(i) = std::sqrt( variance * inverse_of_X_transp_X(i,i) );
        }

        if (coef(i) == 0 && stdErr(i) == 0) {
            // In this special case, 0/0 should be interpreted as 0:
            // We know that 0 is the exact value for the coefficient, so
            // the t-value should be 0 (corresponding to a p-value of 1)
            tStats(i) = 0;
        } else {
            // If stdErr(i) == 0 then abs(tStats(i)) will be infinity, which is
            // what we need.
            tStats(i) = coef(i) / stdErr(i);
        }
    }

    // Vector of p-values: For efficiency reasons, we want to return this
    // by reference, so we need to bind to db memory
    HandleMap<ColumnVector> pValues(allocateArray<double>(state.widthOfX));
    for (int i = 0; i < state.widthOfX; i++)
        pValues(i) = 2. * (1. - studentT_CDF(
                                    state.numRows - state.widthOfX,
                                    std::fabs( tStats(i) )));

    // Return all coefficients, standard errors, etc. in a tuple
    AnyType tuple;
    tuple << coef << r2 << stdErr << tStats << pValues
        << decomposition.conditionNo();
    return tuple;
}

} // namespace regress

} // namespace modules

} // namespace madlib
<commit_msg>Linear regression: - Use abstraction for triangular view of matrix<commit_after>/* ----------------------------------------------------------------------- *//**
 *
 * @file linear.cpp
 *
 * @brief Linear-regression functions
 *
 *//* ----------------------------------------------------------------------- */

#include <dbconnector/dbconnector.hpp>
#include <modules/shared/HandleTraits_proto.hpp>
#include <modules/prob/prob.hpp>

namespace madlib {

namespace modules {

// Import names from other MADlib modules
using prob::studentT_CDF;

namespace regress {

#include "linear.hpp"

/**
 * @brief Transition state for linear-regression functions
 *
 * TransitionState encapsulates the transition state during the
 * linear-regression aggregate functions. To the database, the state is exposed
 * as a single DOUBLE PRECISION array, to the C++ code it is a proper object
 * containing scalars, a vector, and a matrix.
 *
 * Note: We assume that the DOUBLE PRECISION array is initialized by the
 * database with length at least 5, and all elemenets are 0.
 */
template <class Handle, class LinAlgTypes = DefaultLinAlgTypes>
class LinRegrTransitionState : public AbstractionLayer {
    // By §14.5.3/9: "Friend declarations shall not declare partial
    // specializations." We do access protected members in operator+=().
    template <class OtherHandle, class OtherLinAlgTypes>
    friend class LinRegrTransitionState;

public:
    LinRegrTransitionState(const AnyType &inArray)
      : mStorage(inArray.getAs<Handle>()) {

        rebind(mStorage[1]);
    }

    /**
     * @brief Convert to backend representation
     *
     * We define this function so that we can use TransitionState in the argument
     * list and as a return type.
     */
    inline operator AnyType() const {
        return mStorage;
    }

    /**
     * @brief Initialize the transition state. Only called for first row.
     *
     * @param inAllocator Allocator for the memory transition state. Must fill
     *     the memory block with zeros.
     * @param inWidthOfX Number of independent variables. The first row of data
     *     determines the size of the transition state. This size is a quadratic
     *     function of inWidthOfX.
     */
    inline void initialize(const Allocator &inAllocator, uint16_t inWidthOfX) {
        mStorage = inAllocator.allocateArray<double>(arraySize(inWidthOfX));
        rebind(inWidthOfX);
        widthOfX = inWidthOfX;
    }

    /**
     * @brief Merge with another TransitionState object
     */
    template <class OtherHandle>
    LinRegrTransitionState &operator+=(
        const LinRegrTransitionState<OtherHandle, LinAlgTypes> &inOtherState) {

        if (mStorage.size() != inOtherState.mStorage.size())
            throw std::logic_error("Internal error: Incompatible transition states");

        for (size_t i = 0; i < mStorage.size(); i++)
            mStorage[i] += inOtherState.mStorage[i];

        // Undo the addition of widthOfX
        widthOfX = inOtherState.widthOfX;
        return *this;
    }

private:
    static inline size_t arraySize(const uint16_t inWidthOfX) {
        return 4 + inWidthOfX + inWidthOfX % 2 + inWidthOfX * inWidthOfX;
    }

    /**
     * @brief Rebind to a new storage array
     *
     * @param inWidthOfX The number of independent variables.
     *
     * Array layout:
     * - 0: numRows (number of rows seen so far)
     * - 1: widthOfX (number of coefficients)
     * - 2: y_sum (sum of independent variables seen so far)
     * - 3: y_square_sum (sum of squares of independent variables seen so far)
     * - 4: X_transp_Y (X^T y, for that parts of X and y seen so far)
     * - 4 + widthOfX + widthOfX % 2: (X^T X, as seen so far)
     *
     * Note that we want 16-byte alignment for all vectors and matrices. We
     * therefore ensure that X_transp_Y and X_transp_X begin at even positions.
     */
    void rebind(uint16_t inWidthOfX) {
        numRows.rebind(&mStorage[0]);
        widthOfX.rebind(&mStorage[1]);
        y_sum.rebind(&mStorage[2]);
        y_square_sum.rebind(&mStorage[3]);
        X_transp_Y.rebind(&mStorage[4], inWidthOfX);
        X_transp_X.rebind(&mStorage[4 + inWidthOfX + (inWidthOfX % 2)],
            inWidthOfX, inWidthOfX);
    }

    Handle mStorage;

public:
    typename HandleTraits<Handle, LinAlgTypes>::ReferenceToUInt64 numRows;
    typename HandleTraits<Handle, LinAlgTypes>::ReferenceToUInt16 widthOfX;
    typename HandleTraits<Handle, LinAlgTypes>::ReferenceToDouble y_sum;
    typename HandleTraits<Handle, LinAlgTypes>::ReferenceToDouble y_square_sum;
    typename HandleTraits<Handle, LinAlgTypes>::ColumnVectorTransparentHandleMap X_transp_Y;
    typename HandleTraits<Handle, LinAlgTypes>::MatrixTransparentHandleMap X_transp_X;
};

/**
 * @brief Perform the linear-regression transition step
 *
 * We update: the number of rows \f$ n \f$, the partial sums
 * \f$ \sum_{i=1}^n y_i \f$ and \f$ \sum_{i=1}^n y_i^2 \f$, the matrix
 * \f$ X^T X \f$, and the vector \f$ X^T \boldsymbol y \f$.
 */
AnyType
linregr_transition::run(AnyType &args) {
    // Arguments from SQL call. Immutable values passed by reference should be
    // instantiated from the respective <tt>_const</tt> class. Otherwise, the
    // abstraction layer will perform a deep copy (i.e., waste unnecessary
    // processor cycles).
    LinRegrTransitionState<MutableArrayHandle<double> > state = args[0];
    double y = args[1].getAs<double>();
    HandleMap<const ColumnVector> x = args[2].getAs<ArrayHandle<double> >();

    // The following check was added with MADLIB-138.
    if (!std::isfinite(y))
        throw std::invalid_argument("Dependent variables are not finite.");
    else if (!isfinite(x))
        throw std::invalid_argument("Design matrix is not finite.");

    // Now do the transition step.
    if (state.numRows == 0) {
        if (x.size() > std::numeric_limits<uint16_t>::max())
            throw std::domain_error("Number of independent variables cannot be "
                "larger than 65535.");

        state.initialize(*this, x.size());
    }
    state.numRows++;
    state.y_sum += y;
    state.y_square_sum += y * y;
    state.X_transp_Y.noalias() += x * y;
    // X^T X is symmetric, so it is sufficient to only fill a triangular part
    // of the matrix
    triangularView<Lower>(state.X_transp_X) += x * trans(x);

    return state;
}

/**
 * @brief Perform the perliminary aggregation function: Merge transition states
 */
AnyType
linregr_merge_states::run(AnyType &args) {
    LinRegrTransitionState<MutableArrayHandle<double> > stateLeft = args[0];
    LinRegrTransitionState<ArrayHandle<double> > stateRight = args[1];

    // We first handle the trivial case where this function is called with one
    // of the states being the initial state
    if (stateLeft.numRows == 0)
        return stateRight;
    else if (stateRight.numRows == 0)
        return stateLeft;

    // Merge states together and return
    stateLeft += stateRight;
    return stateLeft;
}

/**
 * @brief Perform the linear-regression final step
 */
AnyType
linregr_final::run(AnyType &args) {
    LinRegrTransitionState<ArrayHandle<double> > state = args[0];

    // See MADLIB-138. At least on certain platforms and with certain versions,
    // LAPACK will run into an infinite loop if pinv() is called for non-finite
    // matrices. We extend the check also to the dependent variables.
    if (!isfinite(state.X_transp_X) || !isfinite(state.X_transp_Y))
        throw std::invalid_argument("Design matrix is not finite.");

    SymmetricPositiveDefiniteEigenDecomposition<Matrix> decomposition(
        state.X_transp_X, EigenvaluesOnly, ComputePseudoInverse);

    // Precompute (X^T * X)^+
    Matrix inverse_of_X_transp_X = decomposition.pseudoInverse();

    // Vector of coefficients: For efficiency reasons, we want to return this
    // by reference, so we need to bind to db memory
    HandleMap<ColumnVector> coef(allocateArray<double>(state.widthOfX));
    coef.noalias() = inverse_of_X_transp_X * state.X_transp_Y;

    // explained sum of squares (regression sum of squares)
    double ess
        = dot(state.X_transp_Y, coef)
            - ((state.y_sum * state.y_sum) / state.numRows);

    // total sum of squares
    double tss
        = state.y_square_sum
            - ((state.y_sum * state.y_sum) / state.numRows);

    // With infinite precision, the following checks are pointless. But due to
    // floating-point arithmetic, this need not hold at this point.
    // Without a formal proof convincing us of the contrary, we should
    // anticipate that numerical peculiarities might occur.
    if (tss < 0)
        tss = 0;
    if (ess < 0)
        ess = 0;
    // Since we know tss with greater accuracy than ess, we do the following
    // sanity adjustment to ess:
    if (ess > tss)
        ess = tss;

    // coefficient of determination
    // If tss == 0, then the regression perfectly fits the data, so the
    // coefficient of determination is 1.
    double r2 = (tss == 0 ? 1 : ess / tss);

    // In the case of linear regression:
    // residual sum of squares (rss) = total sum of squares (tss) - explained
    // sum of squares (ess)
    // Proof: http://en.wikipedia.org/wiki/Sum_of_squares
    double rss = tss - ess;

    // Variance is also called the mean square error
	double variance = rss / (state.numRows - state.widthOfX);

    // Vector of standard errors and t-statistics: For efficiency reasons, we
    // want to return these by reference, so we need to bind to db memory
    HandleMap<ColumnVector> stdErr(allocateArray<double>(state.widthOfX));
    HandleMap<ColumnVector> tStats(allocateArray<double>(state.widthOfX));
    for (int i = 0; i < state.widthOfX; i++) {
        // In an abundance of caution, we see a tiny possibility that numerical
        // instabilities in the pinv operation can lead to negative values on
        // the main diagonal of even a SPD matrix
        if (inverse_of_X_transp_X(i,i) < 0) {
            stdErr(i) = 0;
        } else {
            stdErr(i) = std::sqrt( variance * inverse_of_X_transp_X(i,i) );
        }

        if (coef(i) == 0 && stdErr(i) == 0) {
            // In this special case, 0/0 should be interpreted as 0:
            // We know that 0 is the exact value for the coefficient, so
            // the t-value should be 0 (corresponding to a p-value of 1)
            tStats(i) = 0;
        } else {
            // If stdErr(i) == 0 then abs(tStats(i)) will be infinity, which is
            // what we need.
            tStats(i) = coef(i) / stdErr(i);
        }
    }

    // Vector of p-values: For efficiency reasons, we want to return this
    // by reference, so we need to bind to db memory
    HandleMap<ColumnVector> pValues(allocateArray<double>(state.widthOfX));
    for (int i = 0; i < state.widthOfX; i++)
        pValues(i) = 2. * (1. - studentT_CDF(
                                    state.numRows - state.widthOfX,
                                    std::fabs( tStats(i) )));

    // Return all coefficients, standard errors, etc. in a tuple
    AnyType tuple;
    tuple << coef << r2 << stdErr << tStats << pValues
        << decomposition.conditionNo();
    return tuple;
}

} // namespace regress

} // namespace modules

} // namespace madlib
<|endoftext|>


<commit_before>#include "console.hpp"
#include "cpp/ylikuutio/callback_system/callback_parameter.hpp"
#include "cpp/ylikuutio/callback_system/callback_object.hpp"
#include "cpp/ylikuutio/callback_system/callback_engine.hpp"
#include "cpp/ylikuutio/callback_system/callback_magic_numbers.hpp"
#include "cpp/ylikuutio/common/any_value.hpp"

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include standard headers
#include <vector>   // std::vector
#include <iostream> // std::cout, std::cin, std::cerr

namespace console
{
    // Keep these variable types as this is according to GLFW documentation!
    // So: `unsigned int codepoint`, `int mods`.
    void charmods_callback(GLFWwindow* window, unsigned int codepoint, int mods)
    {
        std::cout << "Hello from character_callback! codepoint: " << codepoint << "\n";

        global_console_pointer->add_character(codepoint);
    }

    datatypes::AnyValue* exit_console(
            callback_system::CallbackEngine*,
            callback_system::CallbackObject* callback_object,
            std::vector<callback_system::CallbackParameter*>)
    {
        datatypes::AnyValue* any_value_console_pointer = callback_object->get_any_value("console_pointer");

        if (any_value_console_pointer == nullptr)
        {
            return nullptr;
        }

        if (any_value_console_pointer->type != datatypes::CONSOLE_POINTER)
        {
            return nullptr;
        }

        console::Console* console_pointer = any_value_console_pointer->console_pointer;
        console_pointer->exit_console();

        // Signal to caller that we have exited the console.
        uint32_t exit_console_magic_number = EXIT_CONSOLE_MAGIC_NUMBER;
        datatypes::AnyValue* any_value_magic_number = new datatypes::AnyValue(exit_console_magic_number);
        return any_value_magic_number;
    }

    datatypes::AnyValue* backspace(
            callback_system::CallbackEngine*,
            callback_system::CallbackObject* callback_object,
            std::vector<callback_system::CallbackParameter*>)
    {
        datatypes::AnyValue* any_value_console_pointer = callback_object->get_any_value("console_pointer");

        if (any_value_console_pointer == nullptr)
        {
            return nullptr;
        }

        if (any_value_console_pointer->type != datatypes::CONSOLE_POINTER)
        {
            return nullptr;
        }

        console::Console* console = any_value_console_pointer->console_pointer;
        console->backspace();
        return nullptr;
    }
}
<commit_msg>`void charmods_callback` prints also `mods` (for testing purposes).<commit_after>#include "console.hpp"
#include "cpp/ylikuutio/callback_system/callback_parameter.hpp"
#include "cpp/ylikuutio/callback_system/callback_object.hpp"
#include "cpp/ylikuutio/callback_system/callback_engine.hpp"
#include "cpp/ylikuutio/callback_system/callback_magic_numbers.hpp"
#include "cpp/ylikuutio/common/any_value.hpp"

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include standard headers
#include <vector>   // std::vector
#include <iostream> // std::cout, std::cin, std::cerr

namespace console
{
    // Keep these variable types as this is according to GLFW documentation!
    // So: `unsigned int codepoint`, `int mods`.
    void charmods_callback(GLFWwindow* window, unsigned int codepoint, int mods)
    {
        // `int mods` values:
        // No modificators:       0x00
        // Shift (left or right): 0x01
        // Alt (not AltGr):       0x04
        // Shift + Alt:           0x05
        std::cout << "Hello from character_callback! codepoint: 0x" << std::hex << codepoint << ", mods: 0x" << mods << "\n";

        global_console_pointer->add_character(codepoint);
    }

    datatypes::AnyValue* exit_console(
            callback_system::CallbackEngine*,
            callback_system::CallbackObject* callback_object,
            std::vector<callback_system::CallbackParameter*>)
    {
        datatypes::AnyValue* any_value_console_pointer = callback_object->get_any_value("console_pointer");

        if (any_value_console_pointer == nullptr)
        {
            return nullptr;
        }

        if (any_value_console_pointer->type != datatypes::CONSOLE_POINTER)
        {
            return nullptr;
        }

        console::Console* console_pointer = any_value_console_pointer->console_pointer;
        console_pointer->exit_console();

        // Signal to caller that we have exited the console.
        uint32_t exit_console_magic_number = EXIT_CONSOLE_MAGIC_NUMBER;
        datatypes::AnyValue* any_value_magic_number = new datatypes::AnyValue(exit_console_magic_number);
        return any_value_magic_number;
    }

    datatypes::AnyValue* backspace(
            callback_system::CallbackEngine*,
            callback_system::CallbackObject* callback_object,
            std::vector<callback_system::CallbackParameter*>)
    {
        datatypes::AnyValue* any_value_console_pointer = callback_object->get_any_value("console_pointer");

        if (any_value_console_pointer == nullptr)
        {
            return nullptr;
        }

        if (any_value_console_pointer->type != datatypes::CONSOLE_POINTER)
        {
            return nullptr;
        }

        console::Console* console = any_value_console_pointer->console_pointer;
        console->backspace();
        return nullptr;
    }
}
<|endoftext|>


<commit_before>#include "acf_depth_channel.hpp"

#include <csapex/msg/io.h>
#include <csapex/msg/generic_vector_message.hpp>
#include <csapex/model/node_modifier.h>
#include <csapex/param/parameter_factory.h>
#include <csapex/utility/register_apex_plugin.h>

#include <csapex_opencv/cv_mat_message.h>
#include <csapex_opencv/roi_message.h>
#include <csapex_ml/features_message.h>

CSAPEX_REGISTER_CLASS(csapex::vision::ACFDepthChannel, csapex::Node)

using namespace csapex;
using namespace csapex::vision;
using namespace csapex::connection_types;

void ACFDepthChannel::setup(csapex::NodeModifier& node_modifier)
{
    in_image_      = node_modifier.addInput<CvMatMessage>("Depth Map");
    in_rois_       = node_modifier.addOptionalInput<GenericVectorMessage, RoiMessage>("ROIs");
    out_channels_  = node_modifier.addOutput<GenericVectorMessage, FeaturesMessage>("Channel Features");
    out_visualize_ = node_modifier.addOutput<CvMatMessage>("Visualize");
}

void ACFDepthChannel::setupParameters(csapex::Parameterizable& parameters)
{
    parameters.addParameter(param::ParameterFactory::declareRange("window/width",
                                                                  10, 1024, 64, 1),
                            std::bind(&ACFDepthChannel::updateWindow, this));
    parameters.addParameter(param::ParameterFactory::declareRange("window/height",
                                                                  10, 1024, 128, 1),
                            std::bind(&ACFDepthChannel::updateWindow, this));
    parameters.addParameter(param::ParameterFactory::declareBool("window/keep_ratio",
                                                                 false),
                            keep_ratio_);
    parameters.addParameter(param::ParameterFactory::declareBool("window/mirror",
                                                                 false),
                            mirror_);

    parameters.addParameter(param::ParameterFactory::declareRange("aggregate/block_size",
                                                                  1, 32, 4, 1),
                            block_size_);

    static const std::map<std::string, int> available_types = {
            { "binary", static_cast<int>(Type::BINARY) },
            { "ternary", static_cast<int>(Type::TERNARY) },
    };
    parameters.addParameter(param::ParameterFactory::declareParameterSet("channel/type",
                                                                        available_types,
                                                                        static_cast<int>(Type::BINARY)),
                            reinterpret_cast<int&>(type_));

    static const std::map<std::string, int> available_methods = {
            { "median", static_cast<int>(Method::MEDIAN) },
            { "mean", static_cast<int>(Method::MEAN) },
            { "histogram", static_cast<int>(Method::HISTOGRAM) },
    };
    parameters.addParameter(param::ParameterFactory::declareParameterSet("channel/method",
                                                                        available_methods,
                                                                        static_cast<int>(Method::MEDIAN)),
                            reinterpret_cast<int&>(method_));

    parameters.addParameter(param::ParameterFactory::declareRange("channel/threshold",
                                                                 0.0, 1000.0, 0.1, 0.01),
                           threshold_);

   parameters.addParameter(param::ParameterFactory::declareBool("channel/normalize",
                                                                false),
                           normalize_);
}

void ACFDepthChannel::updateWindow()
{
    int old_height = window_height_;

    window_width_  = readParameter<int>("window/width");
    window_height_ = readParameter<int>("window/height");
    if (window_ratio_ == 0.0)
        window_ratio_ = window_height_ / double(window_width_);

    if (keep_ratio_)
    {
        if (window_height_ != old_height)
        {
            window_width_ = window_height_ / window_ratio_;
            setParameter<int>("window/width", window_width_);
        } else
        {
            window_height_ = window_width_ * window_ratio_;
            setParameter<int>("window/height", window_height_);
        }
    }
}

std::vector<float> ACFDepthChannel::extractChannel(const cv::Mat& depth_map) const
{
    cv::Mat aggregated_depth_map;
    cv::resize(depth_map, aggregated_depth_map, cv::Size(depth_map.cols / block_size_, depth_map.rows / block_size_));
    const cv::Mat valid_pixel_mask = aggregated_depth_map != 0;

    double min_value;
    double max_value;
    cv::minMaxLoc(aggregated_depth_map, &min_value, &max_value);

    float center = 0.0f;
    switch (method_)
    {
        case Method::HISTOGRAM:
        {
            const const float BIN_SIZE = 0.25f;
            static const int channels[] = { 0 };
            const int bins[] = { int((max_value - min_value) / BIN_SIZE) };
            const float value_range[] = { float(min_value), float(max_value) + std::numeric_limits<float>::epsilon() };
            const float* ranges[] = { value_range };

            cv::Mat hist;
            cv::calcHist(&aggregated_depth_map, 1, channels, valid_pixel_mask, hist, 1, bins, ranges, true);

            cv::Point max;
            cv::minMaxLoc(hist, nullptr, nullptr, nullptr, &max);

            center = min_value + (max.y + 0.5f) * BIN_SIZE;
            break;
        }
        case Method::MEDIAN:
        {
            cv::Mat values = aggregated_depth_map.reshape(0, 1).clone();

            const auto middle = values.cols / 2;
            std::nth_element(values.begin<float>(), values.begin<float>() + middle, values.end<float>());
            center = values.at<float>(0, middle);
            break;
        }
        case Method::MEAN:
            center = cv::mean(aggregated_depth_map)[0];
            break;
    }

    std::vector<float> feature;
    feature.reserve(aggregated_depth_map.rows * aggregated_depth_map.cols);

    switch (type_)
    {
        case Type::TERNARY:
            std::transform(aggregated_depth_map.begin<float>(), aggregated_depth_map.end<float>(),
                           std::back_inserter(feature),
                           [&](float value)
                           {
                               if (normalize_)
                               {
                                   const float delta = value - center;
                                   if (delta > threshold_)
                                       return delta / float(max_value - (center + threshold_));
                                   else if (delta < -threshold_)
                                       return delta / float(center - threshold_ - min_value);
                                   else
                                       return 0.f;
                               }
                               else
                               {
                                   if (value > center + threshold_)
                                       return 1.f;
                                   else if (value < center - threshold_)
                                       return -1.f;
                                   else
                                       return 0.f;
                               }
                           });
            break;
        case Type::BINARY:
            std::transform(aggregated_depth_map.begin<float>(), aggregated_depth_map.end<float>(),
                           std::back_inserter(feature),
                           [&](float value)
                           {
                               if (normalize_)
                               {
                                   const float delta = value - center;
                                   if (delta > threshold_)
                                       return delta / float(max_value - (center + threshold_));
                                   else if (delta < -threshold_)
                                       return -delta / float(center - threshold_ - min_value);
                                   else
                                       return 0.f;
                               }
                               else
                               {
                                   if (std::abs(value - center) > threshold_)
                                       return 1.f;
                                   else
                                       return 0.f;
                               }
                           });
            break;
    }

    return std::move(feature);
}

void ACFDepthChannel::process()
{
    CvMatMessage::ConstPtr in_image = msg::getMessage<CvMatMessage>(in_image_);
    const cv::Mat& image = in_image->value;

    std::shared_ptr<std::vector<RoiMessage> const> in_rois;
    if (msg::hasMessage(in_rois_))
        in_rois = msg::getMessage<GenericVectorMessage, RoiMessage>(in_rois_);

    if (image.channels() != 1 || image.type() != CV_32F)
        throw std::runtime_error("Only 1 channel float images (depth maps) are supported");

    CvMatMessage::Ptr out_visualize;
    if (msg::isConnected(out_visualize_))
    {
        out_visualize = std::make_shared<CvMatMessage>(enc::bgr, in_image->stamp_micro_seconds);
        out_visualize->frame_id = in_image->frame_id;
        out_visualize->value = cv::Mat(image.rows, image.cols, CV_8UC3, cv::Scalar(0, 0, 0));
    }

    auto out_features = std::make_shared<std::vector<FeaturesMessage>>();

    const auto process_roi = [&](const Roi& roi)
    {
        const cv::Rect roi_region = roi.rect() & cv::Rect(0, 0, image.cols, image.rows);

        FeaturesMessage feature(in_image->stamp_micro_seconds);
        feature.classification = roi.classification();

        cv::Mat image_region;
        cv::resize(cv::Mat(image, roi_region), image_region, cv::Size(window_width_, window_height_));

        feature.value = extractChannel(image_region);
        out_features->push_back(feature);

        if (out_visualize)
        {
            const float scale_x = float(image_region.cols / block_size_) / roi_region.width;
            const float scale_y = float(image_region.rows / block_size_) / roi_region.height;

            for (int dy = 0; dy < roi_region.height; ++dy)
                for (int dx = 0; dx < roi_region.width; ++dx)
                {
                    const int ldx = dx * scale_x;
                    const int ldy = dy * scale_y;
                    const int step = window_width_ / block_size_;

                    const float value = feature.value[ldx + step * ldy];
                    cv::Vec3b& dst = out_visualize->value.at<cv::Vec3b>(roi_region.y + dy, roi_region.x + dx);

                    if (value == 0)
                         dst = cv::Vec3b(0, 255, 0);
                    else if (value < 0)
                        dst = cv::Vec3b(0, 0, 255) * std::abs(value);
                    else if (value > 0)
                        dst = cv::Vec3b(255, 0, 0) * std::abs(value);
                }
        }

        if (mirror_)
        {
            cv::flip(image_region, image_region, 1);

            feature.value = extractChannel(image_region);
            out_features->push_back(std::move(feature));
        }
    };

    if (in_rois)
    {
        for (const RoiMessage& roi : *in_rois)
            process_roi(roi.value);
    }
    else
        process_roi(csapex::Roi(0, 0, image.cols, image.rows));

    msg::publish<GenericVectorMessage, FeaturesMessage>(out_channels_, out_features);
    if (out_visualize)
        msg::publish(out_visualize_, out_visualize);
}
<commit_msg>vision: ACFDepthChannel - filter valid points in all methods<commit_after>#include "acf_depth_channel.hpp"

#include <csapex/msg/io.h>
#include <csapex/msg/generic_vector_message.hpp>
#include <csapex/model/node_modifier.h>
#include <csapex/param/parameter_factory.h>
#include <csapex/utility/register_apex_plugin.h>

#include <csapex_opencv/cv_mat_message.h>
#include <csapex_opencv/roi_message.h>
#include <csapex_ml/features_message.h>

CSAPEX_REGISTER_CLASS(csapex::vision::ACFDepthChannel, csapex::Node)

using namespace csapex;
using namespace csapex::vision;
using namespace csapex::connection_types;

void ACFDepthChannel::setup(csapex::NodeModifier& node_modifier)
{
    in_image_      = node_modifier.addInput<CvMatMessage>("Depth Map");
    in_rois_       = node_modifier.addOptionalInput<GenericVectorMessage, RoiMessage>("ROIs");
    out_channels_  = node_modifier.addOutput<GenericVectorMessage, FeaturesMessage>("Channel Features");
    out_visualize_ = node_modifier.addOutput<CvMatMessage>("Visualize");
}

void ACFDepthChannel::setupParameters(csapex::Parameterizable& parameters)
{
    parameters.addParameter(param::ParameterFactory::declareRange("window/width",
                                                                  10, 1024, 64, 1),
                            std::bind(&ACFDepthChannel::updateWindow, this));
    parameters.addParameter(param::ParameterFactory::declareRange("window/height",
                                                                  10, 1024, 128, 1),
                            std::bind(&ACFDepthChannel::updateWindow, this));
    parameters.addParameter(param::ParameterFactory::declareBool("window/keep_ratio",
                                                                 false),
                            keep_ratio_);
    parameters.addParameter(param::ParameterFactory::declareBool("window/mirror",
                                                                 false),
                            mirror_);

    parameters.addParameter(param::ParameterFactory::declareRange("aggregate/block_size",
                                                                  1, 32, 4, 1),
                            block_size_);

    static const std::map<std::string, int> available_types = {
            { "binary", static_cast<int>(Type::BINARY) },
            { "ternary", static_cast<int>(Type::TERNARY) },
    };
    parameters.addParameter(param::ParameterFactory::declareParameterSet("channel/type",
                                                                        available_types,
                                                                        static_cast<int>(Type::BINARY)),
                            reinterpret_cast<int&>(type_));

    static const std::map<std::string, int> available_methods = {
            { "median", static_cast<int>(Method::MEDIAN) },
            { "mean", static_cast<int>(Method::MEAN) },
            { "histogram", static_cast<int>(Method::HISTOGRAM) },
    };
    parameters.addParameter(param::ParameterFactory::declareParameterSet("channel/method",
                                                                        available_methods,
                                                                        static_cast<int>(Method::MEDIAN)),
                            reinterpret_cast<int&>(method_));

    parameters.addParameter(param::ParameterFactory::declareRange("channel/threshold",
                                                                 0.0, 1000.0, 0.1, 0.01),
                           threshold_);

   parameters.addParameter(param::ParameterFactory::declareBool("channel/normalize",
                                                                false),
                           normalize_);
}

void ACFDepthChannel::updateWindow()
{
    int old_height = window_height_;

    window_width_  = readParameter<int>("window/width");
    window_height_ = readParameter<int>("window/height");
    if (window_ratio_ == 0.0)
        window_ratio_ = window_height_ / double(window_width_);

    if (keep_ratio_)
    {
        if (window_height_ != old_height)
        {
            window_width_ = window_height_ / window_ratio_;
            setParameter<int>("window/width", window_width_);
        } else
        {
            window_height_ = window_width_ * window_ratio_;
            setParameter<int>("window/height", window_height_);
        }
    }
}

std::vector<float> ACFDepthChannel::extractChannel(const cv::Mat& depth_map) const
{
    cv::Mat aggregated_depth_map;
    cv::resize(depth_map, aggregated_depth_map, cv::Size(depth_map.cols / block_size_, depth_map.rows / block_size_));
    const cv::Mat valid_pixel_mask = aggregated_depth_map > 0;

    double min_value;
    double max_value;
    cv::minMaxLoc(aggregated_depth_map, &min_value, &max_value);

    float center = 0.0f;
    switch (method_)
    {
        case Method::HISTOGRAM:
        {
            const static float BIN_SIZE = 0.25f;
            static const int channels[] = { 0 };
            const int bins[] = { int((max_value - min_value) / BIN_SIZE) };
            const float value_range[] = { float(min_value), float(max_value) + std::numeric_limits<float>::epsilon() };
            const float* ranges[] = { value_range };

            cv::Mat hist;
            cv::calcHist(&aggregated_depth_map, 1, channels, valid_pixel_mask, hist, 1, bins, ranges, true);

            cv::Point max;
            cv::minMaxLoc(hist, nullptr, nullptr, nullptr, &max);

            center = min_value + (max.y + 0.5f) * BIN_SIZE;
            break;
        }
        case Method::MEDIAN:
        {
            cv::Mat values = aggregated_depth_map.reshape(0, 1).clone();
            const int invalid_pixel_count = values.cols - cv::countNonZero(valid_pixel_mask);

            const auto middle = invalid_pixel_count + (values.cols - invalid_pixel_count) / 2;
            std::nth_element(values.begin<float>(), values.begin<float>() + middle, values.end<float>());
            center = values.at<float>(0, middle);
            break;
        }
        case Method::MEAN:
            center = cv::mean(aggregated_depth_map, valid_pixel_mask)[0];
            break;
    }

    std::vector<float> feature;
    feature.reserve(aggregated_depth_map.rows * aggregated_depth_map.cols);

    switch (type_)
    {
        case Type::TERNARY:
            std::transform(aggregated_depth_map.begin<float>(), aggregated_depth_map.end<float>(),
                           std::back_inserter(feature),
                           [&](float value)
                           {
                               if (normalize_)
                               {
                                   const float delta = value - center;
                                   if (delta > threshold_)
                                       return delta / float(max_value - (center + threshold_));
                                   else if (delta < -threshold_)
                                       return delta / float(center - threshold_ - min_value);
                                   else
                                       return 0.f;
                               }
                               else
                               {
                                   if (value > center + threshold_)
                                       return 1.f;
                                   else if (value < center - threshold_)
                                       return -1.f;
                                   else
                                       return 0.f;
                               }
                           });
            break;
        case Type::BINARY:
            std::transform(aggregated_depth_map.begin<float>(), aggregated_depth_map.end<float>(),
                           std::back_inserter(feature),
                           [&](float value)
                           {
                               if (normalize_)
                               {
                                   const float delta = value - center;
                                   if (delta > threshold_)
                                       return delta / float(max_value - (center + threshold_));
                                   else if (delta < -threshold_)
                                       return -delta / float(center - threshold_ - min_value);
                                   else
                                       return 0.f;
                               }
                               else
                               {
                                   if (std::abs(value - center) > threshold_)
                                       return 1.f;
                                   else
                                       return 0.f;
                               }
                           });
            break;
    }

    return std::move(feature);
}

void ACFDepthChannel::process()
{
    CvMatMessage::ConstPtr in_image = msg::getMessage<CvMatMessage>(in_image_);
    const cv::Mat& image = in_image->value;

    std::shared_ptr<std::vector<RoiMessage> const> in_rois;
    if (msg::hasMessage(in_rois_))
        in_rois = msg::getMessage<GenericVectorMessage, RoiMessage>(in_rois_);

    if (image.channels() != 1 || image.type() != CV_32F)
        throw std::runtime_error("Only 1 channel float images (depth maps) are supported");

    CvMatMessage::Ptr out_visualize;
    if (msg::isConnected(out_visualize_))
    {
        out_visualize = std::make_shared<CvMatMessage>(enc::bgr, in_image->stamp_micro_seconds);
        out_visualize->frame_id = in_image->frame_id;
        out_visualize->value = cv::Mat(image.rows, image.cols, CV_8UC3, cv::Scalar(0, 0, 0));
    }

    auto out_features = std::make_shared<std::vector<FeaturesMessage>>();

    const auto process_roi = [&](const Roi& roi)
    {
        const cv::Rect roi_region = roi.rect() & cv::Rect(0, 0, image.cols, image.rows);

        FeaturesMessage feature(in_image->stamp_micro_seconds);
        feature.classification = roi.classification();

        cv::Mat image_region;
        cv::resize(cv::Mat(image, roi_region), image_region, cv::Size(window_width_, window_height_));

        feature.value = extractChannel(image_region);
        out_features->push_back(feature);

        if (out_visualize)
        {
            const float scale_x = float(image_region.cols / block_size_) / roi_region.width;
            const float scale_y = float(image_region.rows / block_size_) / roi_region.height;

            for (int dy = 0; dy < roi_region.height; ++dy)
                for (int dx = 0; dx < roi_region.width; ++dx)
                {
                    const int ldx = dx * scale_x;
                    const int ldy = dy * scale_y;
                    const int step = window_width_ / block_size_;

                    const float value = feature.value[ldx + step * ldy];
                    cv::Vec3b& dst = out_visualize->value.at<cv::Vec3b>(roi_region.y + dy, roi_region.x + dx);

                    if (value == 0)
                         dst = cv::Vec3b(0, 255, 0);
                    else if (value < 0)
                        dst = cv::Vec3b(0, 0, 255) * std::abs(value);
                    else if (value > 0)
                        dst = cv::Vec3b(255, 0, 0) * std::abs(value);
                }
        }

        if (mirror_)
        {
            cv::flip(image_region, image_region, 1);

            feature.value = extractChannel(image_region);
            out_features->push_back(std::move(feature));
        }
    };

    if (in_rois)
    {
        for (const RoiMessage& roi : *in_rois)
            process_roi(roi.value);
    }
    else
        process_roi(csapex::Roi(0, 0, image.cols, image.rows));

    msg::publish<GenericVectorMessage, FeaturesMessage>(out_channels_, out_features);
    if (out_visualize)
        msg::publish(out_visualize_, out_visualize);
}
<|endoftext|>


<commit_before>// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
#include <bse/bsemain.hh>
#include <bse/testing.hh>
#include "bse/internal.hh"

using Bse::printerr;
typedef Bse::IntegrityCheck::TestFunc TestFunc;

// == BSE_INTEGRITY_TEST Registry ==
struct TestEntry {
  TestFunc    test;
  const char *func;
  const char *file;
  int         line;
  TestEntry (const char *_file, int _line, const char *_func, TestFunc _test) :
    test (_test), func (_func), file (_file), line (_line)
  {}
};
static std::vector<TestEntry> *tests = NULL; // NOTE, this must be available for high priority early constructors

// == BSE_INTEGRITY_CHECK Activation ==
namespace Bse {
// Override Bse weak symbol to enable Bse's internal integrity tests, see bcore.hh
const bool IntegrityCheck::enabled = true;
// Registration function called for all integrity tests
void
IntegrityCheck::Test::register_test (const char *file, int line, const char *func, TestFunc test)
{
  if (!tests)
    tests = new std::vector<TestEntry>();
  tests->push_back (TestEntry (file, line, func, test));
}
} // Bse

static int      // for backtrace tests
my_compare_func (const void*, const void*)
{
  BSE_BACKTRACE();
  exit (0);
}

// == Main test program ==
int
main (int argc, char *argv[])
{
  bse_init_test (&argc, argv);

  if (argc >= 2 && String ("--backtrace") == argv[1])
    {
      char dummy_array[3] = { 1, 2, 3 };
      qsort (dummy_array, 3, 1, my_compare_func);
    }
  else if (argc >= 2 && String ("--assert_return1") == argv[1])
    {
      assert_return (1, 0);
      return 0;
    }
  else if (argc >= 2 && String ("--assert_return0") == argv[1])
    {
      Bse::set_debug_flags (Bse::DebugFlags::SIGQUIT_ON_ABORT);
      assert_return (0, 0);
      return 0;
    }
  else if (argc >= 2 && String ("--assert_return_unreached") == argv[1])
    {
      Bse::set_debug_flags (Bse::DebugFlags::SIGQUIT_ON_ABORT);
      assert_return_unreached (0);
      return 0;
    }
  else if (argc >= 2 && String ("--fatal_error") == argv[1])
    {
      Bse::set_debug_flags (Bse::DebugFlags::SIGQUIT_ON_ABORT);
      Bse::fatal_error ("got argument --fatal_error");
      return 0;
    }
  else if (argc >= 2 && String ("--return_unless0") == argv[1])
    {
      return_unless (0, 7);
      return 0;
    }
  else if (argc >= 2 && String ("--return_unless1") == argv[1])
    {
      return_unless (1, 8);
      return 0;
    }

  // integrity tests
  assert_return (Bse::IntegrityCheck::checks_enabled() == true, -1);

  if (tests)
    for (const auto &te : *tests)
      { // note, more than one space after "TESTING:" confuses emacs file:line matches
        printerr ("  TESTING: %s:%u: %s…\n", te.file, te.line, te.func);
        te.test();
        printerr ("    …DONE  (%s)\n", te.func);
      }

  return 0;
}
<commit_msg>BSE: integrity: always use SIGQUIT instead of abort() to avoid apport<commit_after>// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
#include <bse/bsemain.hh>
#include <bse/testing.hh>
#include "bse/internal.hh"

using Bse::printerr;
typedef Bse::IntegrityCheck::TestFunc TestFunc;

// == BSE_INTEGRITY_TEST Registry ==
struct TestEntry {
  TestFunc    test;
  const char *func;
  const char *file;
  int         line;
  TestEntry (const char *_file, int _line, const char *_func, TestFunc _test) :
    test (_test), func (_func), file (_file), line (_line)
  {}
};
static std::vector<TestEntry> *tests = NULL; // NOTE, this must be available for high priority early constructors

// == BSE_INTEGRITY_CHECK Activation ==
namespace Bse {
// Override Bse weak symbol to enable Bse's internal integrity tests, see bcore.hh
const bool IntegrityCheck::enabled = true;
// Registration function called for all integrity tests
void
IntegrityCheck::Test::register_test (const char *file, int line, const char *func, TestFunc test)
{
  if (!tests)
    tests = new std::vector<TestEntry>();
  tests->push_back (TestEntry (file, line, func, test));
}
} // Bse

static int      // for backtrace tests
my_compare_func (const void*, const void*)
{
  BSE_BACKTRACE();
  exit (0);
}

// == Main test program ==
int
main (int argc, char *argv[])
{
  bse_init_test (&argc, argv);
  Bse::set_debug_flags (Bse::DebugFlags::SIGQUIT_ON_ABORT);

  if (argc >= 2 && String ("--backtrace") == argv[1])
    {
      char dummy_array[3] = { 1, 2, 3 };
      qsort (dummy_array, 3, 1, my_compare_func);
    }
  else if (argc >= 2 && String ("--assert_return1") == argv[1])
    {
      assert_return (1, 0);
      return 0;
    }
  else if (argc >= 2 && String ("--assert_return0") == argv[1])
    {
      assert_return (0, 0);
      return 0;
    }
  else if (argc >= 2 && String ("--assert_return_unreached") == argv[1])
    {
      assert_return_unreached (0);
      return 0;
    }
  else if (argc >= 2 && String ("--fatal_error") == argv[1])
    {
      Bse::fatal_error ("got argument --fatal_error");
      return 0;
    }
  else if (argc >= 2 && String ("--return_unless0") == argv[1])
    {
      return_unless (0, 7);
      return 0;
    }
  else if (argc >= 2 && String ("--return_unless1") == argv[1])
    {
      return_unless (1, 8);
      return 0;
    }

  // integrity tests
  assert_return (Bse::IntegrityCheck::checks_enabled() == true, -1);

  if (tests)
    for (const auto &te : *tests)
      { // note, more than one space after "TESTING:" confuses emacs file:line matches
        printerr ("  TESTING: %s:%u: %s…\n", te.file, te.line, te.func);
        te.test();
        printerr ("    …DONE  (%s)\n", te.func);
      }

  return 0;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "GSCameraPlayer.h"
#include "IpCameraPipeline.h"
#include "WebCameraPipeline.h"

using namespace vosvideo::cameraplayer;

GSCameraPlayer::GSCameraPlayer()
{
	LOG_TRACE("GSCameraPlayer created");
}

GSCameraPlayer::~GSCameraPlayer()
{
	LOG_TRACE("GSCameraPlayer destroying camera player");
	delete _pipeline;
}

int32_t GSCameraPlayer::OpenURL(vosvideo::data::CameraConfMsg& cameraConf)
{
	if (_state == PlayerState::OpenPending ||
		_state == PlayerState::Started ||
		_state == PlayerState::Paused ||
		_state == PlayerState::Stopped ||
		_state == PlayerState::Closing)
	{
		return -1;
	}

	std::wstring waudioUri;
	std::wstring wvideoUri;
	cameraConf.GetUris(waudioUri, wvideoUri);

	_deviceId = cameraConf.GetCameraId();
	_deviceName = cameraConf.GetCameraName();

	std::wstring username;
	std::wstring password;
	cameraConf.GetCredentials(username, password);

	bool isRecordingEnabled = false;
	std::wstring recordingFolder;
	uint32_t recordingLength = 0;
	uint32_t maxFilesNum = 0;
	vosvideo::data::CameraRecordingMode recordingMode;
	cameraConf.GetFileSinkParameters(isRecordingEnabled, recordingFolder, recordingLength, maxFilesNum, recordingMode);
	cameraType_ = cameraConf.GetCameraType();

	if (wvideoUri != L"webcamera")
	{
		_pipeline = new IpCameraPipeline(
			util::StringUtil::ToString(wvideoUri),
			username,
			password,
			isRecordingEnabled,
			recordingMode,
			recordingFolder,
			recordingLength,
			maxFilesNum,
			_deviceName);
	}
	else
	{
		_pipeline = new WebCameraPipeline(
			isRecordingEnabled,
			recordingMode,
			recordingFolder,
			recordingLength,
			maxFilesNum,
			_deviceName);
	}

	_pipeline->Create();

	////Need to convert to std::string due to LOG_TRACE not working with std::wstring
	//this->_deviceVideoUri = std::string(wvideoUri.begin(), wvideoUri.end());
	//std::string audioUri(waudioUri.begin(), waudioUri.end());

	//LOG_TRACE("GSCameraPlayer Opening Video URI " << this->_deviceVideoUri << " Audio URI " << audioUri);

	//this->_appThread = new boost::thread(boost::bind(&GSCameraPlayer::AppThreadStart, this));
	//this->_appThread->detach();

	_state = PlayerState::OpenPending;
	return 0;
}

void GSCameraPlayer::GetWebRtcCapability(webrtc::VideoCaptureCapability& webRtcCapability)
{
	LOG_TRACE("GSCameraPlayer GetWebRtcCapability called");
	_pipeline->GetWebRtcCapability(webRtcCapability);
}

int32_t GSCameraPlayer::Play(){
	LOG_TRACE("GSCameraPlayer Play called");
	return -1;
}

int32_t GSCameraPlayer::Pause()
{
	LOG_TRACE("GSCameraPlayer Paused called");
	return -1;
}

int32_t GSCameraPlayer::Stop()
{
	LOG_TRACE("GSCameraPlayer Stop called");
	return -1;
}

int32_t GSCameraPlayer::Shutdown()
{
	LOG_TRACE("GSCameraPlayer Shutdown called");
	return -1;
}

PlayerState GSCameraPlayer::GetState(std::shared_ptr<vosvideo::data::SendData>& lastErrMsg) const
{
	LOG_TRACE("GSCameraPlayer GetState(shared_ptr) called");
	return _state;
}

PlayerState GSCameraPlayer::GetState() const
{
	LOG_TRACE("GSCameraPlayer GetState called");
	return _state;
}

// Probably most important method, through it camera communicates to WebRTC
void GSCameraPlayer::SetExternalCapturer(webrtc::VideoCaptureExternal* captureObserver)
{
	LOG_TRACE("GSCameraPlayer SetExternalCapturer called");
	_pipeline->AddExternalCapturer(captureObserver);
}

void GSCameraPlayer::RemoveExternalCapturers()
{
	LOG_TRACE("GSCameraPlayer RemoveExternalCapturers called");
	_pipeline->RemoveAllExternalCapturers();
}

void GSCameraPlayer::RemoveExternalCapturer(webrtc::VideoCaptureExternal* captureObserver)
{
	LOG_TRACE("GSCameraPlayer RemoveExternalCapturer called");
	_pipeline->RemoveExternalCapturer(captureObserver);
}

uint32_t GSCameraPlayer::GetDeviceId() const
{
	LOG_TRACE("GSCameraPlayer GetDeviceId called");
	return _deviceId;
}
<commit_msg>Less traces<commit_after>#include "stdafx.h"
#include "GSCameraPlayer.h"
#include "IpCameraPipeline.h"
#include "WebCameraPipeline.h"

using namespace vosvideo::cameraplayer;

GSCameraPlayer::GSCameraPlayer()
{
	LOG_TRACE("GSCameraPlayer created");
}

GSCameraPlayer::~GSCameraPlayer()
{
	LOG_TRACE("GSCameraPlayer destroying camera player");
	delete _pipeline;
}

int32_t GSCameraPlayer::OpenURL(vosvideo::data::CameraConfMsg& cameraConf)
{
	if (_state == PlayerState::OpenPending ||
		_state == PlayerState::Started ||
		_state == PlayerState::Paused ||
		_state == PlayerState::Stopped ||
		_state == PlayerState::Closing)
	{
		return -1;
	}

	std::wstring waudioUri;
	std::wstring wvideoUri;
	cameraConf.GetUris(waudioUri, wvideoUri);

	_deviceId = cameraConf.GetCameraId();
	_deviceName = cameraConf.GetCameraName();

	std::wstring username;
	std::wstring password;
	cameraConf.GetCredentials(username, password);

	bool isRecordingEnabled = false;
	std::wstring recordingFolder;
	uint32_t recordingLength = 0;
	uint32_t maxFilesNum = 0;
	vosvideo::data::CameraRecordingMode recordingMode;
	cameraConf.GetFileSinkParameters(isRecordingEnabled, recordingFolder, recordingLength, maxFilesNum, recordingMode);
	cameraType_ = cameraConf.GetCameraType();

	if (wvideoUri != L"webcamera")
	{
		_pipeline = new IpCameraPipeline(
			util::StringUtil::ToString(wvideoUri),
			username,
			password,
			isRecordingEnabled,
			recordingMode,
			recordingFolder,
			recordingLength,
			maxFilesNum,
			_deviceName);
	}
	else
	{
		_pipeline = new WebCameraPipeline(
			isRecordingEnabled,
			recordingMode,
			recordingFolder,
			recordingLength,
			maxFilesNum,
			_deviceName);
	}

	_pipeline->Create();

	////Need to convert to std::string due to LOG_TRACE not working with std::wstring
	//this->_deviceVideoUri = std::string(wvideoUri.begin(), wvideoUri.end());
	//std::string audioUri(waudioUri.begin(), waudioUri.end());

	//LOG_TRACE("GSCameraPlayer Opening Video URI " << this->_deviceVideoUri << " Audio URI " << audioUri);

	//this->_appThread = new boost::thread(boost::bind(&GSCameraPlayer::AppThreadStart, this));
	//this->_appThread->detach();

	_state = PlayerState::OpenPending;
	return 0;
}

void GSCameraPlayer::GetWebRtcCapability(webrtc::VideoCaptureCapability& webRtcCapability)
{
	LOG_TRACE("GSCameraPlayer GetWebRtcCapability called");
	_pipeline->GetWebRtcCapability(webRtcCapability);
}

int32_t GSCameraPlayer::Play(){
	LOG_TRACE("GSCameraPlayer Play called");
	return -1;
}

int32_t GSCameraPlayer::Pause()
{
	LOG_TRACE("GSCameraPlayer Paused called");
	return -1;
}

int32_t GSCameraPlayer::Stop()
{
	LOG_TRACE("GSCameraPlayer Stop called");
	return -1;
}

int32_t GSCameraPlayer::Shutdown()
{
	LOG_TRACE("GSCameraPlayer Shutdown called");
	return -1;
}

PlayerState GSCameraPlayer::GetState(std::shared_ptr<vosvideo::data::SendData>& lastErrMsg) const
{
	LOG_TRACE("GSCameraPlayer GetState(shared_ptr) called");
	return _state;
}

PlayerState GSCameraPlayer::GetState() const
{
	return _state;
}

// Probably most important method, through it camera communicates to WebRTC
void GSCameraPlayer::SetExternalCapturer(webrtc::VideoCaptureExternal* captureObserver)
{
	LOG_TRACE("GSCameraPlayer SetExternalCapturer called");
	_pipeline->AddExternalCapturer(captureObserver);
}

void GSCameraPlayer::RemoveExternalCapturers()
{
	LOG_TRACE("GSCameraPlayer RemoveExternalCapturers called");
	_pipeline->RemoveAllExternalCapturers();
}

void GSCameraPlayer::RemoveExternalCapturer(webrtc::VideoCaptureExternal* captureObserver)
{
	LOG_TRACE("GSCameraPlayer RemoveExternalCapturer called");
	_pipeline->RemoveExternalCapturer(captureObserver);
}

uint32_t GSCameraPlayer::GetDeviceId() const
{
	LOG_TRACE("GSCameraPlayer GetDeviceId called");
	return _deviceId;
}
<|endoftext|>


<commit_before>#ifndef SKSAT_WINDOW_HPP
#define SKSAT_WINDOW_HPP

#include <sksat/common.hpp>
#include <sksat/platform.hpp>

namespace sksat {

class window_base {
public:
	window_base() : opend(false), xsize(default_xsize), ysize(default_ysize), xpos(default_xpos), ypos(default_ypos) {}
	window_base(size_t x, size_t y) : opend(false), xsize(x), ysize(y), xpos(default_xpos), ypos(default_ypos) {}
	window_base(sksat::string &t, size_t x, size_t y) : opend(false), title(t), xsize(x), ysize(y), xpos(default_xpos), ypos(default_ypos) {}

	void open(){ opend = api_open(); }
	void open(size_t x, size_t y){ open(); set_size(x,y); }
	void open(sksat::string &t){ set_title(t); open(); }
	void open(sksat::string &t, size_t x, size_t y){ set_title(t); open(x,y); }

	void close(){ if(opend) api_close(); opend=false; }

	void show(){ if(opend) api_show(); }

	void set_title(sksat::string &t){ title = t; set_title(t.c_str()); }
	void set_title(const char *t){ title = t; api_set_title(t);  }
	sksat::string get_title() const { return title; }

	virtual void set_size(size_t x, size_t y){
		xsize=x;
		ysize=y;
		if(opend)
			api_set_size(x,y);
	}
	void set_xsize(size_t x){ set_size(x, ysize); }
	void set_ysize(size_t y){ set_size(xsize, y); }
	size_t get_xsize() const { return xsize; }
	size_t get_ysize() const { return ysize; }

	operator bool () const { return opend; }

	// 描画関数
/*
	void draw_point(sksat::color &col, size_t x, size_t y);
	void draw_line(sksat::color &col, size_t x0, size_t y0, size_t x1, size_t y1);
	void draw_rect(sksat::color &col, size_t x0, size_t y0, size_t x1, size_t y1, bool fill);

	// set_color()でセットした色
	void draw_point(size_t x, size_t y);
	void draw_line(size_t x0, size_t y0, size_t x1, size_t y1);
	void draw_rect(size_t x0, size_t y0, size_t x1, size_t y1, bool fill);

	void fill_rect(size_t x0, size_t y0, size_t x1, size_t y1){ draw_rect(x0,y0,x1,y1,true); }
*/

	inline void flush(){ if(opend) api_flush(); }

	inline bool step_loop(){ if(opend) return api_step_loop(); }
	inline void loop(){ while(api_step_loop()); }

protected: // 環境依存部(純粋仮想関数)
	virtual bool api_open() = 0;
	virtual void api_close() = 0;
	virtual void api_show() = 0;
	virtual void api_set_title(const char *t) = 0;
	virtual void api_set_size(size_t x, size_t y) = 0;
	virtual void api_flush() = 0;
	virtual bool api_step_loop() = 0;
public:
	static size_t default_xsize, default_ysize;
	static size_t default_xpos, default_ypos;
protected:
	bool opend;
	size_t xsize, ysize;
	size_t xpos, ypos;
	sksat::string title;
};

size_t window_base::default_xsize = 100;
size_t window_base::default_ysize = 100;
size_t window_base::default_xpos  = 0;
size_t window_base::default_ypos  = 0;

}

#if defined(OS_WIN32)
	#include <sksat/win32/window.hpp>
	namespace sksat{ using sksat::win32::window; }
#elif defined(OS_LINUX)
	#include <sksat/linux/window.hpp>
	namespace sksat{ using sksat::linux::window; }
#else
	#error not implemented.
#endif

#endif
<commit_msg>[ADD] move func<commit_after>#ifndef SKSAT_WINDOW_HPP
#define SKSAT_WINDOW_HPP

#include <sksat/common.hpp>
#include <sksat/platform.hpp>

namespace sksat {

class window_base {
public:
	window_base() : opend(false), xsize(default_xsize), ysize(default_ysize), xpos(default_xpos), ypos(default_ypos) {}
	window_base(size_t x, size_t y) : opend(false), xsize(x), ysize(y), xpos(default_xpos), ypos(default_ypos) {}
	window_base(sksat::string &t, size_t x, size_t y) : opend(false), title(t), xsize(x), ysize(y), xpos(default_xpos), ypos(default_ypos) {}

	void open(){ opend = api_open(); }
	void open(size_t x, size_t y){ open(); set_size(x,y); }
	void open(sksat::string &t){ set_title(t); open(); }
	void open(sksat::string &t, size_t x, size_t y){ set_title(t); open(x,y); }

	void close(){ if(opend) api_close(); opend=false; }

	void show(){ if(opend) api_show(); }

	void set_title(sksat::string &t){ title = t; set_title(t.c_str()); }
	void set_title(const char *t){ title = t; api_set_title(t);  }
	sksat::string get_title() const { return title; }

	virtual void set_size(size_t x, size_t y){
		xsize=x;
		ysize=y;
		if(opend)
			api_set_size(x,y);
	}
	void set_xsize(size_t x){ set_size(x, ysize); }
	void set_ysize(size_t y){ set_size(xsize, y); }
	size_t get_xsize() const { return xsize; }
	size_t get_ysize() const { return ysize; }

	void move(size_t x, size_t y){ xpos=x; ypos=y; api_move(x,y); }
	void set_pos(size_t x, size_t y){ move(x,y); }
	void set_xpos(size_t x){ move(x,ypos); }
	void set_ypos(size_t y){ move(xpos,y); }

	operator bool () const { return opend; }

	// 描画関数
/*
	void draw_point(sksat::color &col, size_t x, size_t y);
	void draw_line(sksat::color &col, size_t x0, size_t y0, size_t x1, size_t y1);
	void draw_rect(sksat::color &col, size_t x0, size_t y0, size_t x1, size_t y1, bool fill);

	// set_color()でセットした色
	void draw_point(size_t x, size_t y);
	void draw_line(size_t x0, size_t y0, size_t x1, size_t y1);
	void draw_rect(size_t x0, size_t y0, size_t x1, size_t y1, bool fill);

	void fill_rect(size_t x0, size_t y0, size_t x1, size_t y1){ draw_rect(x0,y0,x1,y1,true); }
*/

	inline void flush(){ if(opend) api_flush(); }

	inline bool step_loop(){ if(opend) return api_step_loop(); }
	inline void loop(){ while(api_step_loop()); }

protected: // 環境依存部(純粋仮想関数)
	virtual bool api_open() = 0;
	virtual void api_close() = 0;
	virtual void api_show() = 0;
	virtual void api_set_title(const char *t) = 0;
	virtual void api_set_size(size_t x, size_t y) = 0;
	virtual void api_flush() = 0;
	virtual void api_move() = 0;
	virtual bool api_step_loop() = 0;
public:
	static size_t default_xsize, default_ysize;
	static size_t default_xpos, default_ypos;
protected:
	bool opend;
	size_t xsize, ysize;
	size_t xpos, ypos;
	sksat::string title;
};

size_t window_base::default_xsize = 100;
size_t window_base::default_ysize = 100;
size_t window_base::default_xpos  = 0;
size_t window_base::default_ypos  = 0;

}

#if defined(OS_WIN32)
	#include <sksat/win32/window.hpp>
	namespace sksat{ using sksat::win32::window; }
#elif defined(OS_LINUX)
	#include <sksat/linux/window.hpp>
	namespace sksat{ using sksat::linux::window; }
#else
	#error not implemented.
#endif

#endif
<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "weight_manager.hpp"

#include <cmath>
#include <string>
#include <utility>
#include "../common/type.hpp"
#include "datum_to_fv_converter.hpp"

namespace jubatus {
namespace core {
namespace fv_converter {

namespace {

struct is_zero {
  bool operator()(const std::pair<std::string, float>& p) {
    return p.second == 0;
  }
};

}  // namespace

weight_manager::weight_manager()
    : diff_weights_(),
      master_weights_() {
}

void weight_manager::update_weight(const common::sfv_t& fv) {
  diff_weights_.update_document_frequency(fv);
}

void weight_manager::get_weight(common::sfv_t& fv) const {
  for (common::sfv_t::iterator it = fv.begin(); it != fv.end(); ++it) {
    double global_weight = get_global_weight(it->first);
    it->second *= global_weight;
  }
  fv.erase(remove_if(fv.begin(), fv.end(), is_zero()), fv.end());
}

double weight_manager::get_global_weight(const std::string& key) const {
  size_t p = key.find_last_of('/');
  if (p == std::string::npos) {
    return 1.0;
  }
  std::string type = key.substr(p + 1);
  if (type == "bin") {
    return 1.0;
  } else if (type == "idf") {
    double doc_count = get_document_count();
    double doc_freq = get_document_frequency(key);
    return log((doc_count + 1) / (doc_freq + 1));
  } else if (type == "weight") {
    p = key.find_last_of('#');
    if (p == std::string::npos) {
      return 0;
    } else {
      return get_user_weight(key.substr(0, p));
    }
  } else {
    return 1;
  }
}

void weight_manager::add_weight(const std::string& key, float weight) {
  diff_weights_.add_weight(key, weight);
}

}  // namespace fv_converter
}  // namespace core
}  // namespace jubatus
<commit_msg>add explicit cast for global_weight<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "weight_manager.hpp"

#include <cmath>
#include <string>
#include <utility>
#include "../common/type.hpp"
#include "datum_to_fv_converter.hpp"

namespace jubatus {
namespace core {
namespace fv_converter {

namespace {

struct is_zero {
  bool operator()(const std::pair<std::string, float>& p) {
    return p.second == 0;
  }
};

}  // namespace

weight_manager::weight_manager()
    : diff_weights_(),
      master_weights_() {
}

void weight_manager::update_weight(const common::sfv_t& fv) {
  diff_weights_.update_document_frequency(fv);
}

void weight_manager::get_weight(common::sfv_t& fv) const {
  for (common::sfv_t::iterator it = fv.begin(); it != fv.end(); ++it) {
    double global_weight = get_global_weight(it->first);
    it->second = static_cast<float>(it->second * global_weight);
  }
  fv.erase(remove_if(fv.begin(), fv.end(), is_zero()), fv.end());
}

double weight_manager::get_global_weight(const std::string& key) const {
  size_t p = key.find_last_of('/');
  if (p == std::string::npos) {
    return 1.0;
  }
  std::string type = key.substr(p + 1);
  if (type == "bin") {
    return 1.0;
  } else if (type == "idf") {
    double doc_count = get_document_count();
    double doc_freq = get_document_frequency(key);
    return log((doc_count + 1) / (doc_freq + 1));
  } else if (type == "weight") {
    p = key.find_last_of('#');
    if (p == std::string::npos) {
      return 0;
    } else {
      return get_user_weight(key.substr(0, p));
    }
  } else {
    return 1;
  }
}

void weight_manager::add_weight(const std::string& key, float weight) {
  diff_weights_.add_weight(key, weight);
}

}  // namespace fv_converter
}  // namespace core
}  // namespace jubatus
<|endoftext|>