<commit_before>#include "retracer.h"

#include "apitracecall.h"
#include "thumbnail.h"

#include "image.hpp"

#include "trace_profiler.hpp"

#include <QDebug>
#include <QVariant>
#include <QList>
#include <QImage>

#include <qjson/parser.h>

/**
 * Wrapper around a QProcess which enforces IO to block .
 *
 * Several QIODevice users (notably QJSON) expect blocking semantics, e.g.,
 * they expect that QIODevice::read() will blocked until the requested ammount
 * of bytes is read or end of file is reached. But by default QProcess, does
 * not block.  And passing QIODevice::Unbuffered mitigates but does not fully
 * address the problem either.
 *
 * This class wraps around QProcess, providing QIODevice interface, while
 * ensuring that all reads block.
 *
 * This class also works around a bug in QProcess::atEnd() implementation.
 *
 * See also:
 * - http://qt-project.org/wiki/Simple_Crypt_IO_Device
 * - http://qt-project.org/wiki/Custom_IO_Device
 */
class BlockingIODevice : public QIODevice
{
    /* We don't use the Q_OBJECT in this class given we don't declare any
     * signals and slots or use any other services provided by Qt's meta-object
     * system. */
public:
    BlockingIODevice(QProcess * io);
    bool isSequential() const;
    bool atEnd() const;
    bool waitForReadyRead(int msecs = -1);

protected:
    qint64 readData(char * data, qint64 maxSize);
    qint64 writeData(const char * data, qint64 maxSize);

private:
    QProcess *m_device;
};

BlockingIODevice::BlockingIODevice(QProcess * io) :
    m_device(io)
{
    /*
     * We pass QIODevice::Unbuffered to prevent the base QIODevice class to do
     * its own buffering on top of the overridden readData() method.
     *
     * The only buffering used will be to satisfy QIODevice::peek() and
     * QIODevice::ungetChar().
     */
    setOpenMode(ReadOnly | Unbuffered);
}

bool BlockingIODevice::isSequential() const
{
    return true;
}

bool BlockingIODevice::atEnd() const
{
    /*
     * XXX: QProcess::atEnd() documentation is wrong -- it will return true
     * even when the process is running --, so we try to workaround that here.
     */
    if (m_device->atEnd()) {
        if (m_device->state() == QProcess::Running) {
            if (!m_device->waitForReadyRead(-1)) {
                return true;
            }
        }
    }
    return false;
}

bool BlockingIODevice::waitForReadyRead(int msecs)
{
    Q_UNUSED(msecs);
    return true;
}

qint64 BlockingIODevice::readData(char * data, qint64 maxSize)
{
    qint64 bytesToRead = maxSize;
    qint64 readSoFar = 0;
    do {
        qint64 chunkSize = m_device->read(data + readSoFar, bytesToRead);
        if (chunkSize < 0) {
            if (readSoFar) {
                return readSoFar;
            } else {
                return chunkSize;
            }
        }
        Q_ASSERT(chunkSize <= bytesToRead);
        bytesToRead -= chunkSize;
        readSoFar += chunkSize;
        if (bytesToRead) {
            if (!m_device->waitForReadyRead(-1)) {
                qDebug() << "waitForReadyRead failed\n";
                break;
            }
        }
    } while(bytesToRead);

    return readSoFar;
}

qint64 BlockingIODevice::writeData(const char * data, qint64 maxSize)
{
    Q_ASSERT(false);
    return -1;
}

Q_DECLARE_METATYPE(QList<ApiTraceError>);

Retracer::Retracer(QObject *parent)
    : QThread(parent),
      m_benchmarking(false),
      m_doubleBuffered(true),
      m_captureState(false),
      m_captureCall(0),
      m_profileGpu(false),
      m_profileCpu(false),
      m_profilePixels(false)
{
    qRegisterMetaType<QList<ApiTraceError> >();

#ifdef Q_OS_WIN
    QString format = QLatin1String("%1;");
#else
    QString format = QLatin1String("%1:");
#endif
    QString buildPath = format.arg(APITRACE_BINARY_DIR);
    m_processEnvironment = QProcessEnvironment::systemEnvironment();
    m_processEnvironment.insert("PATH", buildPath +
                                m_processEnvironment.value("PATH"));

    qputenv("PATH",
            m_processEnvironment.value("PATH").toLatin1());
}

QString Retracer::fileName() const
{
    return m_fileName;
}

void Retracer::setFileName(const QString &name)
{
    m_fileName = name;
}

void Retracer::setAPI(trace::API api)
{
    m_api = api;
}

bool Retracer::isBenchmarking() const
{
    return m_benchmarking;
}

void Retracer::setBenchmarking(bool bench)
{
    m_benchmarking = bench;
}

bool Retracer::isDoubleBuffered() const
{
    return m_doubleBuffered;
}

void Retracer::setDoubleBuffered(bool db)
{
    m_doubleBuffered = db;
}

bool Retracer::isProfilingGpu() const
{
    return m_profileGpu;
}

bool Retracer::isProfilingCpu() const
{
    return m_profileCpu;
}

bool Retracer::isProfilingPixels() const
{
    return m_profilePixels;
}

bool Retracer::isProfiling() const
{
    return m_profileGpu || m_profileCpu || m_profilePixels;
}

void Retracer::setProfiling(bool gpu, bool cpu, bool pixels)
{
    m_profileGpu = gpu;
    m_profileCpu = cpu;
    m_profilePixels = pixels;
}

void Retracer::setCaptureAtCallNumber(qlonglong num)
{
    m_captureCall = num;
}

qlonglong Retracer::captureAtCallNumber() const
{
    return m_captureCall;
}

bool Retracer::captureState() const
{
    return m_captureState;
}

void Retracer::setCaptureState(bool enable)
{
    m_captureState = enable;
}

bool Retracer::captureThumbnails() const
{
    return m_captureThumbnails;
}

void Retracer::setCaptureThumbnails(bool enable)
{
    m_captureThumbnails = enable;
}

/**
 * Starting point for the retracing thread.
 *
 * Overrides QThread::run().
 */
void Retracer::run()
{
    QString msg = QLatin1String("Replay finished!");

    /*
     * Construct command line
     */

    QString prog;
    QStringList arguments;

    switch (m_api) {
    case trace::API_GL:
        prog = QLatin1String("glretrace");
        break;
    case trace::API_EGL:
        prog = QLatin1String("eglretrace");
        break;
    case trace::API_DX:
    case trace::API_D3D7:
    case trace::API_D3D8:
    case trace::API_D3D9:
    case trace::API_D3D10:
    case trace::API_D3D10_1:
    case trace::API_D3D11:
#ifdef Q_OS_WIN
        prog = QLatin1String("d3dretrace");
#else
        prog = QLatin1String("wine");
        arguments << QLatin1String("d3dretrace.exe");
#endif
        break;
    default:
        emit finished(QLatin1String("Unsupported API"));
        return;
    }

    if (m_captureState) {
        arguments << QLatin1String("-D");
        arguments << QString::number(m_captureCall);
    } else if (m_captureThumbnails) {
        arguments << QLatin1String("-s"); // emit snapshots
        arguments << QLatin1String("-"); // emit to stdout
    } else if (isProfiling()) {
        if (m_profileGpu) {
            arguments << QLatin1String("--pgpu");
        }

        if (m_profileCpu) {
            arguments << QLatin1String("--pcpu");
        }

        if (m_profilePixels) {
            arguments << QLatin1String("--ppd");
        }
    } else {
        if (m_doubleBuffered) {
            arguments << QLatin1String("--db");
        } else {
            arguments << QLatin1String("--sb");
        }

        if (m_benchmarking) {
            arguments << QLatin1String("-b");
        }
    }

    arguments << m_fileName;

    /*
     * Start the process.
     */

    QProcess process;

    process.start(prog, arguments, QIODevice::ReadOnly);
    if (!process.waitForStarted(-1)) {
        emit finished(QLatin1String("Could not start process"));
        return;
    }

    /*
     * Process standard output
     */

    QList<QImage> thumbnails;
    QVariantMap parsedJson;
    trace::Profile* profile = NULL;

    process.setReadChannel(QProcess::StandardOutput);
    if (process.waitForReadyRead(-1)) {
        BlockingIODevice io(&process);

        if (m_captureState) {
            /*
             * Parse JSON from the output.
             *
             * XXX: QJSON's scanner is inneficient as it abuses single
             * character QIODevice::peek (not cheap), instead of maintaining a
             * lookahead character on its own.
             */

            bool ok = false;
            QJson::Parser jsonParser;

            // Allow Nan/Infinity
            jsonParser.allowSpecialNumbers(true);
#if 0
            parsedJson = jsonParser.parse(&io, &ok).toMap();
#else
            /*
             * XXX: QJSON expects blocking IO, and it looks like
             * BlockingIODevice does not work reliably in all cases.
             */
            process.waitForFinished(-1);
            parsedJson = jsonParser.parse(&process, &ok).toMap();
#endif
            if (!ok) {
                msg = QLatin1String("failed to parse JSON");
            }
        } else if (m_captureThumbnails) {
            /*
             * Parse concatenated PNM images from output.
             */

            while (!io.atEnd()) {
                unsigned channels = 0;
                unsigned width = 0;
                unsigned height = 0;

                char header[512];
                qint64 headerSize = 0;
                int headerLines = 3; // assume no optional comment line

                for (int headerLine = 0; headerLine < headerLines; ++headerLine) {
                    qint64 headerRead = io.readLine(&header[headerSize], sizeof(header) - headerSize);

                    // if header actually contains optional comment line, ...
                    if (headerLine == 1 && header[headerSize] == '#') {
                        ++headerLines;
                    }

                    headerSize += headerRead;
                }

                const char *headerEnd = image::readPNMHeader(header, headerSize, &channels, &width, &height);

                // if invalid PNM header was encountered, ...
                if (header == headerEnd) {
                    qDebug() << "error: invalid snapshot stream encountered";
                    break;
                }

                // qDebug() << "channels: " << channels << ", width: " << width << ", height: " << height";

                QImage snapshot = QImage(width, height, channels == 1 ? QImage::Format_Mono : QImage::Format_RGB888);

                int rowBytes = channels * width;
                for (int y = 0; y < height; ++y) {
                    unsigned char *scanLine = snapshot.scanLine(y);
                    qint64 readBytes = io.read((char *) scanLine, rowBytes);
                    Q_ASSERT(readBytes == rowBytes);
                }

                QImage thumb = thumbnail(snapshot);
                thumbnails.append(thumb);
            }

            Q_ASSERT(process.state() != QProcess::Running);
        } else if (isProfiling()) {
            profile = new trace::Profile();

            while (!io.atEnd()) {
                char line[256];
                qint64 lineLength;

                lineLength = io.readLine(line, 256);

                if (lineLength == -1)
                    break;

                trace::Profiler::parseLine(line, profile);
            }
        } else {
            QByteArray output;
            output = process.readAllStandardOutput();
            if (output.length() < 80) {
                msg = QString::fromUtf8(output);
            }
        }
    }

    /*
     * Wait for process termination
     */

    process.waitForFinished(-1);

    if (process.exitStatus() != QProcess::NormalExit) {
        msg = QLatin1String("Process crashed");
    } else if (process.exitCode() != 0) {
        msg = QLatin1String("Process exited with non zero exit code");
    }

    /*
     * Parse errors.
     */

    QList<ApiTraceError> errors;
    process.setReadChannel(QProcess::StandardError);
    QRegExp regexp("(^\\d+): +(\\b\\w+\\b): ([^\\r\\n]+)[\\r\\n]*$");
    while (!process.atEnd()) {
        QString line = process.readLine();
        if (regexp.indexIn(line) != -1) {
            ApiTraceError error;
            error.callIndex = regexp.cap(1).toInt();
            error.type = regexp.cap(2);
            error.message = regexp.cap(3);
            errors.append(error);
        } else if (!errors.isEmpty()) {
            // Probably a multiligne message
            ApiTraceError &previous = errors.last();
            if (line.endsWith("\n")) {
                line.chop(1);
            }
            previous.message.append('\n');
            previous.message.append(line);
        }
    }

    /*
     * Emit signals
     */

    if (m_captureState) {
        ApiTraceState *state = new ApiTraceState(parsedJson);
        emit foundState(state);
        msg = QLatin1String("State fetched.");
    }

    if (m_captureThumbnails && !thumbnails.isEmpty()) {
        emit foundThumbnails(thumbnails);
    }

    if (isProfiling() && profile) {
        emit foundProfile(profile);
    }

    if (!errors.isEmpty()) {
        emit retraceErrors(errors);
    }

    emit finished(msg);
}

