<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <gtest/gtest.h>
#include <CommonAPI/SerializableStruct.h>
#include <CommonAPI/SerializableVariant.h>

class TypeStream {
  public:
    virtual ~TypeStream() {}

    virtual void writeBoolType() = 0;

    virtual void writeInt8Type() = 0;
    virtual void writeInt16Type() = 0;
    virtual void writeInt32Type() = 0;
    virtual void writeInt64Type() = 0;

    virtual void writeUInt8Type() = 0;
    virtual void writeUInt16Type() = 0;
    virtual void writeUInt32Type() = 0;
    virtual void writeUInt64Type() = 0;

    virtual void writeInt8EnumType() = 0;
    virtual void writeInt16EnumType() = 0;
    virtual void writeInt32EnumType() = 0;
    virtual void writeInt64EnumType() = 0;

    virtual void writeUInt8EnumType() = 0;
    virtual void writeUInt16EnumType() = 0;
    virtual void writeUInt32EnumType() = 0;
    virtual void writeUInt64EnumType() = 0;

    virtual void writeFloatType() = 0;
    virtual void writeDoubleType() = 0;

    virtual void writeStringType() = 0;
    virtual void writeByteBufferType() = 0;
    virtual void writeVersionType() = 0;

    virtual void writeVectorType() = 0;

    virtual void beginWriteMapType() = 0;
    virtual void endWriteMapType() = 0;

    virtual void writeSerializableStructType(const CommonAPI::SerializableStruct& serializableStruct) = 0;
    virtual void writeVariantType(const CommonAPI::SerializableVariant& serializableVariant) = 0;
};

//##############################################################################################################

class DBusTypeStream: public TypeStream {
  public:
    DBusTypeStream(): signature_("") {

    }
    virtual ~DBusTypeStream() {}

    inline virtual void writeBoolType() {
        signature_.append("b");
    }

    inline virtual void writeInt8Type()  {
        signature_.append("y");
    }
    inline virtual void writeInt16Type()  {
        signature_.append("n");
    }
    inline virtual void writeInt32Type()  {
        signature_.append("i");
    }
    inline virtual void writeInt64Type()  {
        signature_.append("x");
    }

    inline virtual void writeUInt8Type()  {
        signature_.append("y");
    }
    inline virtual void writeUInt16Type()  {
        signature_.append("q");
    }
    inline virtual void writeUInt32Type()  {
        signature_.append("u");
    }
    inline virtual void writeUInt64Type()  {
        signature_.append("t");
    }

    inline virtual void writeInt8EnumType()  {
        signature_.append("y");
    }
    inline virtual void writeInt16EnumType()  {
        signature_.append("n");
    }
    inline virtual void writeInt32EnumType()  {
        signature_.append("i");
    }
    inline virtual void writeInt64EnumType()  {
        signature_.append("x");
    }

    inline virtual void writeUInt8EnumType()  {
        signature_.append("y");
    }
    inline virtual void writeUInt16EnumType()  {
        signature_.append("n");
    }
    inline virtual void writeUInt32EnumType()  {
        signature_.append("u");
    }
    inline virtual void writeUInt64EnumType()  {
        signature_.append("t");
    }

    inline virtual void writeFloatType()  {
        signature_.append("d");
    }
    inline virtual void writeDoubleType()  {
        signature_.append("d");
    }

    inline virtual void writeStringType()  {
        signature_.append("s");
    }
    inline virtual void writeByteBufferType()  {
        signature_.append("ay");
    }
    inline virtual void writeVersionType()  {
        signature_.append("(uu)");
    }

    inline virtual void beginWriteMapType()  {
        signature_.append("{");
    }
    inline virtual void endWriteMapType() {
        signature_.append("}");
    }

    inline virtual void writeSerializableStructType(const CommonAPI::SerializableStruct& serializableStruct)  {
        //TODO
    }
    inline virtual void writeVariantType(const CommonAPI::SerializableVariant& serializableVariant)  {
        //TODO
    }

    inline virtual void writeVectorType()  {
        signature_.append("a");
    }

  private:
    std::string signature_;
};

//##############################################################################################################

template <typename _VectorElementType>
class TypeStreamGenericVectorHelper {
 public:
    static void writeVectorType(TypeStream& typeStream, const std::vector<_VectorElementType>& vectorValue) {
        typeStream.writeVectorType();
        doWriteVectorType(typeStream, vectorValue);
    }

 private:
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<bool>& vectorValue) {
        typeStream.writeBoolType();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<int8_t>& vectorValue) {
        typeStream.writeInt8Type();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<int16_t>& vectorValue) {
        typeStream.writeInt16Type();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<int32_t>& vectorValue) {
        typeStream.writeInt32Type();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<int64_t>& vectorValue) {
        typeStream.writeInt64Type();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<uint8_t>& vectorValue) {
        typeStream.writeUInt8Type();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<uint16_t>& vectorValue) {
        typeStream.writeUInt16Type();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<uint32_t>& vectorValue) {
        typeStream.writeUInt32Type();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<uint64_t>& vectorValue) {
        typeStream.writeUInt64Type();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<float>& vectorValue) {
        typeStream.writeFloatType();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<double>& vectorValue) {
        typeStream.writeDoubleType();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<std::string>& vectorValue) {
        typeStream.writeStringType();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<CommonAPI::ByteBuffer>& vectorValue) {
        typeStream.writeByteBufferType();
    }
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<CommonAPI::Version>& vectorValue) {
        typeStream.writeVersionType();
    }

    template<typename _InnerVectorElementType>
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<std::vector<_InnerVectorElementType>>& vectorValue) {
        std::vector<_InnerVectorElementType> dummy;
        TypeStreamVectorHelper<_InnerVectorElementType>::writeVectorType(typeStream, dummy);
    }

    template<typename _InnerKeyType, typename _InnerValueType>
    static inline void doWriteVectorType(TypeStream& typeStream, const std::vector<std::unordered_map<_InnerKeyType, _InnerValueType>>& vectorValue) {
        typeStream.writeVectorType();
        typeStream.beginWriteMapType();
        //TODO
        typeStream.endWriteMapType();
    }
};

template <typename _VectorElementType, bool _IsSerializableStruct = false>
struct TypeStreamSerializableStructVectorHelper: public TypeStreamGenericVectorHelper<_VectorElementType> {
};

template <typename _VectorElementType>
struct TypeStreamSerializableStructVectorHelper<_VectorElementType, true> {
    static void writeVectorType(TypeStream& typeStream, const std::vector<_VectorElementType>& vectorValue) {
        typeStream.writeVectorType();
        //TODO: Write actual struct signature
    }
};

template <typename _VectorElementType>
struct TypeStreamVectorHelper: TypeStreamSerializableStructVectorHelper<_VectorElementType,
                                                                        std::is_base_of<CommonAPI::SerializableStruct, _VectorElementType>::value> {
};

//##############################################################################################################

template<typename _Type>
void writeType(TypeStream& typeStream, _Type& currentType);

template<>
inline void writeType<bool>(TypeStream& typeStream, bool& currentType) {
    return typeStream.writeBoolType();
}

template<>
inline void writeType<int8_t> (TypeStream& typeStream, int8_t& currentType) {
    typeStream.writeInt8Type();
}

template<>
inline void writeType<int16_t> (TypeStream& typeStream, int16_t& currentType) {
    typeStream.writeInt16Type();
}

template<>
inline void writeType<int32_t> (TypeStream& typeStream, int32_t& currentType) {
    typeStream.writeInt32Type();
}

template<>
inline void writeType<int64_t> (TypeStream& typeStream, int64_t& currentType) {
    typeStream.writeInt64Type();
}

template<>
inline void writeType<uint8_t> (TypeStream& typeStream, uint8_t& currentType) {
    typeStream.writeUInt8Type();
}

template<>
inline void writeType<uint16_t> (TypeStream& typeStream, uint16_t& currentType) {
    typeStream.writeUInt16Type();
}

template<>
inline void writeType<uint32_t> (TypeStream& typeStream, uint32_t& currentType) {
    typeStream.writeUInt32Type();
}

template<>
inline void writeType<uint64_t> (TypeStream& typeStream, uint64_t& currentType) {
    typeStream.writeUInt64Type();
}

template<>
inline void writeType<float> (TypeStream& typeStream, float& currentType) {
    typeStream.writeFloatType();
}

template<>
inline void writeType<double> (TypeStream& typeStream, double& currentType) {
    typeStream.writeDoubleType();
}

template<>
inline void writeType<std::string> (TypeStream& typeStream, std::string& currentType) {
    typeStream.writeStringType();
}

template<>
inline void writeType<CommonAPI::ByteBuffer> (TypeStream& typeStream, CommonAPI::ByteBuffer& currentType) {
    typeStream.writeByteBufferType();
}

template<>
inline void writeType<CommonAPI::Version> (TypeStream& typeStream, CommonAPI::Version& currentType) {
    typeStream.writeVersionType();
}

template<>
inline void writeType<CommonAPI::SerializableStruct> (TypeStream& typeStream, CommonAPI::SerializableStruct& currentType) {
    typeStream.writeSerializableStructType(currentType);
}

template<typename... _VariantTypes>
inline void writeType(TypeStream& typeStream, const CommonAPI::SerializableVariant& variant) {
    //TODO
}

template<typename _KeyType, typename _ValueType>
inline void writeType(TypeStream& typeStream, const std::unordered_map<_KeyType, _ValueType>& mapValue) {
    typeStream.beginWriteMapType();
    //TODO
    typeStream.endWriteMapType();
}

template<typename _VectorElementType>
inline void writeType(TypeStream& typeStream, const std::vector<_VectorElementType>& vectorValue) {
    TypeStreamVectorHelper<_VectorElementType>::writeVectorType(typeStream, vectorValue);
}

template<typename _Type>
struct TypeSearchVisitor {
public:
    TypeSearchVisitor(typename TypeStream& typeStream): typeStream_(typeStream) {
    }