#include "retracer.moc"
<commit_msg>gui: Silence unused var warning.<commit_after>#include "retracer.h"

#include "apitracecall.h"
#include "thumbnail.h"

#include "image.hpp"

#include "trace_profiler.hpp"

#include <QDebug>
#include <QVariant>
#include <QList>
#include <QImage>

#include <qjson/parser.h>

/**
 * Wrapper around a QProcess which enforces IO to block .
 *
 * Several QIODevice users (notably QJSON) expect blocking semantics, e.g.,
 * they expect that QIODevice::read() will blocked until the requested ammount
 * of bytes is read or end of file is reached. But by default QProcess, does
 * not block.  And passing QIODevice::Unbuffered mitigates but does not fully
 * address the problem either.
 *
 * This class wraps around QProcess, providing QIODevice interface, while
 * ensuring that all reads block.
 *
 * This class also works around a bug in QProcess::atEnd() implementation.
 *
 * See also:
 * - http://qt-project.org/wiki/Simple_Crypt_IO_Device
 * - http://qt-project.org/wiki/Custom_IO_Device
 */
class BlockingIODevice : public QIODevice
{
    /* We don't use the Q_OBJECT in this class given we don't declare any
     * signals and slots or use any other services provided by Qt's meta-object
     * system. */
public:
    BlockingIODevice(QProcess * io);
    bool isSequential() const;
    bool atEnd() const;
    bool waitForReadyRead(int msecs = -1);

protected:
    qint64 readData(char * data, qint64 maxSize);
    qint64 writeData(const char * data, qint64 maxSize);

private:
    QProcess *m_device;
};

BlockingIODevice::BlockingIODevice(QProcess * io) :
    m_device(io)
{
    /*
     * We pass QIODevice::Unbuffered to prevent the base QIODevice class to do
     * its own buffering on top of the overridden readData() method.
     *
     * The only buffering used will be to satisfy QIODevice::peek() and
     * QIODevice::ungetChar().
     */
    setOpenMode(ReadOnly | Unbuffered);
}

bool BlockingIODevice::isSequential() const
{
    return true;
}

bool BlockingIODevice::atEnd() const
{
    /*
     * XXX: QProcess::atEnd() documentation is wrong -- it will return true
     * even when the process is running --, so we try to workaround that here.
     */
    if (m_device->atEnd()) {
        if (m_device->state() == QProcess::Running) {
            if (!m_device->waitForReadyRead(-1)) {
                return true;
            }
        }
    }
    return false;
}

bool BlockingIODevice::waitForReadyRead(int msecs)
{
    Q_UNUSED(msecs);
    return true;
}

qint64 BlockingIODevice::readData(char * data, qint64 maxSize)
{
    qint64 bytesToRead = maxSize;
    qint64 readSoFar = 0;
    do {
        qint64 chunkSize = m_device->read(data + readSoFar, bytesToRead);
        if (chunkSize < 0) {
            if (readSoFar) {
                return readSoFar;
            } else {
                return chunkSize;
            }
        }
        Q_ASSERT(chunkSize <= bytesToRead);
        bytesToRead -= chunkSize;
        readSoFar += chunkSize;
        if (bytesToRead) {
            if (!m_device->waitForReadyRead(-1)) {
                qDebug() << "waitForReadyRead failed\n";
                break;
            }
        }
    } while(bytesToRead);

    return readSoFar;
}

qint64 BlockingIODevice::writeData(const char * data, qint64 maxSize)
{
    Q_ASSERT(false);
    return -1;
}

Q_DECLARE_METATYPE(QList<ApiTraceError>);

Retracer::Retracer(QObject *parent)
    : QThread(parent),
      m_benchmarking(false),
      m_doubleBuffered(true),
      m_captureState(false),
      m_captureCall(0),
      m_profileGpu(false),
      m_profileCpu(false),
      m_profilePixels(false)
{
    qRegisterMetaType<QList<ApiTraceError> >();

#ifdef Q_OS_WIN
    QString format = QLatin1String("%1;");
#else
    QString format = QLatin1String("%1:");
#endif
    QString buildPath = format.arg(APITRACE_BINARY_DIR);
    m_processEnvironment = QProcessEnvironment::systemEnvironment();
    m_processEnvironment.insert("PATH", buildPath +
                                m_processEnvironment.value("PATH"));

    qputenv("PATH",
            m_processEnvironment.value("PATH").toLatin1());
}

QString Retracer::fileName() const
{
    return m_fileName;
}

void Retracer::setFileName(const QString &name)
{
    m_fileName = name;
}

void Retracer::setAPI(trace::API api)
{
    m_api = api;
}

bool Retracer::isBenchmarking() const
{
    return m_benchmarking;
}

void Retracer::setBenchmarking(bool bench)
{
    m_benchmarking = bench;
}

bool Retracer::isDoubleBuffered() const
{
    return m_doubleBuffered;
}

void Retracer::setDoubleBuffered(bool db)
{
    m_doubleBuffered = db;
}

bool Retracer::isProfilingGpu() const
{
    return m_profileGpu;
}

bool Retracer::isProfilingCpu() const
{
    return m_profileCpu;
}

bool Retracer::isProfilingPixels() const
{
    return m_profilePixels;
}

bool Retracer::isProfiling() const
{
    return m_profileGpu || m_profileCpu || m_profilePixels;
}

void Retracer::setProfiling(bool gpu, bool cpu, bool pixels)
{
    m_profileGpu = gpu;
    m_profileCpu = cpu;
    m_profilePixels = pixels;
}

void Retracer::setCaptureAtCallNumber(qlonglong num)
{
    m_captureCall = num;
}

qlonglong Retracer::captureAtCallNumber() const
{
    return m_captureCall;
}

bool Retracer::captureState() const
{
    return m_captureState;
}

void Retracer::setCaptureState(bool enable)
{
    m_captureState = enable;
}

bool Retracer::captureThumbnails() const
{
    return m_captureThumbnails;
}

void Retracer::setCaptureThumbnails(bool enable)
{
    m_captureThumbnails = enable;
}

/**
 * Starting point for the retracing thread.
 *
 * Overrides QThread::run().
 */
void Retracer::run()
{
    QString msg = QLatin1String("Replay finished!");

    /*
     * Construct command line
     */

    QString prog;
    QStringList arguments;

    switch (m_api) {
    case trace::API_GL:
        prog = QLatin1String("glretrace");
        break;
    case trace::API_EGL:
        prog = QLatin1String("eglretrace");
        break;
    case trace::API_DX:
    case trace::API_D3D7:
    case trace::API_D3D8:
    case trace::API_D3D9:
    case trace::API_D3D10:
    case trace::API_D3D10_1:
    case trace::API_D3D11:
#ifdef Q_OS_WIN
        prog = QLatin1String("d3dretrace");
#else
        prog = QLatin1String("wine");
        arguments << QLatin1String("d3dretrace.exe");
#endif
        break;
    default:
        emit finished(QLatin1String("Unsupported API"));
        return;
    }

    if (m_captureState) {
        arguments << QLatin1String("-D");
        arguments << QString::number(m_captureCall);
    } else if (m_captureThumbnails) {
        arguments << QLatin1String("-s"); // emit snapshots
        arguments << QLatin1String("-"); // emit to stdout
    } else if (isProfiling()) {
        if (m_profileGpu) {
            arguments << QLatin1String("--pgpu");
        }

        if (m_profileCpu) {
            arguments << QLatin1String("--pcpu");
        }

        if (m_profilePixels) {
            arguments << QLatin1String("--ppd");
        }
    } else {
        if (m_doubleBuffered) {
            arguments << QLatin1String("--db");
        } else {
            arguments << QLatin1String("--sb");
        }

        if (m_benchmarking) {
            arguments << QLatin1String("-b");
        }
    }

    arguments << m_fileName;

    /*
     * Start the process.
     */

    QProcess process;

    process.start(prog, arguments, QIODevice::ReadOnly);
    if (!process.waitForStarted(-1)) {
        emit finished(QLatin1String("Could not start process"));
        return;
    }

    /*
     * Process standard output
     */

    QList<QImage> thumbnails;
    QVariantMap parsedJson;
    trace::Profile* profile = NULL;

    process.setReadChannel(QProcess::StandardOutput);
    if (process.waitForReadyRead(-1)) {
        BlockingIODevice io(&process);

        if (m_captureState) {
            /*
             * Parse JSON from the output.
             *
             * XXX: QJSON's scanner is inneficient as it abuses single
             * character QIODevice::peek (not cheap), instead of maintaining a
             * lookahead character on its own.
             */

            bool ok = false;
            QJson::Parser jsonParser;

            // Allow Nan/Infinity
            jsonParser.allowSpecialNumbers(true);
#if 0
            parsedJson = jsonParser.parse(&io, &ok).toMap();
#else
            /*
             * XXX: QJSON expects blocking IO, and it looks like
             * BlockingIODevice does not work reliably in all cases.
             */
            process.waitForFinished(-1);
            parsedJson = jsonParser.parse(&process, &ok).toMap();
#endif
            if (!ok) {
                msg = QLatin1String("failed to parse JSON");
            }
        } else if (m_captureThumbnails) {
            /*
             * Parse concatenated PNM images from output.
             */

            while (!io.atEnd()) {
                unsigned channels = 0;
                unsigned width = 0;
                unsigned height = 0;

                char header[512];
                qint64 headerSize = 0;
                int headerLines = 3; // assume no optional comment line

                for (int headerLine = 0; headerLine < headerLines; ++headerLine) {
                    qint64 headerRead = io.readLine(&header[headerSize], sizeof(header) - headerSize);

                    // if header actually contains optional comment line, ...
                    if (headerLine == 1 && header[headerSize] == '#') {
                        ++headerLines;
                    }

                    headerSize += headerRead;
                }

                const char *headerEnd = image::readPNMHeader(header, headerSize, &channels, &width, &height);

                // if invalid PNM header was encountered, ...
                if (header == headerEnd) {
                    qDebug() << "error: invalid snapshot stream encountered";
                    break;
                }

                // qDebug() << "channels: " << channels << ", width: " << width << ", height: " << height";

                QImage snapshot = QImage(width, height, channels == 1 ? QImage::Format_Mono : QImage::Format_RGB888);

                int rowBytes = channels * width;
                for (int y = 0; y < height; ++y) {
                    unsigned char *scanLine = snapshot.scanLine(y);
                    qint64 readBytes = io.read((char *) scanLine, rowBytes);
                    Q_ASSERT(readBytes == rowBytes);
                    (void)readBytes;
                }

                QImage thumb = thumbnail(snapshot);
                thumbnails.append(thumb);
            }

            Q_ASSERT(process.state() != QProcess::Running);
        } else if (isProfiling()) {
            profile = new trace::Profile();

            while (!io.atEnd()) {
                char line[256];
                qint64 lineLength;

                lineLength = io.readLine(line, 256);

                if (lineLength == -1)
                    break;

                trace::Profiler::parseLine(line, profile);
            }
        } else {
            QByteArray output;
            output = process.readAllStandardOutput();
            if (output.length() < 80) {
                msg = QString::fromUtf8(output);
            }
        }
    }

    /*
     * Wait for process termination
     */

    process.waitForFinished(-1);

    if (process.exitStatus() != QProcess::NormalExit) {
        msg = QLatin1String("Process crashed");
    } else if (process.exitCode() != 0) {
        msg = QLatin1String("Process exited with non zero exit code");
    }

    /*
     * Parse errors.
     */

    QList<ApiTraceError> errors;
    process.setReadChannel(QProcess::StandardError);
    QRegExp regexp("(^\\d+): +(\\b\\w+\\b): ([^\\r\\n]+)[\\r\\n]*$");
    while (!process.atEnd()) {
        QString line = process.readLine();
        if (regexp.indexIn(line) != -1) {
            ApiTraceError error;
            error.callIndex = regexp.cap(1).toInt();
            error.type = regexp.cap(2);
            error.message = regexp.cap(3);
            errors.append(error);
        } else if (!errors.isEmpty()) {
            // Probably a multiligne message
            ApiTraceError &previous = errors.last();
            if (line.endsWith("\n")) {
                line.chop(1);
            }
            previous.message.append('\n');
            previous.message.append(line);
        }
    }

    /*
     * Emit signals
     */

    if (m_captureState) {
        ApiTraceState *state = new ApiTraceState(parsedJson);
        emit foundState(state);
        msg = QLatin1String("State fetched.");
    }

    if (m_captureThumbnails && !thumbnails.isEmpty()) {
        emit foundThumbnails(thumbnails);
    }

    if (isProfiling() && profile) {
        emit foundProfile(profile);
    }

    if (!errors.isEmpty()) {
        emit retraceErrors(errors);
    }

    emit finished(msg);
}

#include "retracer.moc"
<|endoftext|>


<commit_before>#include <boost/python.hpp>
#include <stddef.h>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <opengm/inference/inference.hxx>
#include <opengm/operations/adder.hxx>
#include <opengm/operations/multiplier.hxx>
#include <opengm/operations/minimizer.hxx>
#include <opengm/operations/maximizer.hxx>
#include <opengm/operations/integrator.hxx>

#include "pyInference.hxx"
#include "pyIcm.hxx"
#include "pyGraphcut.hxx"
#include "pyTrbp.hxx"
#include "pyBp.hxx"
#include "pyAstar.hxx"

//#include "pyGibbs.hxx"
#include "pyBruteforce.hxx"
#include "pyLazyflipper.hxx"
#include "pyDynp.hxx"

#include  "pyAe.hxx"
#include  "pyAbSwap.hxx"
#include  "pyPartitionMove.hxx"

#include "pyDualDecompositionSubGradient.hxx"
//#include "pyDualDecompositionMerit.hxx"
#ifdef WITH_CONICBUNDLE
   //#include "pyDualDecompositionBundle.hxx"
#endif
#ifdef WITH_LIBDAI
#include  "pyLibdai.hxx"
#endif

#ifdef WITH_CPLEX
#include "pyCplex.hxx"
#include "pyMultiCut.hxx"
#endif

#ifdef WITH_TRWS
#include "pyTrws.hxx"
#endif

#ifdef WITH_MRF
#include "pyMrf.hxx"
#endif

#ifdef WITH_FASTPD
#include "pyFastPD.hxx"
#endif

#ifdef WITH_AD3
#include "pyAd3.hxx"
#include "pyLoc.hxx"
#endif

#include "pyQpbo.hxx"

#ifdef WITH_QPBO
#include "pyQpbo.hxx"
#include "pyMQpbo.hxx"
#include "pyReducedInference.hxx"
#include  "pyAeFusion.hxx"
#endif

#if !defined(NOVIGRA) && (defined(WITH_QPBO) || (defined(WITH_BLOSSOM5) && defined(WITH_PLANARITY) ) )
#include "pyCgc.hxx"
#include "pyIntersectionBased.hxx"
#else
#error "something went wrong"
#endif

//#include "pyPbp.hxx"

#include "pyFusionMoves.hxx"
#include "pySelfFusion.hxx"
#include "pyFusionBased.hxx"

//#include "pySwendsenWang.hxx"

//#include "pyLpInference.hxx"

#include <opengm/python/opengmpython.hxx>
#include <opengm/python/converter.hxx>
#include <opengm/python/numpyview.hxx>
#include <opengm/python/pythonfunction.hxx>

// include the LPDef symbols only once!
#undef OPENGM_LPDEF_NO_SYMBOLS
#include <opengm/inference/auxiliary/lpdef.hxx>

using namespace boost::python;