    template<typename _Type>
    void operator()(const _Type& currentType) const {
        writeType<_Type>(typeStream_, currentType);
    }

private:
    TypeStream& typeStream_;
};

class TypeStreamTest: public ::testing::Test {
  protected:

    void SetUp() {
    }

    void TearDown() {
    }
};

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>Tests for variant serialisation<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <gtest/gtest.h>

#include <unordered_map>
#include <vector>

#include <CommonAPI/SerializableStruct.h>
#include <CommonAPI/SerializableVariant.h>
#include <CommonAPI/types.h>
#include <CommonAPI/ByteBuffer.h>

#include <type_traits>

class TypeStream {
  public:
    virtual ~TypeStream() {}

    virtual void writeBoolType() = 0;

    virtual void writeInt8Type() = 0;
    virtual void writeInt16Type() = 0;
    virtual void writeInt32Type() = 0;
    virtual void writeInt64Type() = 0;

    virtual void writeUInt8Type() = 0;
    virtual void writeUInt16Type() = 0;
    virtual void writeUInt32Type() = 0;
    virtual void writeUInt64Type() = 0;

    virtual void writeInt8EnumType() = 0;
    virtual void writeInt16EnumType() = 0;
    virtual void writeInt32EnumType() = 0;
    virtual void writeInt64EnumType() = 0;

    virtual void writeUInt8EnumType() = 0;
    virtual void writeUInt16EnumType() = 0;
    virtual void writeUInt32EnumType() = 0;
    virtual void writeUInt64EnumType() = 0;

    virtual void writeFloatType() = 0;
    virtual void writeDoubleType() = 0;

    virtual void writeStringType() = 0;
    virtual void writeByteBufferType() = 0;
    virtual void writeVersionType() = 0;

    virtual void writeVectorType() = 0;

    virtual void beginWriteMapType() = 0;
    virtual void endWriteMapType() = 0;

    virtual void beginWriteStructType() = 0;
    virtual void endWriteStructType() = 0;

    virtual void writeVariantType() = 0;

    virtual std::string retrieveSignature() = 0;
};

//##############################################################################################################

class DBusTypeStream: public TypeStream {
  public:
    DBusTypeStream(): signature_("") {

    }
    virtual ~DBusTypeStream() {}

    inline virtual void writeBoolType() {
        signature_.append("b");
    }

    inline virtual void writeInt8Type()  {
        signature_.append("y");
    }
    inline virtual void writeInt16Type()  {
        signature_.append("n");
    }
    inline virtual void writeInt32Type()  {
        signature_.append("i");
    }
    inline virtual void writeInt64Type()  {
        signature_.append("x");
    }

    inline virtual void writeUInt8Type()  {
        signature_.append("y");
    }
    inline virtual void writeUInt16Type()  {
        signature_.append("q");
    }
    inline virtual void writeUInt32Type()  {
        signature_.append("u");
    }
    inline virtual void writeUInt64Type()  {
        signature_.append("t");
    }

    inline virtual void writeInt8EnumType()  {
        signature_.append("y");
    }
    inline virtual void writeInt16EnumType()  {
        signature_.append("n");
    }
    inline virtual void writeInt32EnumType()  {
        signature_.append("i");
    }
    inline virtual void writeInt64EnumType()  {
        signature_.append("x");
    }

    inline virtual void writeUInt8EnumType()  {
        signature_.append("y");
    }
    inline virtual void writeUInt16EnumType()  {
        signature_.append("n");
    }
    inline virtual void writeUInt32EnumType()  {
        signature_.append("u");
    }
    inline virtual void writeUInt64EnumType()  {
        signature_.append("t");
    }

    inline virtual void writeFloatType()  {
        signature_.append("d");
    }
    inline virtual void writeDoubleType()  {
        signature_.append("d");
    }

    inline virtual void writeStringType()  {
        signature_.append("s");
    }
    inline virtual void writeByteBufferType()  {
        signature_.append("ay");
    }
    inline virtual void writeVersionType()  {
        signature_.append("(uu)");
    }

    inline virtual void beginWriteStructType()  {
        signature_.append("(");
    }
    inline virtual void endWriteStructType() {
        signature_.append(")");
    }

    inline virtual void beginWriteMapType()  {
        signature_.append("a{");
    }
    inline virtual void endWriteMapType() {
        signature_.append("}");
    }

    inline virtual void writeVectorType()  {
        signature_.append("a");
    }

    inline virtual void writeVariantType()  {
        signature_.append("v");
    }

    inline virtual std::string retrieveSignature() {
        return std::move(signature_);
    }

  private:
    std::string signature_;
};

//##############################################################################################################

template<typename _Type, bool _Check>
struct TypeWriter {
inline static void writeType(TypeStream& typeStream) {
//    if() {
        _Type::writeToTypeStream(typeStream);
//    } else if(std::is_base_of<CommonAPI::SerializableVariant, _Type>::value) {
//        typeStream.writeVariantType();
//    }
}
};

template<typename _Type>
struct TypeWriter<_Type, typename std::enable_if<std::is_base_of<CommonAPI::SerializableVariant, _Type>::value, _Type>::type> {
inline static void writeType(TypeStream& typeStream) {
    typeStream.writeVariantType();
}
};

template<>
struct TypeWriter<bool> {
inline static void writeType(TypeStream& typeStream) {
    typeStream.writeBoolType();
}
};

template<>
struct TypeWriter<int8_t> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeInt8Type();
}
};

template<>
struct TypeWriter<int16_t> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeInt16Type();
}
};

template<>
struct TypeWriter<int32_t> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeInt32Type();
}
};

template<>
struct TypeWriter<int64_t> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeInt64Type();
}
};

template<>
struct TypeWriter<uint8_t> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeUInt8Type();
}
};

template<>
struct TypeWriter<uint16_t> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeUInt16Type();
}
};

template<>
struct TypeWriter<uint32_t> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeUInt32Type();
}
};

template<>
struct TypeWriter<uint64_t> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeUInt64Type();
}
};

template<>
struct TypeWriter<float> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeFloatType();
}
};

template<>
struct TypeWriter<double> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeDoubleType();
}
};

template<>
struct TypeWriter<std::string> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeStringType();
}
};

template<>
struct TypeWriter<CommonAPI::ByteBuffer> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeByteBufferType();
}
};

template<>
struct TypeWriter<CommonAPI::Version> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeVersionType();
}
};

template<>
struct TypeWriter<CommonAPI::SerializableVariant> {
inline static void writeType (TypeStream& typeStream) {
    typeStream.writeVariantType();
}
};

template<typename _VectorElementType>
struct TypeWriter<std::vector<_VectorElementType>> {
inline static void writeType(TypeStream& typeStream) {
    typeStream.writeVectorType();
    TypeWriter<_VectorElementType>::writeType(typeStream);
}
};

template<typename _KeyType, typename _ValueType>
struct TypeWriter<std::unordered_map<_KeyType, _ValueType>> {
inline static void writeType(TypeStream& typeStream) {
    typeStream.beginWriteMapType();

    TypeWriter<_KeyType>::writeType(typeStream);
    TypeWriter<_ValueType>::writeType(typeStream);

    typeStream.endWriteMapType();
}
};

//##############################################################################################################

struct TypeSearchVisitor {
public:
    TypeSearchVisitor(TypeStream& typeStream): typeStream_(typeStream) {
    }

    template<typename _Type>
    void operator()(const _Type& currentType) const {
        TypeWriter<_Type>::writeType(typeStream_, currentType);
    }

private:
    TypeStream& typeStream_;
};

//##############################################################################################################

class TypeStreamTest: public ::testing::Test {
  protected:

    void SetUp() {
    }

    void TearDown() {
    }
};

TEST_F(TypeStreamTest, CreatesBoolSignature) {
    DBusTypeStream typeStream;
    TypeWriter<bool>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("b") == 0);
}

TEST_F(TypeStreamTest, CreatesInt8Signature) {
    DBusTypeStream typeStream;
    TypeWriter<int8_t>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("y") == 0);
}
TEST_F(TypeStreamTest, CreatesInt16Signature) {
    DBusTypeStream typeStream;
    TypeWriter<int16_t>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("n") == 0);
}
TEST_F(TypeStreamTest, CreatesInt32Signature) {
    DBusTypeStream typeStream;
    TypeWriter<int32_t>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("i") == 0);
}
TEST_F(TypeStreamTest, CreatesInt64Signature) {
    DBusTypeStream typeStream;
    TypeWriter<int64_t>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("x") == 0);
}

TEST_F(TypeStreamTest, CreatesUInt8Signature) {
    DBusTypeStream typeStream;
    TypeWriter<uint8_t>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("y") == 0);
}
TEST_F(TypeStreamTest, CreatesUInt16Signature) {
    DBusTypeStream typeStream;
    TypeWriter<uint16_t>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("q") == 0);
}
TEST_F(TypeStreamTest, CreatesUInt32Signature) {
    DBusTypeStream typeStream;
    TypeWriter<uint32_t>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("u") == 0);
}
TEST_F(TypeStreamTest, CreatesUInt64Signature) {
    DBusTypeStream typeStream;
    TypeWriter<uint64_t>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("t") == 0);
}

TEST_F(TypeStreamTest, CreatesFloatSignature) {
    DBusTypeStream typeStream;
    TypeWriter<float>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("d") == 0);
}
TEST_F(TypeStreamTest, CreatesDoubleSignature) {
    DBusTypeStream typeStream;
    TypeWriter<double>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("d") == 0);
}

TEST_F(TypeStreamTest, CreatesStringSignature) {
    DBusTypeStream typeStream;
    TypeWriter<std::string>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("s") == 0);
}

TEST_F(TypeStreamTest, CreatesByteBufferSignature) {
    DBusTypeStream typeStream;
    TypeWriter<CommonAPI::ByteBuffer>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("ay") == 0);
}
TEST_F(TypeStreamTest, CreatesVersionSignature) {
    DBusTypeStream typeStream;
    TypeWriter<CommonAPI::Version>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("(uu)") == 0);
}