BOOST_PYTHON_MODULE_INIT(_inference) {

   Py_Initialize();
   PyEval_InitThreads();
   boost::python::numeric::array::set_module_and_type("numpy", "ndarray");

   std::string adderString="adder";
   std::string multiplierString="multiplier";
   std::string minimizerString="minimizer";
   std::string maximizerString="maximizer";
   std::string integratorString="integrator";
   std::string substring,submoduleName,subsubmoduleName,subsubstring;
   docstring_options doc_options(true,true,false);
   scope current;
   std::string currentScopeName(extract<const char*>(current.attr("__name__")));
   currentScopeName="inference";
   //import_array();
   export_inference();
   //adder
   {
      substring=adderString;
      submoduleName = currentScopeName + std::string(".") + substring;
      // Create the submodule, and attach it to the current scope.
      object submodule(borrowed(PyImport_AddModule(submoduleName.c_str())));
      current.attr(substring.c_str()) = submodule;
      submodule.attr("__package__")=submoduleName.c_str();
      // Switch the scope to the submodule, add methods and classes.
      scope submoduleScope = submodule;
      // minimizer
      {
         subsubstring=minimizerString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         // Switch the scope to the submodule, add methods and classes.
         scope subsubmoduleScope = subsubmodule;

         export_icm<opengm::python::GmAdder,opengm::Minimizer>();
         //export_pbp<opengm::python::GmAdder,opengm::Minimizer>();
         export_bp<opengm::python::GmAdder,opengm::Minimizer>();
         export_trbp<opengm::python::GmAdder,opengm::Minimizer>();
         export_astar<opengm::python::GmAdder,opengm::Minimizer>();
         //export_gibbs<opengm::python::GmAdder,opengm::Minimizer>();

         export_dual_decomposition_subgradient<opengm::python::GmAdder,opengm::Minimizer>();

         //export_self_fusion<opengm::python::GmAdder,opengm::Minimizer>();
         export_fusion_moves<opengm::python::GmAdder,opengm::Minimizer>();

         #ifdef WITH_CONICBUNDLE
            //export_dual_decomposition_bundle<opengm::python::GmAdder,opengm::Minimizer>();
         #endif
         export_lazyflipper<opengm::python::GmAdder,opengm::Minimizer>();
         #ifdef WITH_AD3
         export_loc<opengm::python::GmAdder,opengm::Minimizer>();
         #endif
         export_bruteforce<opengm::python::GmAdder,opengm::Minimizer>();
         export_graphcut<opengm::python::GmAdder,opengm::Minimizer>();
         export_abswap<opengm::python::GmAdder,opengm::Minimizer>();
         export_ae<opengm::python::GmAdder,opengm::Minimizer>();
         export_dynp<opengm::python::GmAdder,opengm::Minimizer>();
         export_partition_move<opengm::python::GmAdder,opengm::Minimizer>();

         //export_qpbo<opengm::python::GmAdder,opengm::Minimizer>();
         #ifdef WITH_QPBO
         export_reduced_inference<opengm::python::GmAdder,opengm::Minimizer>();
         export_ae_fusion<opengm::python::GmAdder,opengm::Minimizer>();
         export_mqpbo<opengm::python::GmAdder,opengm::Minimizer>();
         export_qpbo_external<opengm::python::GmAdder,opengm::Minimizer>();
         #endif
         #ifdef WITH_TRWS
         export_trws<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

         #ifdef WITH_CPLEX
         export_cplex<opengm::python::GmAdder,opengm::Minimizer>();
         export_multicut<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

        #if defined(WITH_QPBO) || defined(WITH_CPLEX) || defined(WITH_BLOSSOM5) && defined(WITH_PLANARITY)
        //export_cgc<opengm::python::GmAdder,opengm::Minimizer>();
       	export_intersection_based<opengm::python::GmAdder,opengm::Minimizer>();
        #endif

         //export_lp_inference<opengm::python::GmAdder,opengm::Minimizer>();

         #ifdef WITH_LIBDAI
         export_libdai_inference<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

         #ifdef WITH_MRF
         export_mrf<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

         #ifdef WITH_FASTPD
         export_fast_pd<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

         #ifdef WITH_AD3
         export_ad3<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

         export_self_fusion<opengm::python::GmAdder,opengm::Minimizer>();
         export_fusion_based<opengm::python::GmAdder,opengm::Minimizer>();
      }
      // maximizer
      {
         subsubstring=maximizerString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         // Switch the scope to the submodule, add methods and classes.
         scope subsubmoduleScope = subsubmodule;
         export_icm<opengm::python::GmAdder,opengm::Maximizer>();
         export_bp<opengm::python::GmAdder,opengm::Maximizer>();
         export_trbp<opengm::python::GmAdder,opengm::Maximizer>();
         export_astar<opengm::python::GmAdder,opengm::Maximizer>();
         export_lazyflipper<opengm::python::GmAdder,opengm::Maximizer>();
         #ifdef WITH_AD3
         export_loc<opengm::python::GmAdder,opengm::Maximizer>();
         #endif
         export_bruteforce<opengm::python::GmAdder,opengm::Maximizer>();
         export_dynp<opengm::python::GmAdder,opengm::Maximizer>();

         #ifdef WITH_AD3
         export_ad3<opengm::python::GmAdder,opengm::Maximizer>();
         #endif
      }
      // integrator
      {
         subsubstring=integratorString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         scope subsubmoduleScope = subsubmodule;

         export_bp<opengm::python::GmAdder,opengm::Integrator>();
         export_trbp<opengm::python::GmAdder,opengm::Integrator>();
         //export_dynp<opengm::python::GmMultiplier,opengm::Maximizer>();
      }
   }
   //multiplier
   {
      substring=multiplierString;
      submoduleName = currentScopeName + std::string(".") + substring;
      // Create the submodule, and attach it to the current scope.
      object submodule(borrowed(PyImport_AddModule(submoduleName.c_str())));
      current.attr(substring.c_str()) = submodule;
      submodule.attr("__package__")=submoduleName.c_str();
      // Switch the scope to the submodule, add methods and classes.
      scope submoduleScope = submodule;
      // minimizer
      {
         subsubstring=minimizerString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         // Switch the scope to the submodule, add methods and classes.
         scope subsubmoduleScope = subsubmodule;
         export_icm<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_bp<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_trbp<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_astar<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_lazyflipper<opengm::python::GmMultiplier,opengm::Minimizer>();
         //export_loc<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_bruteforce<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_dynp<opengm::python::GmMultiplier,opengm::Minimizer>();
      }
      // maximizer
      {
         subsubstring=maximizerString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         // Switch the scope to the submodule, add methods and classes.
         scope subsubmoduleScope = subsubmodule;
         export_icm<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_bp<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_trbp<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_astar<opengm::python::GmMultiplier,opengm::Maximizer>();
         //export_gibbs<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_lazyflipper<opengm::python::GmMultiplier,opengm::Maximizer>();
         //export_loc<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_bruteforce<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_dynp<opengm::python::GmMultiplier,opengm::Maximizer>();
      }
      // integrator
      {
         subsubstring=integratorString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         scope subsubmoduleScope = subsubmodule;

         export_bp<opengm::python::GmMultiplier,opengm::Integrator>();
         export_trbp<opengm::python::GmMultiplier,opengm::Integrator>();
         //export_dynp<opengm::python::GmMultiplier,opengm::Maximizer>();
      }
   }
}
<commit_msg>hotfix<commit_after>#include <boost/python.hpp>
#include <stddef.h>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <opengm/inference/inference.hxx>
#include <opengm/operations/adder.hxx>
#include <opengm/operations/multiplier.hxx>
#include <opengm/operations/minimizer.hxx>
#include <opengm/operations/maximizer.hxx>
#include <opengm/operations/integrator.hxx>

#include "pyInference.hxx"
#include "pyIcm.hxx"
#include "pyGraphcut.hxx"
#include "pyTrbp.hxx"
#include "pyBp.hxx"
#include "pyAstar.hxx"

//#include "pyGibbs.hxx"
#include "pyBruteforce.hxx"
#include "pyLazyflipper.hxx"
#include "pyDynp.hxx"

#include  "pyAe.hxx"
#include  "pyAbSwap.hxx"
#include  "pyPartitionMove.hxx"

#include "pyDualDecompositionSubGradient.hxx"
//#include "pyDualDecompositionMerit.hxx"
#ifdef WITH_CONICBUNDLE
   //#include "pyDualDecompositionBundle.hxx"
#endif
#ifdef WITH_LIBDAI
#include  "pyLibdai.hxx"
#endif

#ifdef WITH_CPLEX
#include "pyCplex.hxx"
#include "pyMultiCut.hxx"
#endif

#ifdef WITH_TRWS
#include "pyTrws.hxx"
#endif

#ifdef WITH_MRF
#include "pyMrf.hxx"
#endif

#ifdef WITH_FASTPD
#include "pyFastPD.hxx"
#endif

#ifdef WITH_AD3
#include "pyAd3.hxx"
#include "pyLoc.hxx"
#endif

#include "pyQpbo.hxx"

#ifdef WITH_QPBO
#include "pyQpbo.hxx"
#include "pyMQpbo.hxx"
#include "pyReducedInference.hxx"
#include  "pyAeFusion.hxx"
#endif

#if !defined(NOVIGRA) && (defined(WITH_QPBO) || (defined(WITH_BLOSSOM5) && defined(WITH_PLANARITY) ) )
#include "pyCgc.hxx"
#include "pyIntersectionBased.hxx"
#endif

//#include "pyPbp.hxx"

#include "pyFusionMoves.hxx"
#include "pySelfFusion.hxx"
#include "pyFusionBased.hxx"

//#include "pySwendsenWang.hxx"

//#include "pyLpInference.hxx"

#include <opengm/python/opengmpython.hxx>
#include <opengm/python/converter.hxx>
#include <opengm/python/numpyview.hxx>
#include <opengm/python/pythonfunction.hxx>

// include the LPDef symbols only once!
#undef OPENGM_LPDEF_NO_SYMBOLS
#include <opengm/inference/auxiliary/lpdef.hxx>

using namespace boost::python;

BOOST_PYTHON_MODULE_INIT(_inference) {

   Py_Initialize();
   PyEval_InitThreads();
   boost::python::numeric::array::set_module_and_type("numpy", "ndarray");

   std::string adderString="adder";
   std::string multiplierString="multiplier";
   std::string minimizerString="minimizer";
   std::string maximizerString="maximizer";
   std::string integratorString="integrator";
   std::string substring,submoduleName,subsubmoduleName,subsubstring;
   docstring_options doc_options(true,true,false);
   scope current;
   std::string currentScopeName(extract<const char*>(current.attr("__name__")));
   currentScopeName="inference";
   //import_array();
   export_inference();
   //adder
   {
      substring=adderString;
      submoduleName = currentScopeName + std::string(".") + substring;
      // Create the submodule, and attach it to the current scope.
      object submodule(borrowed(PyImport_AddModule(submoduleName.c_str())));
      current.attr(substring.c_str()) = submodule;
      submodule.attr("__package__")=submoduleName.c_str();
      // Switch the scope to the submodule, add methods and classes.
      scope submoduleScope = submodule;
      // minimizer
      {
         subsubstring=minimizerString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         // Switch the scope to the submodule, add methods and classes.
         scope subsubmoduleScope = subsubmodule;

         export_icm<opengm::python::GmAdder,opengm::Minimizer>();
         //export_pbp<opengm::python::GmAdder,opengm::Minimizer>();
         export_bp<opengm::python::GmAdder,opengm::Minimizer>();
         export_trbp<opengm::python::GmAdder,opengm::Minimizer>();
         export_astar<opengm::python::GmAdder,opengm::Minimizer>();
         //export_gibbs<opengm::python::GmAdder,opengm::Minimizer>();

         export_dual_decomposition_subgradient<opengm::python::GmAdder,opengm::Minimizer>();

         //export_self_fusion<opengm::python::GmAdder,opengm::Minimizer>();
         export_fusion_moves<opengm::python::GmAdder,opengm::Minimizer>();

         #ifdef WITH_CONICBUNDLE
            //export_dual_decomposition_bundle<opengm::python::GmAdder,opengm::Minimizer>();
         #endif
         export_lazyflipper<opengm::python::GmAdder,opengm::Minimizer>();
         #ifdef WITH_AD3
         export_loc<opengm::python::GmAdder,opengm::Minimizer>();
         #endif
         export_bruteforce<opengm::python::GmAdder,opengm::Minimizer>();
         export_graphcut<opengm::python::GmAdder,opengm::Minimizer>();
         export_abswap<opengm::python::GmAdder,opengm::Minimizer>();
         export_ae<opengm::python::GmAdder,opengm::Minimizer>();
         export_dynp<opengm::python::GmAdder,opengm::Minimizer>();
         export_partition_move<opengm::python::GmAdder,opengm::Minimizer>();

         //export_qpbo<opengm::python::GmAdder,opengm::Minimizer>();
         #ifdef WITH_QPBO
         export_reduced_inference<opengm::python::GmAdder,opengm::Minimizer>();
         export_ae_fusion<opengm::python::GmAdder,opengm::Minimizer>();
         export_mqpbo<opengm::python::GmAdder,opengm::Minimizer>();
         export_qpbo_external<opengm::python::GmAdder,opengm::Minimizer>();
         #endif
         #ifdef WITH_TRWS
         export_trws<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

         #ifdef WITH_CPLEX
         export_cplex<opengm::python::GmAdder,opengm::Minimizer>();
         export_multicut<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

        #if defined(WITH_QPBO) || defined(WITH_CPLEX) || defined(WITH_BLOSSOM5) && defined(WITH_PLANARITY)
        //export_cgc<opengm::python::GmAdder,opengm::Minimizer>();
       	export_intersection_based<opengm::python::GmAdder,opengm::Minimizer>();
        #endif

         //export_lp_inference<opengm::python::GmAdder,opengm::Minimizer>();

         #ifdef WITH_LIBDAI
         export_libdai_inference<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

         #ifdef WITH_MRF
         export_mrf<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

         #ifdef WITH_FASTPD
         export_fast_pd<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

         #ifdef WITH_AD3
         export_ad3<opengm::python::GmAdder,opengm::Minimizer>();
         #endif

         export_self_fusion<opengm::python::GmAdder,opengm::Minimizer>();
         export_fusion_based<opengm::python::GmAdder,opengm::Minimizer>();
      }
      // maximizer
      {
         subsubstring=maximizerString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         // Switch the scope to the submodule, add methods and classes.
         scope subsubmoduleScope = subsubmodule;
         export_icm<opengm::python::GmAdder,opengm::Maximizer>();
         export_bp<opengm::python::GmAdder,opengm::Maximizer>();
         export_trbp<opengm::python::GmAdder,opengm::Maximizer>();
         export_astar<opengm::python::GmAdder,opengm::Maximizer>();
         export_lazyflipper<opengm::python::GmAdder,opengm::Maximizer>();
         #ifdef WITH_AD3
         export_loc<opengm::python::GmAdder,opengm::Maximizer>();
         #endif
         export_bruteforce<opengm::python::GmAdder,opengm::Maximizer>();
         export_dynp<opengm::python::GmAdder,opengm::Maximizer>();

         #ifdef WITH_AD3
         export_ad3<opengm::python::GmAdder,opengm::Maximizer>();
         #endif
      }
      // integrator
      {
         subsubstring=integratorString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         scope subsubmoduleScope = subsubmodule;

         export_bp<opengm::python::GmAdder,opengm::Integrator>();
         export_trbp<opengm::python::GmAdder,opengm::Integrator>();
         //export_dynp<opengm::python::GmMultiplier,opengm::Maximizer>();
      }
   }
   //multiplier
   {
      substring=multiplierString;
      submoduleName = currentScopeName + std::string(".") + substring;
      // Create the submodule, and attach it to the current scope.
      object submodule(borrowed(PyImport_AddModule(submoduleName.c_str())));
      current.attr(substring.c_str()) = submodule;
      submodule.attr("__package__")=submoduleName.c_str();
      // Switch the scope to the submodule, add methods and classes.
      scope submoduleScope = submodule;
      // minimizer
      {
         subsubstring=minimizerString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         // Switch the scope to the submodule, add methods and classes.
         scope subsubmoduleScope = subsubmodule;
         export_icm<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_bp<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_trbp<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_astar<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_lazyflipper<opengm::python::GmMultiplier,opengm::Minimizer>();
         //export_loc<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_bruteforce<opengm::python::GmMultiplier,opengm::Minimizer>();
         export_dynp<opengm::python::GmMultiplier,opengm::Minimizer>();
      }
      // maximizer
      {
         subsubstring=maximizerString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         // Switch the scope to the submodule, add methods and classes.
         scope subsubmoduleScope = subsubmodule;
         export_icm<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_bp<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_trbp<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_astar<opengm::python::GmMultiplier,opengm::Maximizer>();
         //export_gibbs<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_lazyflipper<opengm::python::GmMultiplier,opengm::Maximizer>();
         //export_loc<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_bruteforce<opengm::python::GmMultiplier,opengm::Maximizer>();
         export_dynp<opengm::python::GmMultiplier,opengm::Maximizer>();
      }
      // integrator
      {
         subsubstring=integratorString;
         subsubmoduleName = currentScopeName + std::string(".") + substring  + std::string(".") + subsubstring ;
         // Create the submodule, and attach it to the current scope.
         object subsubmodule(borrowed(PyImport_AddModule(subsubmoduleName.c_str())));
         submoduleScope.attr(subsubstring.c_str()) = subsubmodule;
         //subsubmodule.attr("__package__")=subsubmoduleName.c_str();
         scope subsubmoduleScope = subsubmodule;

         export_bp<opengm::python::GmMultiplier,opengm::Integrator>();
         export_trbp<opengm::python::GmMultiplier,opengm::Integrator>();
         //export_dynp<opengm::python::GmMultiplier,opengm::Maximizer>();
      }
   }
}
<|endoftext|>


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

/**
 * @file FlightTaskOrbit.cpp
 */

#include "FlightTaskOrbit.hpp"

#include <mathlib/mathlib.h>
#include <lib/ecl/geo/geo.h>

using namespace matrix;

FlightTaskOrbit::FlightTaskOrbit() : _circle_approach_line(_position)
{
	_sticks_data_required = false;
}

bool FlightTaskOrbit::applyCommandParameters(const vehicle_command_s &command)
{
	bool ret = true;
	// save previous velocity and roatation direction
	float v = fabsf(_v);
	bool clockwise = _v > 0;

	// commanded radius
	if (PX4_ISFINITE(command.param1)) {
		clockwise = command.param1 > 0;
		const float r = fabsf(command.param1);
		ret = ret && setRadius(r);
	}

	// commanded velocity, take sign of radius as rotation direction
	if (PX4_ISFINITE(command.param2)) {
		v = command.param2;
	}

	ret = ret && setVelocity(v * (clockwise ? 1.f : -1.f));

	// commanded heading behaviour
	if (PX4_ISFINITE(command.param3)) {
		_yaw_behaviour = command.param3;
	}

	// TODO: apply x,y / z independently in geo library
	// commanded center coordinates
	// if(PX4_ISFINITE(command.param5) && PX4_ISFINITE(command.param6)) {
	// 	map_projection_global_project(command.param5, command.param6, &_center(0), &_center(1));
	// }

	// commanded altitude
	// if(PX4_ISFINITE(command.param7)) {
	// 	_position_setpoint(2) = gl_ref.alt - command.param7;
	// }

	if (PX4_ISFINITE(command.param5) && PX4_ISFINITE(command.param6) && PX4_ISFINITE(command.param7)) {
		if (globallocalconverter_tolocal(command.param5, command.param6, command.param7, &_center(0), &_center(1),
						 &_position_setpoint(2))) {
			// global to local conversion failed
			ret = false;
		}
	}

	// perpendicularly approach the orbit circle again when new parameters get commanded
	_in_circle_approach = true;

	return ret;
}

bool FlightTaskOrbit::sendTelemetry()
{
	orbit_status_s orbit_status{};
	orbit_status.timestamp = hrt_absolute_time();
	orbit_status.radius = math::signNoZero(_v) * _r;
	orbit_status.frame = 0; // MAV_FRAME::MAV_FRAME_GLOBAL
	orbit_status.yaw_behaviour = _yaw_behaviour;

	if (globallocalconverter_toglobal(_center(0), _center(1), _position_setpoint(2), &orbit_status.x, &orbit_status.y,
					  &orbit_status.z)) {
		return false; // don't send the message if the transformation failed
	}

	_orbit_status_pub.publish(orbit_status);

	return true;
}

bool FlightTaskOrbit::setRadius(float r)
{
	// clip the radius to be within range
	r = math::constrain(r, _radius_min, _radius_max);

	// small radius is more important than high velocity for safety
	if (!checkAcceleration(r, _v, _acceleration_max)) {
		_v = sign(_v) * sqrtf(_acceleration_max * r);
	}

	_r = r;
	return true;
}

bool FlightTaskOrbit::setVelocity(const float v)
{
	if (fabs(v) < _velocity_max &&
	    checkAcceleration(_r, v, _acceleration_max)) {
		_v = v;
		return true;
	}

	return false;
}

bool FlightTaskOrbit::checkAcceleration(float r, float v, float a)
{
	return v * v < a * r;
}

bool FlightTaskOrbit::activate(vehicle_local_position_setpoint_s last_setpoint)
{
	bool ret = FlightTaskManualAltitudeSmooth::activate(last_setpoint);
	_r = _radius_min;
	_v =  1.f;
	_center = Vector2f(_position);
	_center(0) -= _r;

	_initial_heading = _yaw;

	// need a valid position and velocity
	ret = ret && PX4_ISFINITE(_position(0))
	      && PX4_ISFINITE(_position(1))
	      && PX4_ISFINITE(_position(2))
	      && PX4_ISFINITE(_velocity(0))
	      && PX4_ISFINITE(_velocity(1))
	      && PX4_ISFINITE(_velocity(2));

	return ret;
}