TEST_F(TypeStreamTest, CreatesVectorOfStringsSignature) {
    DBusTypeStream typeStream;
    TypeWriter<std::vector<std::string> >::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("as") == 0);
}

TEST_F(TypeStreamTest, CreatesVectorOfVersionsSignature) {
    DBusTypeStream typeStream;
    TypeWriter<std::vector<CommonAPI::Version> >::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("a(uu)") == 0);
}

TEST_F(TypeStreamTest, CreatesMapOfUInt16ToStringSignature) {
    DBusTypeStream typeStream;
    TypeWriter<std::unordered_map<uint16_t, std::string>>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("a{qs}") == 0);
}

TEST_F(TypeStreamTest, CreatesBasicVariantSignature) {
    DBusTypeStream typeStream;
    TypeWriter<CommonAPI::SerializableVariant>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("v") == 0);
}

TEST_F(TypeStreamTest, CreatesDerivedVariantSignature) {
    DBusTypeStream typeStream;
    TypeWriter<CommonAPI::Variant<int, double, std::string>>::writeType(typeStream);
    std::string signature = typeStream.retrieveSignature();
    ASSERT_TRUE(signature.compare("v") == 0);
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/**
 * create_weightvector_from_SvmOutput main file. Reads a model.dat to
 * create a weight vector to be used with sopnet.
 */

#include <iostream>
#include <fstream>
#include <sstream>
#include <sopnet/segments/SegmentHash.h>
#include <util/exceptions.h>
#include <util/ProgramOptions.h>
#include <util/Logger.h>
#include <util/helpers.hpp>
#include <util/foreach.h>

util::ProgramOption optionModelFile(
		util::_long_name        = "model",
		util::_description_text = "A file that contains the svm model",
		util::_default_value    = "model.dat");

util::ProgramOption optionNormFile(
		util::_long_name        = "normalisation",
		util::_description_text = "A file that contains the feature normalisation information",
		util::_default_value    = "svm_normalisation.txt");

util::ProgramOption optionFeatureWeightsFile(
		util::_long_name        = "out",
		util::_description_text = "The file to store the weight vector in.",
		util::_default_value    = "feature_weights.dat");

int main(int optionc, char** optionv) {

	try {

		/********
		 * INIT *
		 ********/

		// init command line parser
		util::ProgramOptions::init(optionc, optionv);

		// init logger
		logger::LogManager::init();

		LOG_USER(logger::out) << "[main] starting..." << std::endl;

		// open feature weights file
		std::ofstream featureWeightsFile(optionFeatureWeightsFile.as<std::string>());

		// open models file
		std::ifstream modelFile(optionModelFile.as<std::string>());

		double threshold;
		std::vector<double> weights;
		int numWeights = 0;

		std::string line;
		// Read file, line by line
		while (std::getline(modelFile, line)) {

			// This is the line that indicates how many weights there are.
			if (line.find("highest feature index") != std::string::npos) {
				std::stringstream numWeightsStream(line);
				numWeightsStream >> numWeights;
				// The number of actual weights allways seems to be two less than indicated.
				numWeights = numWeights -2;
			}

			// Skip if not at threshold line
			if (line.find("threshold") == std::string::npos) {
				continue;
			}

			// get threshold
			std::stringstream thresholdStream(line);
			thresholdStream >> threshold;

			// The next line contains the weight vector
			std::getline(modelFile, line);
			std::stringstream weightLine(line);

			// The first element of that line is alpha times y
			double alphay;
			weightLine >> alphay;
			if (alphay != 1)
				LOG_USER(logger::out) << "Alpha times y was expected to be 1, but was not." << std::endl;

			std::string indexAndWeight;
			int vector_index = 0;
			while (weightLine >> indexAndWeight && indexAndWeight != "#"){
				//LOG_USER(logger::out) << "indexAndWeight: " << indexAndWeight << std::endl;
				// Get index and weight
				std::string::size_type n;
				n = indexAndWeight.find(":");
				std::string indexStr = indexAndWeight.substr(0,n);
				std::string weightStr = indexAndWeight.substr(n+1,indexAndWeight.size()-n);
				//LOG_USER(logger::out) << "indexStr: " << indexStr << std::endl;
				//LOG_USER(logger::out) << "weightStr: " << weightStr << std::endl;
				int index = std::stoi( indexStr );
				double weight = std::stod( weightStr );
				while (vector_index < index -1) {
					weights.push_back(0);
					vector_index++;
				}
				weights.push_back(weight);
				vector_index++;
			}

			while (vector_index < numWeights) {
				weights.push_back(0);
				vector_index++;
			}
		}

		// Open normalisation file
		std::ifstream normFile(optionNormFile.as<std::string>());

		std::vector<double> mins, maxs;

		std::string normLine;
		while (std::getline(normFile, normLine)) {

			double min, max;
			std::stringstream normStream(normLine);
			normStream >> min;
			normStream >> max;
			mins.push_back(min);
			maxs.push_back(max);
		}

		// Write out weights
		for (unsigned int i = 0; i < weights.size(); i++) {
			double unnormalised_weight = ( weights[i] * (mins[i]-maxs[i]) ) + mins[i];
			featureWeightsFile << unnormalised_weight << std::endl;
		}

	} catch (Exception& e) {

		handleException(e, std::cerr);
	}
}

<commit_msg>Corrected unnormalisation for svm output<commit_after>/**
 * create_weightvector_from_SvmOutput main file. Reads a model.dat to
 * create a weight vector to be used with sopnet.
 */

#include <iostream>
#include <fstream>
#include <sstream>
#include <sopnet/segments/SegmentHash.h>
#include <util/exceptions.h>
#include <util/ProgramOptions.h>
#include <util/Logger.h>
#include <util/helpers.hpp>
#include <util/foreach.h>

util::ProgramOption optionModelFile(
		util::_long_name        = "model",
		util::_description_text = "A file that contains the svm model",
		util::_default_value    = "model.dat");

util::ProgramOption optionNormFile(
		util::_long_name        = "normalisation",
		util::_description_text = "A file that contains the feature normalisation information",
		util::_default_value    = "svm_normalisation.txt");

util::ProgramOption optionFeatureWeightsFile(
		util::_long_name        = "out",
		util::_description_text = "The file to store the weight vector in.",
		util::_default_value    = "feature_weights.dat");

int main(int optionc, char** optionv) {

	try {

		/********
		 * INIT *
		 ********/

		// init command line parser
		util::ProgramOptions::init(optionc, optionv);

		// init logger
		logger::LogManager::init();

		LOG_USER(logger::out) << "[main] starting..." << std::endl;

		// open feature weights file
		std::ofstream featureWeightsFile(optionFeatureWeightsFile.as<std::string>());

		// open models file
		std::ifstream modelFile(optionModelFile.as<std::string>());

		double threshold;
		std::vector<double> weights;
		int numWeights = 0;

		std::string line;
		// Read file, line by line
		while (std::getline(modelFile, line)) {

			// This is the line that indicates how many weights there are.
			if (line.find("highest feature index") != std::string::npos) {
				std::stringstream numWeightsStream(line);
				numWeightsStream >> numWeights;
				// The number of actual weights allways seems to be two less than indicated.
				numWeights = numWeights -2;
			}

			// Skip if not at threshold line
			if (line.find("threshold") == std::string::npos) {
				continue;
			}

			// get threshold
			std::stringstream thresholdStream(line);
			thresholdStream >> threshold;

			// The next line contains the weight vector
			std::getline(modelFile, line);
			std::stringstream weightLine(line);

			// The first element of that line is alpha times y
			double alphay;
			weightLine >> alphay;
			if (alphay != 1)
				LOG_USER(logger::out) << "Alpha times y was expected to be 1, but was not." << std::endl;

			std::string indexAndWeight;
			int vector_index = 0;
			while (weightLine >> indexAndWeight && indexAndWeight != "#"){
				//LOG_USER(logger::out) << "indexAndWeight: " << indexAndWeight << std::endl;
				// Get index and weight
				std::string::size_type n;
				n = indexAndWeight.find(":");
				std::string indexStr = indexAndWeight.substr(0,n);
				std::string weightStr = indexAndWeight.substr(n+1,indexAndWeight.size()-n);
				//LOG_USER(logger::out) << "indexStr: " << indexStr << std::endl;
				//LOG_USER(logger::out) << "weightStr: " << weightStr << std::endl;
				int index = std::stoi( indexStr );
				double weight = std::stod( weightStr );
				while (vector_index < index -1) {
					weights.push_back(0);
					vector_index++;
				}
				weights.push_back(weight);
				vector_index++;
			}

			while (vector_index < numWeights) {
				weights.push_back(0);
				vector_index++;
			}
		}

		// Open normalisation file
		std::ifstream normFile(optionNormFile.as<std::string>());

		std::vector<double> mins, maxs;

		std::string normLine;
		while (std::getline(normFile, normLine)) {

			double min, max;
			std::stringstream normStream(normLine);
			normStream >> min;
			normStream >> max;
			mins.push_back(min);
			maxs.push_back(max);
		}

		// Threshold after unnormalising
		double threshold_subterm = 0;
		for (unsigned int i = 0; i < weights.size(); i++) {
			threshold_subterm += weights[i] / (maxs[i] - mins[i]) * maxs[i];
		}
		double threshold_unnorm = threshold - threshold_subterm;

		// Compute unnormalised weights
		std::vector<double> unnormalised_weights(weights.size(),0);
		for (unsigned int i = 0; i < weights.size(); i++) {
			unnormalised_weights[i] = weights[i] / (maxs[i] - mins[i]);
		}

		// Encode threshold in the last three weights
		for (unsigned int i = weights.size() - 3; i < weights.size(); i++) {
			unnormalised_weights[i] += threshold_unnorm;
		}

		// Write out weights
		for (unsigned int i = 0; i < weights.size(); i++) {
			featureWeightsFile << unnormalised_weights[i] << std::endl;
		}

	} catch (Exception& e) {

		handleException(e, std::cerr);
	}
}

<|endoftext|>


<commit_before>/**
  @file  sparse_adjacency_matrices.cc
  @brief Tool for calculating persistent homology of sparse adjacency matrices

  This is a tool shipped by 'Aleph - A Library for Exploring Persistent
  Homology'. It calculates the persistent homology of sparse adjacency
  matrices, i.e. data sets containing *multiple* graphs, using either
  a degree filtration or a filtration based on the *sum* of degrees.

  Original author: Bastian Rieck
*/

#include <aleph/geometry/RipsExpander.hh>

#include <aleph/math/KahanSummation.hh>

#include <aleph/persistentHomology/Calculation.hh>

#include <aleph/topology/FloydWarshall.hh>
#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

#include <aleph/topology/filtrations/Data.hh>
#include <aleph/topology/filtrations/Degree.hh>

#include <aleph/topology/io/GML.hh>
#include <aleph/topology/io/SparseAdjacencyMatrix.hh>

#include <aleph/utilities/Filesystem.hh>
#include <aleph/utilities/Format.hh>

#include <getopt.h>

#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

#include <cmath>

using DataType          = float;
using VertexType        = std::size_t;
using Simplex           = aleph::topology::Simplex<DataType, VertexType>;
using SimplicialComplex = aleph::topology::SimplicialComplex<Simplex>;

std::vector<DataType> closenessCentrality( const SimplicialComplex& K )
{
  auto M = aleph::topology::floydWarshall( K, 1 );
  auto n = M.numRows();

  std::vector<DataType> result;
  result.reserve( n );

  for( decltype(n) i = 0; i < n; i++ )
  {
    aleph::math::KahanSummation<DataType> sum = DataType();

    for( decltype(n) j = 0; j < n; j++ )
      if( std::isfinite( M(i,j) ) )
        sum += M(i,j);

    result.push_back( DataType(n) / sum );
  }

  return result;
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "closeness-centrality", no_argument, nullptr, 'c' },
    { "sum"                 , no_argument, nullptr, 's' },
    { nullptr               , 0          , nullptr,  0  }
  };

  bool calculateClosenessCentrality = false;
  bool useSumOfDegrees              = false;

  {
    int option = 0;
    while( ( option = getopt_long( argc, argv, "cs", commandLineOptions, nullptr ) ) != -1 )
    {
      switch( option )
      {
      case 'c':
        calculateClosenessCentrality = true;
        break;
      case 's':
        useSumOfDegrees = true;
        break;
      }
    }
  }

  if( ( argc - optind ) < 1 )
    return -1;

  std::string filename = argv[optind++];

  std::vector<SimplicialComplex> simplicialComplexes;
  std::vector<std::string> labels;

  aleph::topology::io::SparseAdjacencyMatrixReader reader;
  reader.setReadGraphLabels();

  std::cerr << "* Reading '" << filename << "'...";

  reader( filename, simplicialComplexes );

  std::cerr << "finished\n"
            << "* Read " << simplicialComplexes.size() << " simplicial complexes\n";

  // Calculate closeness centrality ------------------------------------

  if( calculateClosenessCentrality )
  {
    std::size_t index = 0;

    for( auto&& K : simplicialComplexes )
    {
      K.sort();
      auto cc     = closenessCentrality( K );
      auto output = "/tmp/"
                    + aleph::utilities::format( index, simplicialComplexes.size() )
                    + "_closeness_centrality.txt";

      std::ofstream out( output );
      for( auto&& value : cc )
        out << value << "\n";

      ++index;
    }
  }

  // Expand simplicial complexes ---------------------------------------

  aleph::geometry::RipsExpander<SimplicialComplex> expander;

  // TODO: make expansion configurable; does it make sense to expand the
  // complexes at all?

  // Calculate degrees -------------------------------------------------

  DataType maxDegree = 0;

  std::cerr << "* Calculating degree-based filtration...";

  for( auto&& K : simplicialComplexes )
  {
    std::vector<unsigned> degrees_;
    aleph::topology::filtrations::degrees( K, std::back_inserter( degrees_ ) );

    std::vector<DataType> degrees( degrees_.begin(), degrees_.end() );

    if( !degrees.empty() )
    {
      maxDegree
        = std::max( maxDegree,
                    *std::max_element( degrees.begin(), degrees.end() ) );
    }

    if( useSumOfDegrees )
      K = expander.assignData( K, degrees.begin(), degrees.end(), DataType(0), [] ( DataType a, DataType b ) { return a+b; } );
    else
      K = expander.assignMaximumData( K, degrees.begin(), degrees.end() );

    K.sort( aleph::topology::filtrations::Data<Simplex>() );
  }

  std::cerr << "finished\n"
            << "* Identified maximum degree as D=" << maxDegree << "\n";

  // Store graphs ------------------------------------------------------

  {
    aleph::topology::io::GMLWriter writer;

    for( std::size_t i = 0; i < simplicialComplexes.size(); i++ )
    {
      auto filename = "/tmp/"
                      + aleph::utilities::format( i, simplicialComplexes.size() )
                      + ".gml";

      std::cerr << "* Storing graph in '" << filename << "'...";

      writer( filename, simplicialComplexes[i] );

      std::cerr << "finished\n";
    }
  }

  // Calculate persistent homology -------------------------------------

  {
    std::size_t index = 0;

    for( auto&& K : simplicialComplexes )
    {
      bool dualize                    = true;
      bool includeAllUnpairedCreators = true;

      auto diagrams
        = aleph::calculatePersistenceDiagrams( K,
                                               dualize,
                                               includeAllUnpairedCreators );

      for( auto&& diagram : diagrams )
      {
        diagram.removeDiagonal();

        auto output = "/tmp/"
                      + aleph::utilities::format( index, simplicialComplexes.size() )
                      + "_d"
                      + std::to_string( diagram.dimension() )
                      + ".txt";

        std::ofstream out( output );

        for( auto&& point : diagram )
        {
          if( point.isUnpaired() )
            out << point.x() << "\t" << 2 * maxDegree << "\n";
          else
            out << point.x() << "\t" << point.y() << "\n";
        }
      }

      ++index;
    }
  }

  // Store labels ------------------------------------------------------

  {
    std::vector<std::string> labels;
    reader.graphLabels( std::back_inserter( labels ) );

    std::ofstream out( "/tmp/"
                      + aleph::utilities::basename( filename )
                      + ".txt" );

    for( auto&& label : labels )
      out << label << "\n";
  }
}
<commit_msg>Made degree factor configurable for sparse adjacency matrix computations<commit_after>/**
  @file  sparse_adjacency_matrices.cc
  @brief Tool for calculating persistent homology of sparse adjacency matrices

  This is a tool shipped by 'Aleph - A Library for Exploring Persistent
  Homology'. It calculates the persistent homology of sparse adjacency
  matrices, i.e. data sets containing *multiple* graphs, using either
  a degree filtration or a filtration based on the *sum* of degrees.

  Original author: Bastian Rieck
*/

#include <aleph/geometry/RipsExpander.hh>

#include <aleph/math/KahanSummation.hh>

#include <aleph/persistentHomology/Calculation.hh>

#include <aleph/topology/FloydWarshall.hh>
#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

#include <aleph/topology/filtrations/Data.hh>
#include <aleph/topology/filtrations/Degree.hh>

#include <aleph/topology/io/GML.hh>
#include <aleph/topology/io/SparseAdjacencyMatrix.hh>

#include <aleph/utilities/Filesystem.hh>
#include <aleph/utilities/Format.hh>
#include <aleph/utilities/String.hh>

#include <getopt.h>

#include <algorithm>
#include <fstream>
#include <iostream>
#include <limits>
#include <string>
#include <vector>

#include <cmath>

using DataType          = float;
using VertexType        = std::size_t;
using Simplex           = aleph::topology::Simplex<DataType, VertexType>;
using SimplicialComplex = aleph::topology::SimplicialComplex<Simplex>;

std::vector<DataType> closenessCentrality( const SimplicialComplex& K )
{
  auto M = aleph::topology::floydWarshall( K, 1 );
  auto n = M.numRows();

  std::vector<DataType> result;
  result.reserve( n );

  for( decltype(n) i = 0; i < n; i++ )
  {
    aleph::math::KahanSummation<DataType> sum = DataType();

    for( decltype(n) j = 0; j < n; j++ )
      if( std::isfinite( M(i,j) ) )
        sum += M(i,j);

    result.push_back( DataType(n) / sum );
  }

  return result;
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "infinity"            , required_argument, nullptr, 'f' },
    { "closeness-centrality", no_argument      , nullptr, 'c' },
    { "sum"                 , no_argument      , nullptr, 's' },
    { nullptr               , 0                , nullptr,  0  }
  };

  bool calculateClosenessCentrality = false;
  bool useSumOfDegrees              = false;
  DataType infinity                 = DataType(2);

  {
    int option = 0;
    while( ( option = getopt_long( argc, argv, "f:cs", commandLineOptions, nullptr ) ) != -1 )
    {
      switch( option )
      {
      case 'f':
        infinity = aleph::utilities::convert<DataType>( optarg );
        break;
      case 'c':
        calculateClosenessCentrality = true;
        break;
      case 's':
        useSumOfDegrees = true;
        break;
      }
    }
  }

  if( ( argc - optind ) < 1 )
    return -1;

  std::string filename = argv[optind++];

  std::vector<SimplicialComplex> simplicialComplexes;
  std::vector<std::string> labels;

  aleph::topology::io::SparseAdjacencyMatrixReader reader;
  reader.setReadGraphLabels();

  std::cerr << "* Reading '" << filename << "'...";

  reader( filename, simplicialComplexes );

  std::cerr << "finished\n"
            << "* Read " << simplicialComplexes.size() << " simplicial complexes\n";

  // Calculate closeness centrality ------------------------------------

  if( calculateClosenessCentrality )
  {
    std::size_t index = 0;

    for( auto&& K : simplicialComplexes )
    {
      K.sort();
      auto cc     = closenessCentrality( K );
      auto output = "/tmp/"
                    + aleph::utilities::format( index, simplicialComplexes.size() )
                    + "_closeness_centrality.txt";

      std::ofstream out( output );
      for( auto&& value : cc )
        out << value << "\n";

      ++index;
    }
  }

  // Expand simplicial complexes ---------------------------------------

  aleph::geometry::RipsExpander<SimplicialComplex> expander;

  // TODO: make expansion configurable; does it make sense to expand the
  // complexes at all?

  // Calculate degrees -------------------------------------------------

  DataType maxDegree = 0;

  std::cerr << "* Calculating degree-based filtration...";

  for( auto&& K : simplicialComplexes )
  {
    std::vector<unsigned> degrees_;
    aleph::topology::filtrations::degrees( K, std::back_inserter( degrees_ ) );

    std::vector<DataType> degrees( degrees_.begin(), degrees_.end() );

    if( !degrees.empty() )
    {
      maxDegree
        = std::max( maxDegree,
                    *std::max_element( degrees.begin(), degrees.end() ) );
    }

    if( useSumOfDegrees )
      K = expander.assignData( K, degrees.begin(), degrees.end(), DataType(0), [] ( DataType a, DataType b ) { return a+b; } );
    else
      K = expander.assignMaximumData( K, degrees.begin(), degrees.end() );

    K.sort( aleph::topology::filtrations::Data<Simplex>() );
  }

  std::cerr << "finished\n"
            << "* Identified maximum degree as D=" << maxDegree << "\n";

  // Store graphs ------------------------------------------------------

  {
    aleph::topology::io::GMLWriter writer;

    for( std::size_t i = 0; i < simplicialComplexes.size(); i++ )
    {
      auto filename = "/tmp/"
                      + aleph::utilities::format( i, simplicialComplexes.size() )
                      + ".gml";

      std::cerr << "* Storing graph in '" << filename << "'...";

      writer( filename, simplicialComplexes[i] );

      std::cerr << "finished\n";
    }
  }

  // Calculate persistent homology -------------------------------------

  {
    std::size_t index = 0;

    for( auto&& K : simplicialComplexes )
    {
      bool dualize                    = true;
      bool includeAllUnpairedCreators = true;

      auto diagrams
        = aleph::calculatePersistenceDiagrams( K,
                                               dualize,
                                               includeAllUnpairedCreators );

      for( auto&& diagram : diagrams )
      {
        diagram.removeDiagonal();

        auto output = "/tmp/"
                      + aleph::utilities::format( index, simplicialComplexes.size() )
                      + "_d"
                      + std::to_string( diagram.dimension() )
                      + ".txt";

        std::ofstream out( output );

        for( auto&& point : diagram )
        {
          if( point.isUnpaired() )
            out << point.x() << "\t" << infinity * maxDegree << "\n";
          else
            out << point.x() << "\t" << point.y() << "\n";
        }
      }

      ++index;
    }
  }

  // Store labels ------------------------------------------------------

  {
    std::vector<std::string> labels;
    reader.graphLabels( std::back_inserter( labels ) );

    std::ofstream out( "/tmp/"
                      + aleph::utilities::basename( filename )
                      + ".txt" );

    for( auto&& label : labels )
      out << label << "\n";
  }
}
<|endoftext|>