bool FlightTaskOrbit::update()
{
	// update altitude
	bool ret = FlightTaskManualAltitudeSmooth::update();

	// stick input adjusts parameters within a fixed time frame
	const float r = _r - _sticks.getPositionExpo()(0) * _deltatime * (_radius_max / 8.f);
	const float v = _v - _sticks.getPositionExpo()(1) * _deltatime * (_velocity_max / 4.f);

	setRadius(r);
	setVelocity(v);

	Vector2f center_to_position = Vector2f(_position) - _center;
	Vector2f start_to_circle = (_r - center_to_position.norm()) * center_to_position.unit_or_zero();

	if (_in_circle_approach) {
		generate_circle_approach_setpoints(start_to_circle);

	} else {
		generate_circle_setpoints(center_to_position);
		generate_circle_yaw_setpoints(center_to_position);
	}

	// publish information to UI
	sendTelemetry();

	return ret;
}

void FlightTaskOrbit::generate_circle_approach_setpoints(Vector2f start_to_circle)
{

	if (_circle_approach_line.isEndReached()) {
		// calculate target point on circle and plan a line trajectory
		Vector2f closest_circle_point = Vector2f(_position) + start_to_circle;
		Vector3f target = Vector3f(closest_circle_point(0), closest_circle_point(1), _position(2));
		_circle_approach_line.setLineFromTo(_position, target);
		_circle_approach_line.setSpeed(_param_mpc_xy_cruise.get());
		_yaw_setpoint = atan2f(start_to_circle(1), start_to_circle(0));
	}

	// follow the planned line and switch to orbiting once the circle is reached
	_circle_approach_line.generateSetpoints(_position_setpoint, _velocity_setpoint);
	_in_circle_approach = !_circle_approach_line.isEndReached();
}

void FlightTaskOrbit::generate_circle_setpoints(Vector2f center_to_position)
{
	// xy velocity to go around in a circle
	Vector2f velocity_xy(-center_to_position(1), center_to_position(0));
	velocity_xy = velocity_xy.unit_or_zero();
	velocity_xy *= _v;

	// xy velocity adjustment to stay on the radius distance
	velocity_xy += (_r - center_to_position.norm()) * center_to_position.unit_or_zero();

	_position_setpoint(0) = _position_setpoint(1) = NAN;
	_velocity_setpoint.xy() = velocity_xy;
	_acceleration_setpoint.xy() = -center_to_position.unit_or_zero() * _v * _v / _r;
}

void FlightTaskOrbit::generate_circle_yaw_setpoints(Vector2f center_to_position)
{
	switch (_yaw_behaviour) {
	case orbit_status_s::ORBIT_YAW_BEHAVIOUR_HOLD_INITIAL_HEADING:
		// make vehicle keep the same heading as when the orbit was commanded
		_yaw_setpoint = _initial_heading;
		_yawspeed_setpoint = NAN;
		break;

	case orbit_status_s::ORBIT_YAW_BEHAVIOUR_UNCONTROLLED:
		// no yaw setpoint
		_yaw_setpoint = NAN;
		_yawspeed_setpoint = NAN;
		break;

	case orbit_status_s::ORBIT_YAW_BEHAVIOUR_HOLD_FRONT_TANGENT_TO_CIRCLE:
		if (_r > 0) {
			_yaw_setpoint = atan2f(center_to_position(1), center_to_position(0)) + M_PI_F / 2.f;

		} else {
			_yaw_setpoint = atan2f(center_to_position(1), center_to_position(0)) - M_PI_F / 2.f;
		}

		_yawspeed_setpoint = _v / _r;

		break;

	case orbit_status_s::ORBIT_YAW_BEHAVIOUR_RC_CONTROLLED:
		_yaw_setpoint = NAN;
		_yawspeed_setpoint = _sticks.getPositionExpo()(3);
		break;

	case orbit_status_s::ORBIT_YAW_BEHAVIOUR_HOLD_FRONT_TO_CIRCLE_CENTER:
	default:
		_yaw_setpoint = atan2f(center_to_position(1), center_to_position(0)) + M_PI_F;
		// yawspeed feed-forward because we know the necessary angular rate
		_yawspeed_setpoint = _v / _r;
		break;
	}
}
<commit_msg>FlightTaskOrbit: use yaw setpoint from Altitude task with RC yaw mode<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2018-2019 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file FlightTaskOrbit.cpp
 */

#include "FlightTaskOrbit.hpp"

#include <mathlib/mathlib.h>
#include <lib/ecl/geo/geo.h>

using namespace matrix;

FlightTaskOrbit::FlightTaskOrbit() : _circle_approach_line(_position)
{
	_sticks_data_required = false;
}

bool FlightTaskOrbit::applyCommandParameters(const vehicle_command_s &command)
{
	bool ret = true;
	// save previous velocity and roatation direction
	float v = fabsf(_v);
	bool clockwise = _v > 0;

	// commanded radius
	if (PX4_ISFINITE(command.param1)) {
		clockwise = command.param1 > 0;
		const float r = fabsf(command.param1);
		ret = ret && setRadius(r);
	}

	// commanded velocity, take sign of radius as rotation direction
	if (PX4_ISFINITE(command.param2)) {
		v = command.param2;
	}

	ret = ret && setVelocity(v * (clockwise ? 1.f : -1.f));

	// commanded heading behaviour
	if (PX4_ISFINITE(command.param3)) {
		_yaw_behaviour = command.param3;
	}

	// TODO: apply x,y / z independently in geo library
	// commanded center coordinates
	// if(PX4_ISFINITE(command.param5) && PX4_ISFINITE(command.param6)) {
	// 	map_projection_global_project(command.param5, command.param6, &_center(0), &_center(1));
	// }

	// commanded altitude
	// if(PX4_ISFINITE(command.param7)) {
	// 	_position_setpoint(2) = gl_ref.alt - command.param7;
	// }

	if (PX4_ISFINITE(command.param5) && PX4_ISFINITE(command.param6) && PX4_ISFINITE(command.param7)) {
		if (globallocalconverter_tolocal(command.param5, command.param6, command.param7, &_center(0), &_center(1),
						 &_position_setpoint(2))) {
			// global to local conversion failed
			ret = false;
		}
	}

	// perpendicularly approach the orbit circle again when new parameters get commanded
	_in_circle_approach = true;

	return ret;
}

bool FlightTaskOrbit::sendTelemetry()
{
	orbit_status_s orbit_status{};
	orbit_status.timestamp = hrt_absolute_time();
	orbit_status.radius = math::signNoZero(_v) * _r;
	orbit_status.frame = 0; // MAV_FRAME::MAV_FRAME_GLOBAL
	orbit_status.yaw_behaviour = _yaw_behaviour;

	if (globallocalconverter_toglobal(_center(0), _center(1), _position_setpoint(2), &orbit_status.x, &orbit_status.y,
					  &orbit_status.z)) {
		return false; // don't send the message if the transformation failed
	}

	_orbit_status_pub.publish(orbit_status);

	return true;
}

bool FlightTaskOrbit::setRadius(float r)
{
	// clip the radius to be within range
	r = math::constrain(r, _radius_min, _radius_max);

	// small radius is more important than high velocity for safety
	if (!checkAcceleration(r, _v, _acceleration_max)) {
		_v = sign(_v) * sqrtf(_acceleration_max * r);
	}

	_r = r;
	return true;
}

bool FlightTaskOrbit::setVelocity(const float v)
{
	if (fabs(v) < _velocity_max &&
	    checkAcceleration(_r, v, _acceleration_max)) {
		_v = v;
		return true;
	}

	return false;
}

bool FlightTaskOrbit::checkAcceleration(float r, float v, float a)
{
	return v * v < a * r;
}

bool FlightTaskOrbit::activate(vehicle_local_position_setpoint_s last_setpoint)
{
	bool ret = FlightTaskManualAltitudeSmooth::activate(last_setpoint);
	_r = _radius_min;
	_v =  1.f;
	_center = Vector2f(_position);
	_center(0) -= _r;

	_initial_heading = _yaw;

	// need a valid position and velocity
	ret = ret && PX4_ISFINITE(_position(0))
	      && PX4_ISFINITE(_position(1))
	      && PX4_ISFINITE(_position(2))
	      && PX4_ISFINITE(_velocity(0))
	      && PX4_ISFINITE(_velocity(1))
	      && PX4_ISFINITE(_velocity(2));

	return ret;
}

bool FlightTaskOrbit::update()
{
	// update altitude
	bool ret = FlightTaskManualAltitudeSmooth::update();

	// stick input adjusts parameters within a fixed time frame
	const float r = _r - _sticks.getPositionExpo()(0) * _deltatime * (_radius_max / 8.f);
	const float v = _v - _sticks.getPositionExpo()(1) * _deltatime * (_velocity_max / 4.f);

	setRadius(r);
	setVelocity(v);

	Vector2f center_to_position = Vector2f(_position) - _center;
	Vector2f start_to_circle = (_r - center_to_position.norm()) * center_to_position.unit_or_zero();

	if (_in_circle_approach) {
		generate_circle_approach_setpoints(start_to_circle);

	} else {
		generate_circle_setpoints(center_to_position);
		generate_circle_yaw_setpoints(center_to_position);
	}

	// publish information to UI
	sendTelemetry();

	return ret;
}

void FlightTaskOrbit::generate_circle_approach_setpoints(Vector2f start_to_circle)
{

	if (_circle_approach_line.isEndReached()) {
		// calculate target point on circle and plan a line trajectory
		Vector2f closest_circle_point = Vector2f(_position) + start_to_circle;
		Vector3f target = Vector3f(closest_circle_point(0), closest_circle_point(1), _position(2));
		_circle_approach_line.setLineFromTo(_position, target);
		_circle_approach_line.setSpeed(_param_mpc_xy_cruise.get());
		_yaw_setpoint = atan2f(start_to_circle(1), start_to_circle(0));
	}

	// follow the planned line and switch to orbiting once the circle is reached
	_circle_approach_line.generateSetpoints(_position_setpoint, _velocity_setpoint);
	_in_circle_approach = !_circle_approach_line.isEndReached();
}