<commit_before>/**
  @file  sparse_adjacency_matrices.cc
  @brief Tool for calculating persistent homology of sparse adjacency matrices

  This is a tool shipped by 'Aleph - A Library for Exploring Persistent
  Homology'. It calculates the persistent homology of sparse adjacency
  matrices, i.e. data sets containing *multiple* graphs, using either
  a degree filtration or a filtration based on the *sum* of degrees.

  Original author: Bastian Rieck
*/

#include <aleph/geometry/RipsExpander.hh>

#include <aleph/math/KahanSummation.hh>

#include <aleph/persistentHomology/Calculation.hh>

#include <aleph/topology/FloydWarshall.hh>
#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

#include <aleph/topology/filtrations/Data.hh>
#include <aleph/topology/filtrations/Degree.hh>

#include <aleph/topology/io/GML.hh>
#include <aleph/topology/io/SparseAdjacencyMatrix.hh>

#include <aleph/utilities/Format.hh>
#include <aleph/utilities/String.hh>

#include <getopt.h>

#include <algorithm>
#include <fstream>
#include <iostream>
#include <limits>
#include <stdexcept>
#include <string>
#include <vector>

#include <cmath>

using DataType          = float;
using VertexType        = std::size_t;
using Simplex           = aleph::topology::Simplex<DataType, VertexType>;
using SimplicialComplex = aleph::topology::SimplicialComplex<Simplex>;

std::vector<DataType> closenessCentrality( const SimplicialComplex& K )
{
  auto M = aleph::topology::floydWarshall( K, 1 );
  auto n = M.numRows();

  std::vector<DataType> result;
  result.reserve( n );

  for( decltype(n) i = 0; i < n; i++ )
  {
    aleph::math::KahanSummation<DataType> sum = DataType();

    for( decltype(n) j = 0; j < n; j++ )
      if( std::isfinite( M(i,j) ) )
        sum += M(i,j);

    result.push_back( DataType(n) / sum );
  }

  return result;
}

void usage()
{
  std::cerr << "Usage: sparse_adjacency_matrices FILE\n"
            << "\n"
            << "Loads a set of sparse adjacency matrices from FILE and performs\n"
            << "several operations with them. By default, the tool will extract\n"
            << "all graphs from the file, use a degree-based filtration, and do\n"
            << "a conversion to GML. Furthermore, persistence diagrams of every\n"
            << "graph will be calculated.\n"
            << "\n"
            << "Optional arguments:\n"
            << "\n"
            << " --dimension D: Expand simplicial complexes up to dimension D\n"
            << " --infinity I:  Use factor I for unpaired points in a diagram\n"
            << "\n"
            << "Flags:\n"
            << "\n"
            << " --closeness-centrality: Calculates closeness centrality filtration\n"
            << " --graphs:               Stores converted graphs in GML format\n"
            << " --sum:                  Calculates degree sum filtration\n"
            << "\n"
            << "\n";
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "dimension"           , required_argument, nullptr, 'd' },
    { "infinity"            , required_argument, nullptr, 'f' },
    { "output"              , required_argument, nullptr, 'o' },
    { "attributes"          , no_argument      , nullptr, 'a' },
    { "closeness-centrality", no_argument      , nullptr, 'c' },
    { "graphs"              , no_argument      , nullptr, 'g' },
    { "sum"                 , no_argument      , nullptr, 's' },
    { "node-labels"         , no_argument      , nullptr, 'n' },
    { nullptr               , 0                , nullptr,  0  }
  };

  unsigned dimension                = 0;
  bool calculateClosenessCentrality = false;
  bool storeGraphs                  = false;
  bool useSumOfDegrees              = false;
  bool readNodeAttributes           = false;
  bool readNodeLabels               = false;
  DataType infinity                 = DataType(2);
  std::string output                = "/tmp";

  {
    int option = 0;
    while( ( option = getopt_long( argc, argv, "d:f:o:acgns", commandLineOptions, nullptr ) ) != -1 )
    {
      switch( option )
      {
      case 'd':
        dimension = static_cast<unsigned>( std::stoul( optarg  ) );
        break;
      case 'f':
        infinity = aleph::utilities::convert<DataType>( optarg );
        break;
      case 'o':
        output = optarg;
        break;
      case 'c':
        calculateClosenessCentrality = true;
        break;
      case 'a':
        readNodeAttributes = true;
        break;
      case 'g':
        storeGraphs = true;
        break;
      case 'n':
        readNodeLabels = true;
        break;
      case 's':
        useSumOfDegrees = true;
        break;
      default:
        throw std::runtime_error( "Unknown command-line arugment" );
      }
    }
  }

  if( ( argc - optind ) < 1 )
  {
    usage();
    return -1;
  }

  // Check that the output parameter at least *looks* like a directory
  if( output.back() != '/' )
    output.push_back( '/' );

  std::string filename = argv[optind++];

  std::vector<SimplicialComplex> simplicialComplexes;
  std::vector<std::string> labels;

  aleph::topology::io::SparseAdjacencyMatrixReader reader;
  reader.setReadGraphLabels();

  if( readNodeAttributes )
  {
    reader.setReadNodeAttributes();
    reader.setNodeAttributeIndex( 0 );
  }

  if( readNodeLabels )
    reader.setReadNodeLabels();

  std::vector<std::string> nodeLabels;

  std::cerr << "* Reading '" << filename << "'...";

  reader( filename, simplicialComplexes );

  if( readNodeLabels )
  {
    // Get node labels for further processing because we must not drop
    // this valuable information.
    reader.nodeLabels(
      std::back_inserter( nodeLabels )
    );
  }

  std::cerr << "finished\n"
            << "* Read " << simplicialComplexes.size() << " simplicial complexes\n";

  // Calculate closeness centrality ------------------------------------

  if( calculateClosenessCentrality )
  {
    std::size_t index = 0;

    for( auto&& K : simplicialComplexes )
    {
      K.sort();
      auto cc         = closenessCentrality( K );
      auto outputPath = output
                      + aleph::utilities::format( index, simplicialComplexes.size() )
                      + "_closeness_centrality.txt";

      std::cerr << "* Storing closeness centrality values in '" << outputPath << "'\n";

      std::ofstream out( outputPath );
      for( auto&& value : cc )
        out << value << "\n";

      ++index;
    }
  }

  // Expand simplicial complexes ---------------------------------------

  aleph::geometry::RipsExpander<SimplicialComplex> expander;

  if( dimension != 0 )
  {
    std::cerr << "* Expanding simplicial complexes to dimension " << dimension << "...";

    for( auto&& K : simplicialComplexes )
      expander( K, dimension );

    std::cerr << "finished\n";
  }

  // Calculate degrees -------------------------------------------------

  DataType maxDegree = 0;

  std::cerr << "* Calculating degree-based filtration...";

  for( auto&& K : simplicialComplexes )
  {
    std::vector<unsigned> degrees_;
    aleph::topology::filtrations::degrees( K, std::back_inserter( degrees_ ) );

    std::vector<DataType> degrees( degrees_.begin(), degrees_.end() );

    if( !degrees.empty() )
    {
      maxDegree
        = std::max( maxDegree,
                    *std::max_element( degrees.begin(), degrees.end() ) );
    }

    if( useSumOfDegrees )
      K = expander.assignData( K, degrees.begin(), degrees.end(), DataType(0), [] ( DataType a, DataType b ) { return a+b; } );
    else
      K = expander.assignMaximumData( K, degrees.begin(), degrees.end() );

    K.sort( aleph::topology::filtrations::Data<Simplex>() );
  }

  std::cerr << "finished\n"
            << "* Identified maximum degree as D=" << maxDegree << "\n";

  // Store graphs ------------------------------------------------------

  if( storeGraphs )
  {
    aleph::topology::io::GMLWriter writer;
    writer.setNodeLabels( nodeLabels.begin(), nodeLabels.end() );

    if( readNodeAttributes )
      writer.writeSimplexDataForVertices();

    for( std::size_t i = 0; i < simplicialComplexes.size(); i++ )
    {
      auto filename = output
                      + aleph::utilities::format( i, simplicialComplexes.size() )
                      + ".gml";

      std::cerr << "* Storing graph in '" << filename << "'...";

      writer( filename, simplicialComplexes[i] );

      std::cerr << "finished\n";
    }
  }

  // Calculate persistent homology -------------------------------------

  {
    std::size_t index = 0;

    for( auto&& K : simplicialComplexes )
    {
      bool dualize                    = true;
      bool includeAllUnpairedCreators = true;

      auto diagrams
        = aleph::calculatePersistenceDiagrams( K,
                                               dualize,
                                               includeAllUnpairedCreators );

      for( auto&& diagram : diagrams )
      {
        diagram.removeDiagonal();

        auto outputPath = output
                        + aleph::utilities::format( index, simplicialComplexes.size() )
                        + "_d"
                        + std::to_string( diagram.dimension() )
                        + ".txt";

        std::ofstream out( outputPath );

        for( auto&& point : diagram )
        {
          if( point.isUnpaired() )
            out << point.x() << "\t" << infinity * maxDegree << "\n";
          else
            out << point.x() << "\t" << point.y() << "\n";
        }
      }

      ++index;
    }
  }

  // Store labels ------------------------------------------------------

  {
    std::vector<std::string> labels;
    reader.graphLabels( std::back_inserter( labels ) );

    auto outputPath = output
                    + "Labels.txt";

    std::cerr << "* Storing labels in '" << outputPath << "'\n";

    std::ofstream out( outputPath );
    for( auto&& label : labels )
      out << label << "\n";
  }
}
<commit_msg>Added superlevel set filtration<commit_after>/**
  @file  sparse_adjacency_matrices.cc
  @brief Tool for calculating persistent homology of sparse adjacency matrices

  This is a tool shipped by 'Aleph - A Library for Exploring Persistent
  Homology'. It calculates the persistent homology of sparse adjacency
  matrices, i.e. data sets containing *multiple* graphs, using either
  a degree filtration or a filtration based on the *sum* of degrees.

  Original author: Bastian Rieck
*/