void FlightTaskOrbit::generate_circle_setpoints(Vector2f center_to_position)
{
	// xy velocity to go around in a circle
	Vector2f velocity_xy(-center_to_position(1), center_to_position(0));
	velocity_xy = velocity_xy.unit_or_zero();
	velocity_xy *= _v;

	// xy velocity adjustment to stay on the radius distance
	velocity_xy += (_r - center_to_position.norm()) * center_to_position.unit_or_zero();

	_position_setpoint(0) = _position_setpoint(1) = NAN;
	_velocity_setpoint.xy() = velocity_xy;
	_acceleration_setpoint.xy() = -center_to_position.unit_or_zero() * _v * _v / _r;
}

void FlightTaskOrbit::generate_circle_yaw_setpoints(Vector2f center_to_position)
{
	switch (_yaw_behaviour) {
	case orbit_status_s::ORBIT_YAW_BEHAVIOUR_HOLD_INITIAL_HEADING:
		// make vehicle keep the same heading as when the orbit was commanded
		_yaw_setpoint = _initial_heading;
		_yawspeed_setpoint = NAN;
		break;

	case orbit_status_s::ORBIT_YAW_BEHAVIOUR_UNCONTROLLED:
		// no yaw setpoint
		_yaw_setpoint = NAN;
		_yawspeed_setpoint = NAN;
		break;

	case orbit_status_s::ORBIT_YAW_BEHAVIOUR_HOLD_FRONT_TANGENT_TO_CIRCLE:
		if (_r > 0) {
			_yaw_setpoint = atan2f(center_to_position(1), center_to_position(0)) + M_PI_F / 2.f;

		} else {
			_yaw_setpoint = atan2f(center_to_position(1), center_to_position(0)) - M_PI_F / 2.f;
		}

		_yawspeed_setpoint = _v / _r;

		break;

	case orbit_status_s::ORBIT_YAW_BEHAVIOUR_RC_CONTROLLED:
		// inherit setpoint from altitude flight task
		break;

	case orbit_status_s::ORBIT_YAW_BEHAVIOUR_HOLD_FRONT_TO_CIRCLE_CENTER:
	default:
		_yaw_setpoint = atan2f(center_to_position(1), center_to_position(0)) + M_PI_F;
		// yawspeed feed-forward because we know the necessary angular rate
		_yawspeed_setpoint = _v / _r;
		break;
	}
}
<|endoftext|>


<commit_before><commit_msg>rsz repairNet<commit_after><|endoftext|>


<commit_before>// This file is part of MorphoDiTa.
//
// Copyright 2013 by Institute of Formal and Applied Linguistics, Faculty of
// Mathematics and Physics, Charles University in Prague, Czech Republic.
//
// MorphoDiTa is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// MorphoDiTa 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 MorphoDiTa.  If not, see <http://www.gnu.org/licenses/>.

#include <memory>

#include "morpho/morpho.h"
#include "tagger/tagger.h"
#include "tagset_converter/tagset_converter.h"
#include "utils/input.h"
#include "utils/parse_int.h"
#include "utils/parse_options.h"
#include "utils/process_args.h"

using namespace ufal::morphodita;

static void generate(FILE* in, FILE* out, const morpho& dictionary, bool use_guesser, const tagset_converter& tagset_converter);

int main(int argc, char* argv[]) {
  show_version_if_requested(argc, argv);

  options_map options;
  if (!parse_options({{"convert_tagset",option_values::any},
                      {"from_tagger",option_values::none}}, argc, argv, options) ||
      argc < 3)
    runtime_errorf("Usage: %s [options] dict_file use_guesser [file[:output_file]]...\n"
                   "Options: --convert_tagset=pdt_to_conll2009|strip_lemma_comment|strip_lemma_id\n"
                   "         --from_tagger", argv[0]);

  unique_ptr<morpho> morpho;
  unique_ptr<tagger> tagger;
  if (options.count("from_tagger")) {
    eprintf("Loading dictionary from tagger: ");
    tagger.reset(tagger::load(argv[1]));
    if (!tagger) runtime_errorf("Cannot load tagger from file '%s'!", argv[1]);
  } else {
    eprintf("Loading dictionary: ");
    morpho.reset(morpho::load(argv[1]));
    if (!morpho) runtime_errorf("Cannot load dictionary from file '%s'!", argv[1]);
  }
  eprintf("done\n");
  auto& dictionary = options.count("from_tagger") ? *tagger->get_morpho() : *morpho;

  bool use_guesser = parse_int(argv[2], "use_guesser");

  unique_ptr<tagset_converter> tagset_converter;
  if (options.count("convert_tagset")) {
    tagset_converter.reset(new_tagset_converter(options["convert_tagset"], dictionary));
    if (!tagset_converter) runtime_errorf("Unknown tag set converter '%s'!", options["convert_tagset"].c_str());
  } else {
    tagset_converter.reset(tagset_converter::new_identity_converter());
    if (!tagset_converter) runtime_errorf("Cannot create identity tag set converter!");
  }

  process_args(3, argc, argv, generate, dictionary, use_guesser, *tagset_converter);

  return 0;
}

void generate(FILE* in, FILE* out, const morpho& dictionary, bool use_guesser, const tagset_converter& tagset_converter) {
  string line;
  vector<tagged_lemma_forms> forms;

  while (getline(in, line)) {
    if (!line.empty()) {
      string_piece lemma = line;
      const char* wildcard = nullptr;

      string::size_type space = line.find('\t');
      if (space != string::npos) {
        lemma.len = space;
        wildcard = line.c_str() + space + 1;
      }

      dictionary.generate(lemma, wildcard, use_guesser ? morpho::GUESSER : morpho::NO_GUESSER, forms);
      tagset_converter.convert_generated(forms);

      bool first = true;
      for (auto&& lemma : forms)
        for (auto&& form : lemma.forms) {
          if (!first) fputc('\t', out);
          fprintf(out, "%s\t%s\t%s", form.form.c_str(), lemma.lemma.c_str(), form.tag.c_str());
          first = false;
        }
    }
    fputc('\n', out);
  }
}
<commit_msg>Avoid clang-3.5 compile error by disambiguating generate method.<commit_after>// This file is part of MorphoDiTa.
//
// Copyright 2013 by Institute of Formal and Applied Linguistics, Faculty of
// Mathematics and Physics, Charles University in Prague, Czech Republic.
//
// MorphoDiTa is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// MorphoDiTa 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 MorphoDiTa.  If not, see <http://www.gnu.org/licenses/>.

#include <memory>

#include "morpho/morpho.h"
#include "tagger/tagger.h"
#include "tagset_converter/tagset_converter.h"
#include "utils/input.h"
#include "utils/parse_int.h"
#include "utils/parse_options.h"
#include "utils/process_args.h"

using namespace ufal::morphodita;

static void generate_vertical(FILE* in, FILE* out, const morpho& dictionary, bool use_guesser, const tagset_converter& tagset_converter);

int main(int argc, char* argv[]) {
  show_version_if_requested(argc, argv);

  options_map options;
  if (!parse_options({{"convert_tagset",option_values::any},
                      {"from_tagger",option_values::none}}, argc, argv, options) ||
      argc < 3)
    runtime_errorf("Usage: %s [options] dict_file use_guesser [file[:output_file]]...\n"
                   "Options: --convert_tagset=pdt_to_conll2009|strip_lemma_comment|strip_lemma_id\n"
                   "         --from_tagger", argv[0]);

  unique_ptr<morpho> morpho;
  unique_ptr<tagger> tagger;
  if (options.count("from_tagger")) {
    eprintf("Loading dictionary from tagger: ");
    tagger.reset(tagger::load(argv[1]));
    if (!tagger) runtime_errorf("Cannot load tagger from file '%s'!", argv[1]);
  } else {
    eprintf("Loading dictionary: ");
    morpho.reset(morpho::load(argv[1]));
    if (!morpho) runtime_errorf("Cannot load dictionary from file '%s'!", argv[1]);
  }
  eprintf("done\n");
  auto& dictionary = options.count("from_tagger") ? *tagger->get_morpho() : *morpho;

  bool use_guesser = parse_int(argv[2], "use_guesser");

  unique_ptr<tagset_converter> tagset_converter;
  if (options.count("convert_tagset")) {
    tagset_converter.reset(new_tagset_converter(options["convert_tagset"], dictionary));
    if (!tagset_converter) runtime_errorf("Unknown tag set converter '%s'!", options["convert_tagset"].c_str());
  } else {
    tagset_converter.reset(tagset_converter::new_identity_converter());
    if (!tagset_converter) runtime_errorf("Cannot create identity tag set converter!");
  }

  process_args(3, argc, argv, generate_vertical, dictionary, use_guesser, *tagset_converter);

  return 0;
}

void generate_vertical(FILE* in, FILE* out, const morpho& dictionary, bool use_guesser, const tagset_converter& tagset_converter) {
  string line;
  vector<tagged_lemma_forms> forms;

  while (getline(in, line)) {
    if (!line.empty()) {
      string_piece lemma = line;
      const char* wildcard = nullptr;

      string::size_type space = line.find('\t');
      if (space != string::npos) {
        lemma.len = space;
        wildcard = line.c_str() + space + 1;
      }

      dictionary.generate(lemma, wildcard, use_guesser ? morpho::GUESSER : morpho::NO_GUESSER, forms);
      tagset_converter.convert_generated(forms);

      bool first = true;
      for (auto&& lemma : forms)
        for (auto&& form : lemma.forms) {
          if (!first) fputc('\t', out);
          fprintf(out, "%s\t%s\t%s", form.form.c_str(), lemma.lemma.c_str(), form.tag.c_str());
          first = false;
        }
    }
    fputc('\n', out);
  }
}
<|endoftext|>


<commit_before>
#include "veraMolnarTrapezium.h"