#include <aleph/geometry/RipsExpander.hh>

#include <aleph/math/KahanSummation.hh>

#include <aleph/persistentHomology/Calculation.hh>

#include <aleph/topology/FloydWarshall.hh>
#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

#include <aleph/topology/filtrations/Data.hh>
#include <aleph/topology/filtrations/Degree.hh>

#include <aleph/topology/io/GML.hh>
#include <aleph/topology/io/SparseAdjacencyMatrix.hh>

#include <aleph/utilities/Format.hh>
#include <aleph/utilities/String.hh>

#include <getopt.h>

#include <algorithm>
#include <fstream>
#include <iostream>
#include <limits>
#include <stdexcept>
#include <string>
#include <vector>

#include <cmath>

using DataType          = float;
using VertexType        = std::size_t;
using Simplex           = aleph::topology::Simplex<DataType, VertexType>;
using SimplicialComplex = aleph::topology::SimplicialComplex<Simplex>;

std::vector<DataType> closenessCentrality( const SimplicialComplex& K )
{
  auto M = aleph::topology::floydWarshall( K, 1 );
  auto n = M.numRows();

  std::vector<DataType> result;
  result.reserve( n );

  for( decltype(n) i = 0; i < n; i++ )
  {
    aleph::math::KahanSummation<DataType> sum = DataType();

    for( decltype(n) j = 0; j < n; j++ )
      if( std::isfinite( M(i,j) ) )
        sum += M(i,j);

    result.push_back( DataType(n) / sum );
  }

  return result;
}

void usage()
{
  std::cerr << "Usage: sparse_adjacency_matrices FILE\n"
            << "\n"
            << "Loads a set of sparse adjacency matrices from FILE and performs\n"
            << "several operations with them. By default, the tool will extract\n"
            << "all graphs from the file, use a degree-based filtration, and do\n"
            << "a conversion to GML. Furthermore, persistence diagrams of every\n"
            << "graph will be calculated.\n"
            << "\n"
            << "Optional arguments:\n"
            << "\n"
            << " --dimension D: Expand simplicial complexes up to dimension D\n"
            << " --infinity I:  Use factor I for unpaired points in a diagram\n"
            << "\n"
            << "Flags:\n"
            << "\n"
            << " --closeness-centrality: Calculates closeness centrality filtration\n"
            << " --graphs:               Stores converted graphs in GML format\n"
            << " --sum:                  Calculates degree sum filtration\n"
            << "\n"
            << "\n";
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "dimension"           , required_argument, nullptr, 'd' },
    { "infinity"            , required_argument, nullptr, 'f' },
    { "output"              , required_argument, nullptr, 'o' },
    { "attributes"          , no_argument      , nullptr, 'a' },
    { "closeness-centrality", no_argument      , nullptr, 'c' },
    { "graphs"              , no_argument      , nullptr, 'g' },
    { "sum"                 , no_argument      , nullptr, 's' },
    { "superlevel"          , no_argument      , nullptr, 'S' },
    { "node-labels"         , no_argument      , nullptr, 'n' },
    { nullptr               , 0                , nullptr,  0  }
  };

  unsigned dimension                = 0;
  bool calculateClosenessCentrality = false;
  bool storeGraphs                  = false;
  bool useSumOfDegrees              = false;
  bool readNodeAttributes           = false;
  bool readNodeLabels               = false;
  bool useSuperlevelSets            = false;
  DataType infinity                 = DataType(2);
  std::string output                = "/tmp";

  {
    int option = 0;
    while( ( option = getopt_long( argc, argv, "d:f:o:acgnsS", commandLineOptions, nullptr ) ) != -1 )
    {
      switch( option )
      {
      case 'd':
        dimension = static_cast<unsigned>( std::stoul( optarg  ) );
        break;
      case 'f':
        infinity = aleph::utilities::convert<DataType>( optarg );
        break;
      case 'o':
        output = optarg;
        break;
      case 'c':
        calculateClosenessCentrality = true;
        break;
      case 'a':
        readNodeAttributes = true;
        break;
      case 'g':
        storeGraphs = true;
        break;
      case 'n':
        readNodeLabels = true;
        break;
      case 's':
        useSumOfDegrees = true;
        break;
      case 'S':
        useSuperlevelSets = true;
        break;
      default:
        throw std::runtime_error( "Unknown command-line arugment" );
      }
    }
  }

  if( ( argc - optind ) < 1 )
  {
    usage();
    return -1;
  }

  // Check that the output parameter at least *looks* like a directory
  if( output.back() != '/' )
    output.push_back( '/' );

  std::string filename = argv[optind++];

  std::vector<SimplicialComplex> simplicialComplexes;
  std::vector<std::string> labels;

  aleph::topology::io::SparseAdjacencyMatrixReader reader;
  reader.setReadGraphLabels();

  if( readNodeAttributes )
  {
    reader.setReadNodeAttributes();
    reader.setNodeAttributeIndex( 0 );
  }

  if( readNodeLabels )
    reader.setReadNodeLabels();

  std::vector<std::string> nodeLabels;

  std::cerr << "* Reading '" << filename << "'...";

  reader( filename, simplicialComplexes );

  if( readNodeLabels )
  {
    // Get node labels for further processing because we must not drop
    // this valuable information.
    reader.nodeLabels(
      std::back_inserter( nodeLabels )
    );
  }

  std::cerr << "finished\n"
            << "* Read " << simplicialComplexes.size() << " simplicial complexes\n";

  // Calculate closeness centrality ------------------------------------

  if( calculateClosenessCentrality )
  {
    std::size_t index = 0;

    for( auto&& K : simplicialComplexes )
    {
      K.sort();
      auto cc         = closenessCentrality( K );
      auto outputPath = output
                      + aleph::utilities::format( index, simplicialComplexes.size() )
                      + "_closeness_centrality.txt";

      std::cerr << "* Storing closeness centrality values in '" << outputPath << "'\n";

      std::ofstream out( outputPath );
      for( auto&& value : cc )
        out << value << "\n";

      ++index;
    }
  }

  // Expand simplicial complexes ---------------------------------------

  aleph::geometry::RipsExpander<SimplicialComplex> expander;

  if( dimension != 0 )
  {
    std::cerr << "* Expanding simplicial complexes to dimension " << dimension << "...";

    for( auto&& K : simplicialComplexes )
      expander( K, dimension );

    std::cerr << "finished\n";
  }

  // Calculate degrees -------------------------------------------------

  DataType maxDegree = 0;

  std::cerr << "* Calculating degree-based filtration...";

  for( auto&& K : simplicialComplexes )
  {
    std::vector<unsigned> degrees_;
    aleph::topology::filtrations::degrees( K, std::back_inserter( degrees_ ) );

    std::vector<DataType> degrees( degrees_.begin(), degrees_.end() );

    if( !degrees.empty() )
    {
      maxDegree
        = std::max( maxDegree,
                    *std::max_element( degrees.begin(), degrees.end() ) );
    }

    if( useSumOfDegrees )
      K = expander.assignData( K, degrees.begin(), degrees.end(), DataType(0), [] ( DataType a, DataType b ) { return a+b; } );
    else
    {
      if( useSuperlevelSets )
      {
        auto init    = std::numeric_limits<DataType>::max();
        auto functor = [] ( const DataType& a, const DataType& b )
        {
          return std::min( a, b );
        };

        K = expander.assignData( K, degrees.begin(), degrees.end(), init, functor );
      }
      else
        K = expander.assignMaximumData( K, degrees.begin(), degrees.end() );
    }

    K.sort( aleph::topology::filtrations::Data<Simplex>() );
  }

  std::cerr << "finished\n"
            << "* Identified maximum degree as D=" << maxDegree << "\n";

  // Store graphs ------------------------------------------------------

  if( storeGraphs )
  {
    aleph::topology::io::GMLWriter writer;
    writer.setNodeLabels( nodeLabels.begin(), nodeLabels.end() );

    if( readNodeAttributes )
      writer.writeSimplexDataForVertices();

    for( std::size_t i = 0; i < simplicialComplexes.size(); i++ )
    {
      auto filename = output
                      + aleph::utilities::format( i, simplicialComplexes.size() )
                      + ".gml";

      std::cerr << "* Storing graph in '" << filename << "'...";

      writer( filename, simplicialComplexes[i] );

      std::cerr << "finished\n";
    }
  }

  // Calculate persistent homology -------------------------------------

  {
    std::size_t index = 0;

    for( auto&& K : simplicialComplexes )
    {
      bool dualize                    = true;
      bool includeAllUnpairedCreators = true;

      auto diagrams
        = aleph::calculatePersistenceDiagrams( K,
                                               dualize,
                                               includeAllUnpairedCreators );

      for( auto&& diagram : diagrams )
      {
        diagram.removeDiagonal();

        auto outputPath = output
                        + aleph::utilities::format( index, simplicialComplexes.size() )
                        + "_d"
                        + std::to_string( diagram.dimension() )
                        + ".txt";

        std::ofstream out( outputPath );

        for( auto&& point : diagram )
        {
          if( point.isUnpaired() )
            out << point.x() << "\t" << infinity * maxDegree << "\n";
          else
            out << point.x() << "\t" << point.y() << "\n";
        }
      }

      ++index;
    }
  }

  // Store labels ------------------------------------------------------

  {
    std::vector<std::string> labels;
    reader.graphLabels( std::back_inserter( labels ) );

    auto outputPath = output
                    + "Labels.txt";

    std::cerr << "* Storing labels in '" << outputPath << "'\n";

    std::ofstream out( outputPath );
    for( auto&& label : labels )
      out << label << "\n";
  }
}
<|endoftext|>


<commit_before>// DepthOp.cpp
/*
 * Copyright (c) 2009, Dan Heeks
 * This program is released under the BSD license. See the file COPYING for
 * details.
 */

#include "stdafx.h"
#include "DepthOp.h"
#include "CNCConfig.h"
#include "ProgramCanvas.h"
#include "Program.h"
#include "interface/PropertyInt.h"
#include "interface/PropertyDouble.h"
#include "interface/PropertyLength.h"
#include "tinyxml/tinyxml.h"
#include "interface/Tool.h"

CDepthOpParams::CDepthOpParams()
{
	m_tool_number = 0;
	m_tool_diameter = 0.0;
	m_clearance_height = 0.0;
	m_start_depth = 0.0;
	m_step_down = 0.0;
	m_final_depth = 0.0;
	m_rapid_down_to_height = 0.0;
	m_horizontal_feed_rate = 0.0;
	m_vertical_feed_rate = 0.0;
	m_spindle_speed = 0.0;
}

void CDepthOpParams::set_initial_values()
{
	CNCConfig config;
    config.Read(_T("DepthFixtureOffset"), &m_workplane,1);
	config.Read(_T("DepthOpToolNumber"), &m_tool_number, 1);
	config.Read(_T("DepthOpToolDiameter"), &m_tool_diameter, 3.0);
	config.Read(_T("DepthOpClearanceHeight"), &m_clearance_height, 5.0);
	config.Read(_T("DepthOpStartDepth"), &m_start_depth, 0.0);
	config.Read(_T("DepthOpStepDown"), &m_step_down, 1.0);
	config.Read(_T("DepthOpFinalDepth"), &m_final_depth, -1.0);
	config.Read(_T("DepthOpRapidDown"), &m_rapid_down_to_height, 2.0);
	config.Read(_T("DepthOpHorizFeed"), &m_horizontal_feed_rate, 100.0);
	config.Read(_T("DepthOpVertFeed"), &m_vertical_feed_rate, 100.0);
	config.Read(_T("DepthOpSpindleSpeed"), &m_spindle_speed, 7000);
}

void CDepthOpParams::write_values_to_config()
{
	CNCConfig config;
	config.Write(_T("DepthFixtureOffset"), m_workplane);
	config.Write(_T("DepthOpToolNumber"), m_tool_number);
	config.Write(_T("DepthOpToolDiameter"), m_tool_diameter);
	config.Write(_T("DepthOpClearanceHeight"), m_clearance_height);
	config.Write(_T("DepthOpStartDepth"), m_start_depth);
	config.Write(_T("DepthOpStepDown"), m_step_down);
	config.Write(_T("DepthOpFinalDepth"), m_final_depth);
	config.Write(_T("DepthOpRapidDown"), m_rapid_down_to_height);
	config.Write(_T("DepthOpHorizFeed"), m_horizontal_feed_rate);
	config.Write(_T("DepthOpVertFeed"), m_vertical_feed_rate);
	config.Write(_T("DepthOpSpindleSpeed"), m_spindle_speed);
}

static void on_set_workplane(int value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_workplane = value;}
static void on_set_tool_number(int value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_tool_number = value;}
static void on_set_tool_diameter(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_tool_diameter = value;}
static void on_set_clearance_height(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_clearance_height = value;}
static void on_set_step_down(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_step_down = value;}
static void on_set_start_depth(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_start_depth = value;}
static void on_set_final_depth(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_final_depth = value;}
static void on_set_rapid_down_to_height(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_rapid_down_to_height = value;}
static void on_set_horizontal_feed_rate(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_horizontal_feed_rate = value;}
static void on_set_vertical_feed_rate(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_vertical_feed_rate = value;}
static void on_set_spindle_speed(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_spindle_speed = value;}

void CDepthOpParams::GetProperties(CDepthOp* parent, std::list<Property *> *list)
{
	list->push_back(new PropertyInt(_("fixture offset"), m_workplane, parent, on_set_workplane));
	list->push_back(new PropertyInt(_("tool number"), m_tool_number, parent, on_set_tool_number));
	list->push_back(new PropertyLength(_("tool diameter"), m_tool_diameter, parent, on_set_tool_diameter));
	list->push_back(new PropertyLength(_("clearance height"), m_clearance_height, parent, on_set_clearance_height));
	list->push_back(new PropertyLength(_("step down"), m_step_down, parent, on_set_step_down));
	list->push_back(new PropertyLength(_("start depth"), m_start_depth, parent, on_set_start_depth));
	list->push_back(new PropertyLength(_("final depth"), m_final_depth, parent, on_set_final_depth));
	list->push_back(new PropertyLength(_("rapid down to height"), m_rapid_down_to_height, parent, on_set_rapid_down_to_height));
	list->push_back(new PropertyDouble(_("horizontal feed rate"), m_horizontal_feed_rate, parent, on_set_horizontal_feed_rate));
	list->push_back(new PropertyDouble(_("vertical feed rate"), m_vertical_feed_rate, parent, on_set_vertical_feed_rate));
	list->push_back(new PropertyDouble(_("spindle speed"), m_spindle_speed, parent, on_set_spindle_speed));
}

void CDepthOpParams::WriteXMLAttributes(TiXmlNode* pElem)
{
	TiXmlElement * element = new TiXmlElement( "depthop" );
	pElem->LinkEndChild( element );
	element->SetAttribute("fixture offset", m_workplane);
	element->SetAttribute("tooln", m_tool_number);
	element->SetDoubleAttribute("toold", m_tool_diameter);
	element->SetDoubleAttribute("clear", m_clearance_height);
	element->SetDoubleAttribute("down", m_step_down);
	element->SetDoubleAttribute("startdepth", m_start_depth);
	element->SetDoubleAttribute("depth", m_final_depth);
	element->SetDoubleAttribute("r", m_rapid_down_to_height);
	element->SetDoubleAttribute("hfeed", m_horizontal_feed_rate);
	element->SetDoubleAttribute("vfeed", m_vertical_feed_rate);
	element->SetDoubleAttribute("spin", m_spindle_speed);
}

void CDepthOpParams::ReadFromXMLElement(TiXmlElement* pElem)
{
	TiXmlElement* depthop = TiXmlHandle(pElem).FirstChildElement("depthop").Element();
	if(depthop)
	{

		depthop->Attribute("fixture offset", &m_workplane);
		depthop->Attribute("tooln", &m_tool_number);
		depthop->Attribute("toold", &m_tool_diameter);
		depthop->Attribute("clear", &m_clearance_height);
		depthop->Attribute("down", &m_step_down);
		depthop->Attribute("startdepth", &m_start_depth);
		depthop->Attribute("depth", &m_final_depth);
		depthop->Attribute("r", &m_rapid_down_to_height);
		depthop->Attribute("hfeed", &m_horizontal_feed_rate);
		depthop->Attribute("vfeed", &m_vertical_feed_rate);
		depthop->Attribute("spin", &m_spindle_speed);
	}
}

void CDepthOp::WriteBaseXML(TiXmlElement *element)
{
	m_depth_op_params.WriteXMLAttributes(element);
	COp::WriteBaseXML(element);
}