void veraMolnarTrapezium::setup(){

	iCenterX = 0;
	iCenterY = 1;
	iTopLeftOffsetX = 2;
	iTopRightOffsetX = 3;
	iBottomLeftOffsetX = 4;
	iBottomRightOffsetX = 5;

// setup pramaters
//    param.set("param", 5, 0, 100);
//    parameters.add(param);
	spacingPercent.set("spacingPercent", 1.2, 0, 10);
	spacingPercentX.set("spacingPercentX", 1.2, 0, 10);
	spacingPercentY.set("spacingPercentY", 1.2, 0, 10);
	unifiedSpacing.set("unifiedSpacing", true);
	whiteBackground.set("whiteBackground", false);
	numWide.set("numWide", 9, 1, 100);
	baseSize.set("baseSize", dimensions.width/spacingPercent/(numWide+2), 10, dimensions.width);
	cornerNoise.set("cornerNoise", 0., 0., 1.);
	centerNoise.set("centerNoise", 0., 0., 1.);

	parameters.add(baseSize);
	parameters.add(spacingPercent);
	parameters.add(unifiedSpacing);
	parameters.add(spacingPercentX);
	parameters.add(spacingPercentY);
	parameters.add(numWide);
	parameters.add(cornerNoise);
	parameters.add(centerNoise);
	parameters.add(whiteBackground);

    loadCode("veraMolnarTrapezium/exampleCode.cpp");
}

void veraMolnarTrapezium::update(){
	if (unifiedSpacing){
		spacingPercentX = spacingPercent;
		spacingPercentY = spacingPercent;
	}
    while(placements.size() < numWide*numWide){
		//centerX, centerY,
		//topLeftOffsetX, topRightOffsetX,
		//bottomLeftOffsetX, bottomRightOffsetX
		placements.push_back({
			ofRandom(0, 1),
			ofRandom(0, 1),
			ofRandom(-1, 1),
			ofRandom(-1, 1),
			ofRandom(-1, 1),
			ofRandom(-1, 1)});
	}
}

void veraMolnarTrapezium::draw(){
	if (whiteBackground){
		ofBackground(255);
		ofSetColor(0);
	} else {
		ofBackground(0);
		ofSetColor(255);
	}
	for(int row = 0; row < numWide; row++){
		for(int column = 0; column < numWide; column++){
			drawTrapezium(row, column);
		}
	}
}

void veraMolnarTrapezium::drawTrapezium(int row, int column){
	float spacingX, spacingY;
	if (unifiedSpacing){
		spacingX = spacingY = baseSize * spacingPercent;
	} else {
		spacingX = baseSize * spacingPercentX;
		spacingY = baseSize * spacingPercentY;
	}
	int index = row * numWide + column;
	float gridLeft = (dimensions.width - numWide * spacingX) / 2;
	float gridTop = (dimensions.height - numWide * spacingY) / 2;

	float leftmostCenter = gridLeft + spacingX / 2;
	float rightmostCenter = leftmostCenter + (numWide - 1) * spacingX;
	float topmostCenter = gridTop + spacingY / 2;
	float bottommostCenter = topmostCenter + (numWide - 1) * spacingY;

	float startCenterX = leftmostCenter + column * spacingX;
	float startCenterY = topmostCenter + row * spacingY;
	float centerSpanX = (rightmostCenter - leftmostCenter);
	float centerSpanY = (bottommostCenter - topmostCenter);
	float targetCenterX = centerSpanX * placements[index][iCenterX] + leftmostCenter;
	float targetCenterY = centerSpanY * placements[index][iCenterY] + leftmostCenter;

	float centerX =
		startCenterX * (1. - centerNoise) +
		targetCenterX * centerNoise;
	float centerY =
		startCenterY * (1. - centerNoise) +
		targetCenterY * centerNoise;

	float top = centerY - baseSize / 2;
	float bottom = centerY + baseSize / 2;
	float left = centerX - baseSize / 2;
	float right = centerX + baseSize / 2;

	float cornerMagnitude = cornerNoise * baseSize;
	ofVec2f topLeft = ofVec2f(top, left);
	topLeft.x += placements[index][iTopLeftOffsetX] * cornerMagnitude;
	ofVec2f topRight = ofVec2f(top, right);
	topRight.x += placements[index][iTopRightOffsetX] * cornerMagnitude;
	ofVec2f bottomRight = ofVec2f(bottom, right);
	bottomRight.x += placements[index][iBottomRightOffsetX] * cornerMagnitude;
	ofVec2f bottomLeft = ofVec2f(bottom, left);
	bottomLeft.x += placements[index][iBottomLeftOffsetX] * cornerMagnitude;

	ofDrawLine(topLeft.x, topLeft.y, topRight.x, topRight.y);
	ofDrawLine(topRight.x, topRight.y, bottomRight.x, bottomRight.y);
	ofDrawLine(bottomRight.x, bottomRight.y, bottomLeft.x, bottomLeft.y);
	ofDrawLine(bottomLeft.x, bottomLeft.y, topLeft.x, topLeft.y);
}
<commit_msg>fixing some spacing bug.<commit_after>
#include "veraMolnarTrapezium.h"

void veraMolnarTrapezium::setup(){

	iCenterX = 0;
	iCenterY = 1;
	iTopLeftOffsetX = 2;
	iTopRightOffsetX = 3;
	iBottomLeftOffsetX = 4;
	iBottomRightOffsetX = 5;

// setup pramaters
//    param.set("param", 5, 0, 100);
//    parameters.add(param);
	spacingPercent.set("spacingPercent", 1.2, 0, 10);
	spacingPercentX.set("spacingPercentX", 1.2, 0, 10);
	spacingPercentY.set("spacingPercentY", 1.2, 0, 10);
	unifiedSpacing.set("unifiedSpacing", true);
	whiteBackground.set("whiteBackground", false);
	numWide.set("numWide", 9, 1, 100);
	baseSize.set("baseSize", dimensions.width/spacingPercent/(numWide+2), 10, dimensions.width);
	cornerNoise.set("cornerNoise", 0., 0., 1.);
	centerNoise.set("centerNoise", 0., 0., 1.);

	parameters.add(baseSize);
	parameters.add(spacingPercent);
	parameters.add(unifiedSpacing);
	parameters.add(spacingPercentX);
	parameters.add(spacingPercentY);
	parameters.add(numWide);
	parameters.add(cornerNoise);
	parameters.add(centerNoise);
	parameters.add(whiteBackground);

    loadCode("veraMolnarTrapezium/exampleCode.cpp");
}

void veraMolnarTrapezium::update(){
	if (unifiedSpacing){
		spacingPercentX = spacingPercent;
		spacingPercentY = spacingPercent;
	}
    while(placements.size() < numWide*numWide){
		//centerX, centerY,
		//topLeftOffsetX, topRightOffsetX,
		//bottomLeftOffsetX, bottomRightOffsetX
		placements.push_back({
			ofRandom(0, 1),
			ofRandom(0, 1),
			ofRandom(-1, 1),
			ofRandom(-1, 1),
			ofRandom(-1, 1),
			ofRandom(-1, 1)});
	}
}

void veraMolnarTrapezium::draw(){
	if (whiteBackground){
		ofBackground(255);
		ofSetColor(0);
	} else {
		ofBackground(0);
		ofSetColor(255);
	}
	for(int row = 0; row < numWide; row++){
		for(int column = 0; column < numWide; column++){
			drawTrapezium(row, column);
		}
	}
}

void veraMolnarTrapezium::drawTrapezium(int row, int column){
	float spacingX, spacingY;
	if (unifiedSpacing){
		spacingX = spacingY = baseSize * spacingPercent;
	} else {
		spacingX = baseSize * spacingPercentX;
		spacingY = baseSize * spacingPercentY;
	}
	int index = row * numWide + column;
	float gridLeft = (dimensions.width - numWide * spacingX) / 2;
	float gridTop = (dimensions.height - numWide * spacingY) / 2;

	float leftmostCenter = gridLeft + spacingX / 2;
	float rightmostCenter = leftmostCenter + (numWide - 1) * spacingX;
	float topmostCenter = gridTop + spacingY / 2;
	float bottommostCenter = topmostCenter + (numWide - 1) * spacingY;

	float startCenterX = leftmostCenter + column * spacingX;
	float startCenterY = topmostCenter + row * spacingY;
	float centerSpanX = (rightmostCenter - leftmostCenter);
	float centerSpanY = (bottommostCenter - topmostCenter);
	float targetCenterX = centerSpanX * placements[index][iCenterX] + leftmostCenter;
	float targetCenterY = centerSpanY * placements[index][iCenterY] + topmostCenter;

	float centerX =
		startCenterX * (1. - centerNoise) +
		targetCenterX * centerNoise;
	float centerY =
		startCenterY * (1. - centerNoise) +
		targetCenterY * centerNoise;

	float top = centerY - baseSize / 2;
	float bottom = centerY + baseSize / 2;
	float left = centerX - baseSize / 2;
	float right = centerX + baseSize / 2;

	float cornerMagnitude = cornerNoise * baseSize;
	ofVec2f topLeft = ofVec2f(top, left);
	topLeft.x += placements[index][iTopLeftOffsetX] * cornerMagnitude;
	ofVec2f topRight = ofVec2f(top, right);
	topRight.x += placements[index][iTopRightOffsetX] * cornerMagnitude;
	ofVec2f bottomRight = ofVec2f(bottom, right);
	bottomRight.x += placements[index][iBottomRightOffsetX] * cornerMagnitude;
	ofVec2f bottomLeft = ofVec2f(bottom, left);
	bottomLeft.x += placements[index][iBottomLeftOffsetX] * cornerMagnitude;

	ofDrawLine(topLeft.x, topLeft.y, topRight.x, topRight.y);
	ofDrawLine(topRight.x, topRight.y, bottomRight.x, bottomRight.y);
	ofDrawLine(bottomRight.x, bottomRight.y, bottomLeft.x, bottomLeft.y);
	ofDrawLine(bottomLeft.x, bottomLeft.y, topLeft.x, topLeft.y);
}
<|endoftext|>