void CDepthOp::ReadBaseXML(TiXmlElement* element)
{
	m_depth_op_params.ReadFromXMLElement(element);
	COp::ReadBaseXML(element);
}

void CDepthOp::GetProperties(std::list<Property *> *list)
{
	m_depth_op_params.GetProperties(this, list);
	COp::GetProperties(list);
}

void CDepthOp::AppendTextToProgram()
{
	COp::AppendTextToProgram();

	theApp.m_program_canvas->AppendText(_T("clearance = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_clearance_height / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("rapid_down_to_height = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_rapid_down_to_height / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("start_depth = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_start_depth / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("step_down = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_step_down / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("final_depth = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_final_depth / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("tool_diameter = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_tool_diameter / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("spindle("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_spindle_speed);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("feedrate_hv("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_horizontal_feed_rate);
	theApp.m_program_canvas->AppendText(_T(", "));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_vertical_feed_rate);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("tool_change("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_tool_number);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("workplane("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_workplane);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("flush_nc()\n"));

}

<commit_msg>the xml file didn't like 'fixture offset'-changed to 'fixture_offset'<commit_after>// DepthOp.cpp
/*
 * Copyright (c) 2009, Dan Heeks
 * This program is released under the BSD license. See the file COPYING for
 * details.
 */

#include "stdafx.h"
#include "DepthOp.h"
#include "CNCConfig.h"
#include "ProgramCanvas.h"
#include "Program.h"
#include "interface/PropertyInt.h"
#include "interface/PropertyDouble.h"
#include "interface/PropertyLength.h"
#include "tinyxml/tinyxml.h"
#include "interface/Tool.h"

CDepthOpParams::CDepthOpParams()
{
	m_tool_number = 0;
	m_tool_diameter = 0.0;
	m_clearance_height = 0.0;
	m_start_depth = 0.0;
	m_step_down = 0.0;
	m_final_depth = 0.0;
	m_rapid_down_to_height = 0.0;
	m_horizontal_feed_rate = 0.0;
	m_vertical_feed_rate = 0.0;
	m_spindle_speed = 0.0;
}

void CDepthOpParams::set_initial_values()
{
	CNCConfig config;
    config.Read(_T("DepthFixtureOffset"), &m_workplane,1);
	config.Read(_T("DepthOpToolNumber"), &m_tool_number, 1);
	config.Read(_T("DepthOpToolDiameter"), &m_tool_diameter, 3.0);
	config.Read(_T("DepthOpClearanceHeight"), &m_clearance_height, 5.0);
	config.Read(_T("DepthOpStartDepth"), &m_start_depth, 0.0);
	config.Read(_T("DepthOpStepDown"), &m_step_down, 1.0);
	config.Read(_T("DepthOpFinalDepth"), &m_final_depth, -1.0);
	config.Read(_T("DepthOpRapidDown"), &m_rapid_down_to_height, 2.0);
	config.Read(_T("DepthOpHorizFeed"), &m_horizontal_feed_rate, 100.0);
	config.Read(_T("DepthOpVertFeed"), &m_vertical_feed_rate, 100.0);
	config.Read(_T("DepthOpSpindleSpeed"), &m_spindle_speed, 7000);
}

void CDepthOpParams::write_values_to_config()
{
	CNCConfig config;
	config.Write(_T("DepthFixtureOffset"), m_workplane);
	config.Write(_T("DepthOpToolNumber"), m_tool_number);
	config.Write(_T("DepthOpToolDiameter"), m_tool_diameter);
	config.Write(_T("DepthOpClearanceHeight"), m_clearance_height);
	config.Write(_T("DepthOpStartDepth"), m_start_depth);
	config.Write(_T("DepthOpStepDown"), m_step_down);
	config.Write(_T("DepthOpFinalDepth"), m_final_depth);
	config.Write(_T("DepthOpRapidDown"), m_rapid_down_to_height);
	config.Write(_T("DepthOpHorizFeed"), m_horizontal_feed_rate);
	config.Write(_T("DepthOpVertFeed"), m_vertical_feed_rate);
	config.Write(_T("DepthOpSpindleSpeed"), m_spindle_speed);
}

static void on_set_workplane(int value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_workplane = value;}
static void on_set_tool_number(int value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_tool_number = value;}
static void on_set_tool_diameter(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_tool_diameter = value;}
static void on_set_clearance_height(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_clearance_height = value;}
static void on_set_step_down(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_step_down = value;}
static void on_set_start_depth(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_start_depth = value;}
static void on_set_final_depth(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_final_depth = value;}
static void on_set_rapid_down_to_height(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_rapid_down_to_height = value;}
static void on_set_horizontal_feed_rate(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_horizontal_feed_rate = value;}
static void on_set_vertical_feed_rate(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_vertical_feed_rate = value;}
static void on_set_spindle_speed(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_spindle_speed = value;}

void CDepthOpParams::GetProperties(CDepthOp* parent, std::list<Property *> *list)
{
	list->push_back(new PropertyInt(_("fixture offset"), m_workplane, parent, on_set_workplane));
	list->push_back(new PropertyInt(_("tool number"), m_tool_number, parent, on_set_tool_number));
	list->push_back(new PropertyLength(_("tool diameter"), m_tool_diameter, parent, on_set_tool_diameter));
	list->push_back(new PropertyLength(_("clearance height"), m_clearance_height, parent, on_set_clearance_height));
	list->push_back(new PropertyLength(_("step down"), m_step_down, parent, on_set_step_down));
	list->push_back(new PropertyLength(_("start depth"), m_start_depth, parent, on_set_start_depth));
	list->push_back(new PropertyLength(_("final depth"), m_final_depth, parent, on_set_final_depth));
	list->push_back(new PropertyLength(_("rapid down to height"), m_rapid_down_to_height, parent, on_set_rapid_down_to_height));
	list->push_back(new PropertyDouble(_("horizontal feed rate"), m_horizontal_feed_rate, parent, on_set_horizontal_feed_rate));
	list->push_back(new PropertyDouble(_("vertical feed rate"), m_vertical_feed_rate, parent, on_set_vertical_feed_rate));
	list->push_back(new PropertyDouble(_("spindle speed"), m_spindle_speed, parent, on_set_spindle_speed));
}

void CDepthOpParams::WriteXMLAttributes(TiXmlNode* pElem)
{
	TiXmlElement * element = new TiXmlElement( "depthop" );
	pElem->LinkEndChild( element );
	element->SetAttribute("fixture_offset", m_workplane);
	element->SetAttribute("tooln", m_tool_number);
	element->SetDoubleAttribute("toold", m_tool_diameter);
	element->SetDoubleAttribute("clear", m_clearance_height);
	element->SetDoubleAttribute("down", m_step_down);
	element->SetDoubleAttribute("startdepth", m_start_depth);
	element->SetDoubleAttribute("depth", m_final_depth);
	element->SetDoubleAttribute("r", m_rapid_down_to_height);
	element->SetDoubleAttribute("hfeed", m_horizontal_feed_rate);
	element->SetDoubleAttribute("vfeed", m_vertical_feed_rate);
	element->SetDoubleAttribute("spin", m_spindle_speed);
}

void CDepthOpParams::ReadFromXMLElement(TiXmlElement* pElem)
{
	TiXmlElement* depthop = TiXmlHandle(pElem).FirstChildElement("depthop").Element();
	if(depthop)
	{

		depthop->Attribute("fixture offset", &m_workplane);
		depthop->Attribute("tooln", &m_tool_number);
		depthop->Attribute("toold", &m_tool_diameter);
		depthop->Attribute("clear", &m_clearance_height);
		depthop->Attribute("down", &m_step_down);
		depthop->Attribute("startdepth", &m_start_depth);
		depthop->Attribute("depth", &m_final_depth);
		depthop->Attribute("r", &m_rapid_down_to_height);
		depthop->Attribute("hfeed", &m_horizontal_feed_rate);
		depthop->Attribute("vfeed", &m_vertical_feed_rate);
		depthop->Attribute("spin", &m_spindle_speed);
	}
}

void CDepthOp::WriteBaseXML(TiXmlElement *element)
{
	m_depth_op_params.WriteXMLAttributes(element);
	COp::WriteBaseXML(element);
}

void CDepthOp::ReadBaseXML(TiXmlElement* element)
{
	m_depth_op_params.ReadFromXMLElement(element);
	COp::ReadBaseXML(element);
}

void CDepthOp::GetProperties(std::list<Property *> *list)
{
	m_depth_op_params.GetProperties(this, list);
	COp::GetProperties(list);
}

void CDepthOp::AppendTextToProgram()
{
	COp::AppendTextToProgram();

	theApp.m_program_canvas->AppendText(_T("clearance = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_clearance_height / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("rapid_down_to_height = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_rapid_down_to_height / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("start_depth = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_start_depth / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("step_down = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_step_down / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("final_depth = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_final_depth / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("tool_diameter = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_tool_diameter / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("spindle("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_spindle_speed);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("feedrate_hv("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_horizontal_feed_rate);
	theApp.m_program_canvas->AppendText(_T(", "));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_vertical_feed_rate);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("tool_change("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_tool_number);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("workplane("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_workplane);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("flush_nc()\n"));

}

<|endoftext|>


<commit_before><commit_msg>legion: avoiding allocation in the common case when computing eq make ready sets<commit_after><|endoftext|>


<commit_before><commit_msg>#78528# EnterData(EditTextObject): recognize formulas even if formatted<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS aw035 (1.21.182); FILE MERGED 2006/07/13 16:05:18 aw 1.21.182.1: #126320# SdrMark::GetObj() -> SdrMark::GetMarkedSdrObj() for isolating selection handling<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS ooo19126 (1.36.66); FILE MERGED 2005/09/05 13:25:47 rt 1.36.66.1: #i54170# Change license header: remove SISSL<commit_after><|endoftext|>


<commit_before><commit_msg>#83188# Prevent crash when item set lacks the ID_FILETP_READONLY item (office documents found by the old chaos search had this problem).<commit_after><|endoftext|>