<commit_before>// Halide tutorial lesson 20: Cloning Funcs

// This lesson demonstrates how to use Func::clone_in to create a clone of
// a Func.

// On linux, you can compile and run it like so:
// g++ lesson_20*.cpp -g -I ../include -L ../bin -lHalide -lpthread -ldl -o lesson_20 -std=c++11
// LD_LIBRARY_PATH=../bin ./lesson_20

// On os x:
// g++ lesson_20*.cpp -g -I ../include -L ../bin -lHalide -o lesson_20 -std=c++11
// DYLD_LIBRARY_PATH=../bin ./lesson_20

// If you have the entire Halide source tree, you can also build it by
// running:
//    make tutorial_lesson_20_cloning_funcs
// in a shell at the top of the halide source tree.

// The only Halide header file you need is Halide.h. It includes all of Halide.
#include "Halide.h"

// We'll also include stdio for printf.
#include <stdio.h>

using namespace Halide;

int main(int argc, char **argv) {
    // First we'll declare some Vars to use below.
    Var x("x"), y("y"), xo("xo"), yo("yo"), xi("xi"), yi("yi");

    // This lesson will be about cloning a Func using the Func::clone_in
    // directive
    {
        // Consider a simple two-stage pipeline:
        Func f("f_single"), g("g_single"), h("h_single");
        f(x, y) = x + y;
        g(x, y) = 2 * f(x, y) + 3;
        h(x, y) = f(x, y) + g(x, y) + 10;

        f.compute_root();
        g.compute_root();
        h.compute_root();

        // This produces the following loop nests:
        // for y:
        //   for x:
        //     f(x, y) = x + y
        // for y:
        //   for x:
        //     g(x, y) = 2 * f(x, y) + 3
        // for y:
        //   for x:
        //     h(x, y) = f(x, y) + g(x, y) + 10

        // Using Func::clone, we can replace calls to 'f' inside 'g' with
        // a clone of 'f' using the schedule alone:
        Func f_clone_in_g = f.clone_in(g);
        f_clone_in_g.compute_root();

        // Equivalently, we could also chain the schedules like so:
        // f.clone_in(g).compute_root();

        // This produces the following loop nests:
        // for y:
        //   for x:
        //     f(x, y) = x + y
        // for y:
        //   for x:
        //     f_clone_in_g(x, y) = x + y
        // for y:
        //   for x:
        //     g(x, y) = 2 * f_clone_in_g(x, y) + 3
        // for y:
        //   for x:
        //     h(x, y) = f(x, y) + g(x, y) + 10

        h.realize(5, 5);

        // The schedule directive f.clone_in(g) replaces all calls to 'f'
        // inside 'g' with a clone of 'f' and then returns that clone.
        // Essentially, it rewrites the original pipeline above into the
        // following:
        {
            Func f_clone_in_g("f_clone_in_g"), f("f"), g("g"), h("h");
            f(x, y) = x + y;
            f_clone_in_g(x, y) = x + y;
            g(x, y) = 2 * f_clone_in_g(x, y) + 3;
            h(x, y) = f(x, y) + g(x, y) + 10;

            f.compute_root();
            f_clone_in_g.compute_root();
            g.compute_root();
            h.compute_root();
        }
    }

    {
        // In the schedule above, only the calls to 'f' made by 'g' are
        // replaced. Other calls made to 'f' would still call 'f' directly
        // (i.e. 'h' still calls 'f' and not the clone). If we wish to
        // replace all calls to 'f' made by both 'g' and 'h' with a single
        // clone, we simply say f.clone_in({g, h}).

        // Consider a three stage pipeline, with two consumers of f:
        Func f("f_group"), g("g_group"), h("h_group"), out("out_group");
        f(x, y) = x + y;
        g(x, y) = 2 * f(x, y);
        h(x, y) = f(x, y) + 10;
        out(x, y) = f(x, y) + g(x, y) + h(x, y);

        f.compute_root();
        g.compute_root();
        h.compute_root();
        out.compute_root();

        // We will replace all calls to 'f' inside both 'g' and 'h'
        // with calls to a single clone:
        f.clone_in({g, h}).compute_root();

        // The equivalent loop nests are:
        // for y:
        //   for x:
        //     f(x, y) = x + y
        // for y:
        //   for x:
        //     f_clone(x, y) = x + y
        // for y:
        //   for x:
        //     g(x, y) = 2 * f_clone(x, y)
        // for y:
        //   for x:
        //     h(x, y) = f_clone(x, y) + 10
        // for y:
        //   for x:
        //     out(x, y) = f(x, y) + g(x, y) + h(x, y)

        out.realize(5, 5);
    }

    {
        // One use case of Func::clone_in() is when two consumers of a producer
        // consume regions of the producer that are very disjoint. Consider
        // the following case for example:
        Func f("f"), g("g"), h("h");
        f(x) = x;
        g(x) = 2 * f(0);
        h(x) = f(99) + 10;

        // Let's schedule 'f' to be computed at root.
        f.compute_root();
        // Since both 'g' and 'h' consumes 'f', the region required of 'f'
        // in the x-dimension is [0, 99]. The equivalent loop nests are:
        // for x = 0 to 99
        //   f(x) = x
        // for x:
        //   g(x) = 2 * f(0)
        // for x:
        //   h(x) = f(99) + 10

        // If 'f' had been very expensive to compute, we might be beter off
        // with having two copies of 'f' for each consumer, 'g' and 'h', to
        // avoid unnecessary computations. To create separate copies of 'f'
        // for each consumer, we can do the following:
        f.clone_in(g).compute_root();

        // The equivalent loop nests are:
        // f(0) = x
        // f_clone(99) = x
        // for x:
        //   g(x) = 2 * f_clone(0)
        // for x:
        //   h(x) = f(99) + 10
    }

    printf("Success!\n");

    return 0;
}
<commit_msg>Fix typos in clone_in tutorial<commit_after>// Halide tutorial lesson 20: Cloning Funcs

// This lesson demonstrates how to use Func::clone_in to create a clone of
// a Func.

// On linux, you can compile and run it like so:
// g++ lesson_20*.cpp -g -I ../include -L ../bin -lHalide -lpthread -ldl -o lesson_20 -std=c++11
// LD_LIBRARY_PATH=../bin ./lesson_20

// On os x:
// g++ lesson_20*.cpp -g -I ../include -L ../bin -lHalide -o lesson_20 -std=c++11
// DYLD_LIBRARY_PATH=../bin ./lesson_20

// If you have the entire Halide source tree, you can also build it by
// running:
//    make tutorial_lesson_20_cloning_funcs
// in a shell at the top of the halide source tree.

// The only Halide header file you need is Halide.h. It includes all of Halide.
#include "Halide.h"

// We'll also include stdio for printf.
#include <stdio.h>

using namespace Halide;

int main(int argc, char **argv) {
    // First we'll declare some Vars to use below.
    Var x("x"), y("y"), xo("xo"), yo("yo"), xi("xi"), yi("yi");

    // This lesson will be about cloning a Func using the Func::clone_in
    // directive
    {
        // Consider a simple two-stage pipeline:
        Func f("f_single"), g("g_single"), h("h_single");
        f(x, y) = x + y;
        g(x, y) = 2 * f(x, y) + 3;
        h(x, y) = f(x, y) + g(x, y) + 10;

        f.compute_root();
        g.compute_root();
        h.compute_root();

        // This produces the following loop nests:
        // for y:
        //   for x:
        //     f(x, y) = x + y
        // for y:
        //   for x:
        //     g(x, y) = 2 * f(x, y) + 3
        // for y:
        //   for x:
        //     h(x, y) = f(x, y) + g(x, y) + 10

        // Using Func::clone, we can replace calls to 'f' inside 'g' with
        // a clone of 'f' using the schedule alone:
        Func f_clone_in_g = f.clone_in(g);
        f_clone_in_g.compute_root();

        // Equivalently, we could also chain the schedules like so:
        // f.clone_in(g).compute_root();

        // This produces the following loop nests:
        // for y:
        //   for x:
        //     f(x, y) = x + y
        // for y:
        //   for x:
        //     f_clone_in_g(x, y) = x + y
        // for y:
        //   for x:
        //     g(x, y) = 2 * f_clone_in_g(x, y) + 3
        // for y:
        //   for x:
        //     h(x, y) = f(x, y) + g(x, y) + 10

        h.realize(5, 5);

        // The schedule directive f.clone_in(g) replaces all calls to 'f'
        // inside 'g' with a clone of 'f' and then returns that clone.
        // Essentially, it rewrites the original pipeline above into the
        // following:
        {
            Func f_clone_in_g("f_clone_in_g"), f("f"), g("g"), h("h");
            f(x, y) = x + y;
            f_clone_in_g(x, y) = x + y;
            g(x, y) = 2 * f_clone_in_g(x, y) + 3;
            h(x, y) = f(x, y) + g(x, y) + 10;

            f.compute_root();
            f_clone_in_g.compute_root();
            g.compute_root();
            h.compute_root();
        }
    }

    {
        // In the schedule above, only the calls to 'f' made by 'g' are
        // replaced. Other calls made to 'f' would still call 'f' directly
        // (i.e. 'h' still calls 'f' and not the clone). If we wish to
        // replace all calls to 'f' made by both 'g' and 'h' with a single
        // clone, we simply say f.clone_in({g, h}).

        // Consider a three stage pipeline, with two consumers of f:
        Func f("f_group"), g("g_group"), h("h_group"), out("out_group");
        f(x, y) = x + y;
        g(x, y) = 2 * f(x, y);
        h(x, y) = f(x, y) + 10;
        out(x, y) = f(x, y) + g(x, y) + h(x, y);

        f.compute_root();
        g.compute_root();
        h.compute_root();
        out.compute_root();

        // We will replace all calls to 'f' inside both 'g' and 'h'
        // with calls to a single clone:
        f.clone_in({g, h}).compute_root();

        // The equivalent loop nests are:
        // for y:
        //   for x:
        //     f(x, y) = x + y
        // for y:
        //   for x:
        //     f_clone(x, y) = x + y
        // for y:
        //   for x:
        //     g(x, y) = 2 * f_clone(x, y)
        // for y:
        //   for x:
        //     h(x, y) = f_clone(x, y) + 10
        // for y:
        //   for x:
        //     out(x, y) = f(x, y) + g(x, y) + h(x, y)

        out.realize(5, 5);
    }

    {
        // One use case of Func::clone_in() is when two consumers of a producer
        // consume regions of the producer that are very disjoint. Consider
        // the following case for example:
        Func f("f"), g("g"), h("h");
        f(x) = x;
        g(x) = 2 * f(0);
        h(x) = f(99) + 10;

        // Let's schedule 'f' to be computed at root.
        f.compute_root();
        // Since both 'g' and 'h' consume 'f', the region required of 'f'
        // in the x-dimension is [0, 99]. The equivalent loop nests are:
        // for x = 0 to 99
        //   f(x) = x
        // for x:
        //   g(x) = 2 * f(0)
        // for x:
        //   h(x) = f(99) + 10

        // If 'f' is very expensive to compute, we might be better off with
        // having distinct copies of 'f' for each consumer, 'g' and 'h', to
        // avoid unnecessary computations. To create separate copies of 'f'
        // for each consumer, we can do the following:
        f.clone_in(g).compute_root();

        // The equivalent loop nests are:
        // f(0) = x
        // f_clone(99) = x
        // for x:
        //   g(x) = 2 * f_clone(0)
        // for x:
        //   h(x) = f(99) + 10
    }

    printf("Success!\n");

    return 0;
}
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include "catch.hpp"
#include "EasyRandom.hpp"
#include <limits>

using namespace EasyRandom;

TEST_CASE( "Test random random" ) {
    const auto firstRandomNumber = Random::get( std::numeric_limits<std::intmax_t>::min( ),
                                                std::numeric_limits<std::intmax_t>::max( ) );

    const auto secondRandomNumber = Random::get( std::numeric_limits<std::intmax_t>::min( ),
                                                 std::numeric_limits<std::intmax_t>::max( ) );

    CHECK( firstRandomNumber != secondRandomNumber );
}

TEST_CASE( "Test range" ) {
    for( std::uint8_t i{ 0u }; i < std::numeric_limits<std::uint8_t>::max( ); ++i ) {
        const auto randomNumber = Random::get( -1, 1 );
        REQUIRE( randomNumber >= -1 );
        REQUIRE( randomNumber <= 1 );
    }

    for( std::uint8_t i{ 0u }; i < std::numeric_limits<std::uint8_t>::max( ); ++i ) {
        const auto randomNumber = Random::get( 1, -1 );
        REQUIRE( randomNumber >= -1 );
        REQUIRE( randomNumber <= 1 );
    }

    const auto randomNumber = Random::get( 1, 1 );

    REQUIRE( 1 == randomNumber );
}

TEST_CASE( "Test type deduction" ) {
    static_assert( std::is_same<int, decltype( Random::get( -10, 10 ) )>::value, "" );
    static_assert( std::is_same<unsigned, decltype( Random::get( 10u, 10u ) )>::value, "" );
    static_assert( std::is_same<long, decltype( Random::get( 10, 10l ) )>::value, "" );
    static_assert( std::is_same<long long, decltype( Random::get( 10ll , 10l ) ) >::value, "" );
    static_assert( std::is_same<unsigned long long, decltype( Random::get( 10llu, 10lu ) ) >::value, "" );
    static_assert( std::is_same<short, decltype( Random::get<short, short>( 10llu, 10lu ) ) >::value, "" );
    static_assert( std::is_same<unsigned short,
                   decltype( Random::get<unsigned short, unsigned short>( 10llu, 10lu ) ) >::value, "" );
}<commit_msg>Add tests for real numbers<commit_after>#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include "catch.hpp"
#include "EasyRandom.hpp"
#include <limits>

using namespace EasyRandom;

TEST_CASE( "Test random random integer" ) {
    const auto firstRandomNumber = Random::get( std::numeric_limits<std::intmax_t>::min( ),
                                                std::numeric_limits<std::intmax_t>::max( ) );

    const auto secondRandomNumber = Random::get( std::numeric_limits<std::intmax_t>::min( ),
                                                 std::numeric_limits<std::intmax_t>::max( ) );

    CHECK( firstRandomNumber != secondRandomNumber );
}

TEST_CASE( "Test range integer" ) {
    for( std::uint8_t i{ 0u }; i < std::numeric_limits<std::uint8_t>::max( ); ++i ) {
        const auto randomNumber = Random::get( -1, 1 );
        REQUIRE( randomNumber >= -1 );
        REQUIRE( randomNumber <= 1 );
    }

    for( std::uint8_t i{ 0u }; i < std::numeric_limits<std::uint8_t>::max( ); ++i ) {
        const auto randomNumber = Random::get( 1, -1 );
        REQUIRE( randomNumber >= -1 );
        REQUIRE( randomNumber <= 1 );
    }

    const auto randomNumber = Random::get( 1, 1 );

    REQUIRE( 1 == randomNumber );
}

TEST_CASE( "Test type deduction integer" ) {
    static_assert( std::is_same<int, decltype( Random::get( -10, 10 ) )>::value, "" );
    static_assert( std::is_same<unsigned, decltype( Random::get( 10u, 10u ) )>::value, "" );
    static_assert( std::is_same<long, decltype( Random::get( 10, 10l ) )>::value, "" );
    static_assert( std::is_same<long long, decltype( Random::get( 10ll , 10l ) ) >::value, "" );
    static_assert( std::is_same<unsigned long long, decltype( Random::get( 10llu, 10lu ) ) >::value, "" );
    static_assert( std::is_same<short, decltype( Random::get<short, short>( 10llu, 10lu ) ) >::value, "" );
    static_assert( std::is_same<unsigned short,
                   decltype( Random::get<unsigned short, unsigned short>( 10llu, 10lu ) ) >::value, "" );
}

TEST_CASE( "Test random random real" ) {
    const auto firstRandomNumber = Random::get( std::numeric_limits<long double>::min( ),
                                                std::numeric_limits<long double>::max( ) );

    const auto secondRandomNumber = Random::get( std::numeric_limits<long double>::min( ),
                                                 std::numeric_limits<long double>::max( ) );

    CHECK( firstRandomNumber != secondRandomNumber );
}

TEST_CASE( "Test range real" ) {
    for( std::uint8_t i{ 0u }; i < std::numeric_limits<std::uint8_t>::max( ); ++i ) {
        const auto randomNumber = Random::get( -1.f, 1.f );
        REQUIRE( randomNumber >= -1.f );
        REQUIRE( randomNumber <= 1.f );
    }

    for( std::uint8_t i{ 0u }; i < std::numeric_limits<std::uint8_t>::max( ); ++i ) {
        const auto randomNumber = Random::get( 1., -1. );
        REQUIRE( randomNumber >= -1. );
        REQUIRE( randomNumber <= 1. );
    }

    for( std::uint8_t i{ 0u }; i < std::numeric_limits<std::uint8_t>::max( ); ++i ) {
        const auto randomNumber = Random::get( 1.l, -1.l );
        REQUIRE( randomNumber >= -1.l );
        REQUIRE( randomNumber <= 1.l );
    }

    const auto randomNumber = Random::get( 1.f, 1.l );

    REQUIRE( 1.l == randomNumber );
}

TEST_CASE( "Test type deduction real" ) {
    static_assert( std::is_same<double, decltype( Random::get( 10., 10. ) )>::value, "" );
    static_assert( std::is_same<long double, decltype( Random::get( 10.l, 10.l ) )>::value, "" );
    static_assert( std::is_same<float, decltype( Random::get( 10.f, 10.f ) )>::value, "" );
    static_assert( std::is_same<double, decltype( Random::get( 10.f, 10. ) ) >::value, "" );
    static_assert( std::is_same<long double, decltype( Random::get( 10.l, 10.f ) ) >::value, "" );
    static_assert( std::is_same<short, decltype( Random::get<short, short>( 10llu, 10lu ) ) >::value, "" );
}
<|endoftext|>


<commit_before>#include "Maze.hpp"
#include "chimera/core/Exception.hpp"
#include <string>

Maze::Maze(const char filename[]) {

    FILE* file;
    char string[1024];

    file = fopen(filename, "rb");
    if (!file) {
        throw Chimera::Exception(std::string("Arguivo nao localizado"));
    }

    // tamanho do mapa
    fgets(string, 1024, file);
    this->width = atoi(string);

    fgets(string, 1024, file);
    this->height = atoi(string);

    // carregando mapa
    for (uint32_t h = 0; h < this->height; h++) {
        fgets(string, 1024, file);
        for (uint32_t w = 0; w < this->width; w++) {
            int indice = w + (h * this->width);
            if (string[w] == 0x20) {
                // Bloco Vazio
                this->data.push_back(0); // this->data[indice] = 0;
            } else {
                // parede (conversão ASCII completa)
                uint8_t val = (uint8_t)(string[w] - 0x30);
                this->data.push_back(val); // this->data[indice] = val;
            }
        }
    }
}

Maze::~Maze() { this->data.clear(); }

uint32_t Maze::getIndexVal(uint32_t w, uint32_t h) { return w + (h * this->width); }

void Maze::newWall(CARDINAL cardinal, uint32_t w, uint32_t h) {

    uint8_t val_target = 0;
    std::vector<Chimera::VertexData> vl;

    float sizeBlock = 10.0f;

    float y_max = sizeBlock / 2; // Altura Maxima
    float y_min = -y_max;        // Altura Minima

    float halfSizeX = (this->width * sizeBlock) / 2.0f;
    float halfSizeZ = (this->height * sizeBlock) / 2.0f;

    // float x_max; // para East  (width++)
    // float x_min; // para Oest  (width++)
    // float z_max; // para South (height++)
    // float z_min; // para North (height--)

    switch (cardinal) {
        case CARDINAL::NORTH:
            if (h != 0) {
                val_target = this->data[this->getIndexVal(w, h - 1)];
                if (val_target == 1) {

                    float x_min = (w * sizeBlock) - halfSizeX;
                    float x_max = x_min + sizeBlock;
                    float z_min = ((h - 1) * halfSizeX) - halfSizeZ;
                    float z_max = z_min + sizeBlock;

                    glm::vec3 norm = glm::vec3(0.0f, 0.0f, 1.0f);
                    vl.push_back({glm::vec3(x_min, y_min, z_min), norm, glm::vec2(0, 0)}); // np0
                    vl.push_back({glm::vec3(x_max, y_min, z_min), norm, glm::vec2(1, 0)}); // np1
                    vl.push_back({glm::vec3(x_max, y_max, z_min), norm, glm::vec2(1, 1)}); // np2
                    vl.push_back({glm::vec3(x_min, y_max, z_min), norm, glm::vec2(0, 1)}); // np3
                }
            }
            break;
        case CARDINAL::EAST:
            if (w != this->width - 1) {
                val_target = this->data[this->getIndexVal(w + 1, h)];
                if (val_target == 1) {

                    float x_min = ((w + 1) * sizeBlock) - halfSizeX;
                    float x_max = x_min + sizeBlock;
                    float z_min = (h * halfSizeX) - halfSizeZ;
                    float z_max = z_min + sizeBlock;

                    glm::vec3 norm = glm::vec3(1.0f, 0.0f, 0.0f);
                    vl.push_back({glm::vec3(x_max, y_min, z_min), norm, glm::vec2(0, 0)}); // ep0
                    vl.push_back({glm::vec3(x_max, y_min, z_max), norm, glm::vec2(1, 0)}); // ep1
                    vl.push_back({glm::vec3(x_max, y_max, z_max), norm, glm::vec2(1, 1)}); // ep2
                    vl.push_back({glm::vec3(x_max, y_max, z_min), norm, glm::vec2(0, 1)}); // ep3
                }
            }
            break;
        case CARDINAL::SOUTH:
            if (h != this->height - 1) {
                val_target = this->data[this->getIndexVal(w, h + 1)];
                if (val_target == 1) {

                    float x_min = (w * sizeBlock) - halfSizeX;
                    float x_max = x_min + sizeBlock;
                    float z_min = ((h + 1) * halfSizeX) - halfSizeZ;
                    float z_max = z_min + sizeBlock;

                    glm::vec3 norm = glm::vec3(0.0f, 0.0f, -1.0f);
                    vl.push_back({glm::vec3(x_min, y_min, z_max), norm, glm::vec2(0, 0)}); // np0
                    vl.push_back({glm::vec3(x_max, y_min, z_max), norm, glm::vec2(1, 0)}); // np1
                    vl.push_back({glm::vec3(x_max, y_max, z_max), norm, glm::vec2(1, 1)}); // np2
                    vl.push_back({glm::vec3(x_min, y_max, z_max), norm, glm::vec2(0, 1)}); // np3
                }
            }
            break;
        case CARDINAL::WEST:
            if (w != 0) {
                val_target = this->data[this->getIndexVal(w - 1, h)];
                if (val_target == 1) {

                    float x_min = ((w - 1) * sizeBlock) - halfSizeX;
                    float x_max = x_min + sizeBlock;
                    float z_min = (h * halfSizeX) - halfSizeZ;
                    float z_max = z_min + sizeBlock;

                    glm::vec3 norm = glm::vec3(-1.0f, 0.0f, 0.0f);
                    vl.push_back({glm::vec3(x_min, y_min, z_min), norm, glm::vec2(0, 0)}); // ep0
                    vl.push_back({glm::vec3(x_min, y_min, z_max), norm, glm::vec2(1, 0)}); // ep1
                    vl.push_back({glm::vec3(x_min, y_max, z_max), norm, glm::vec2(1, 1)}); // ep2
                    vl.push_back({glm::vec3(x_min, y_max, z_min), norm, glm::vec2(0, 1)}); // ep3
                }
            }
            break;
    }

    if (vl.size() > 0) {
        this->vertexData.push_back(vl[0]);
        this->vertexData.push_back(vl[1]);
        this->vertexData.push_back(vl[2]);
        this->vertexData.push_back(vl[2]);
        this->vertexData.push_back(vl[3]);
        this->vertexData.push_back(vl[0]);
    }
}

void Maze::createMap() {

    for (uint32_t h = 0; h < this->height; h++) {
        for (uint32_t w = 0; w < this->width; w++) {
            uint8_t val = this->data[this->getIndexVal(w, h)];
            if (val == 0) {
                for (uint8_t i = (uint8_t)CARDINAL::NORTH; i <= (uint8_t)CARDINAL::WEST; i++) {
                    this->newWall((CARDINAL)i, w, h);
                }
            }
        }
    }
}<commit_msg>corrigindo inversao de textura<commit_after>#include "Maze.hpp"
#include "chimera/core/Exception.hpp"
#include <string>

Maze::Maze(const char filename[]) {

    FILE* file;
    char string[1024];

    file = fopen(filename, "rb");
    if (!file) {
        throw Chimera::Exception(std::string("Arguivo nao localizado"));
    }

    // tamanho do mapa
    fgets(string, 1024, file);
    this->width = atoi(string);

    fgets(string, 1024, file);
    this->height = atoi(string);

    // carregando mapa
    for (uint32_t h = 0; h < this->height; h++) {
        fgets(string, 1024, file);
        for (uint32_t w = 0; w < this->width; w++) {
            int indice = w + (h * this->width);
            if (string[w] == 0x20) {
                // Bloco Vazio
                this->data.push_back(0); // this->data[indice] = 0;
            } else {
                // parede (conversão ASCII completa)
                uint8_t val = (uint8_t)(string[w] - 0x30);
                this->data.push_back(val); // this->data[indice] = val;
            }
        }
    }
}

Maze::~Maze() { this->data.clear(); }

uint32_t Maze::getIndexVal(uint32_t w, uint32_t h) { return w + (h * this->width); }

void Maze::newWall(CARDINAL cardinal, uint32_t w, uint32_t h) {

    uint8_t val_target = 0;
    std::vector<Chimera::VertexData> vl;

    float sizeBlock = 10.0f;

    float y_max = sizeBlock / 2; // Altura Maxima
    float y_min = -y_max;        // Altura Minima

    float halfSizeX = (this->width * sizeBlock) / 2.0f;
    float halfSizeZ = (this->height * sizeBlock) / 2.0f;

    // float x_max; // para East  (width++)
    // float x_min; // para Oest  (width++)
    // float z_max; // para South (height++)
    // float z_min; // para North (height--)

    switch (cardinal) {
        case CARDINAL::NORTH:
            if (h != 0) {
                val_target = this->data[this->getIndexVal(w, h - 1)];
                if (val_target == 1) {

                    float x_min = (w * sizeBlock) - halfSizeX;
                    float x_max = x_min + sizeBlock;
                    float z_min = ((h - 1) * halfSizeX) - halfSizeZ;
                    float z_max = z_min + sizeBlock;

                    glm::vec3 norm = glm::vec3(0.0f, 0.0f, 1.0f);
                    vl.push_back({glm::vec3(x_min, y_min, z_min), norm, glm::vec2(0, 0)}); // np0
                    vl.push_back({glm::vec3(x_max, y_min, z_min), norm, glm::vec2(1, 0)}); // np1
                    vl.push_back({glm::vec3(x_max, y_max, z_min), norm, glm::vec2(1, 1)}); // np2
                    vl.push_back({glm::vec3(x_min, y_max, z_min), norm, glm::vec2(0, 1)}); // np3
                }
            }
            break;
        case CARDINAL::EAST:
            if (w != this->width - 1) {
                val_target = this->data[this->getIndexVal(w + 1, h)];
                if (val_target == 1) {

                    float x_min = ((w + 1) * sizeBlock) - halfSizeX;
                    float x_max = x_min + sizeBlock;
                    float z_min = (h * halfSizeX) - halfSizeZ;
                    float z_max = z_min + sizeBlock;

                    glm::vec3 norm = glm::vec3(1.0f, 0.0f, 0.0f);
                    vl.push_back({glm::vec3(x_max, y_min, z_min), norm, glm::vec2(0, 0)}); // ep0
                    vl.push_back({glm::vec3(x_max, y_min, z_max), norm, glm::vec2(1, 0)}); // ep1
                    vl.push_back({glm::vec3(x_max, y_max, z_max), norm, glm::vec2(1, 1)}); // ep2
                    vl.push_back({glm::vec3(x_max, y_max, z_min), norm, glm::vec2(0, 1)}); // ep3
                }
            }
            break;
        case CARDINAL::SOUTH:
            if (h != this->height - 1) {
                val_target = this->data[this->getIndexVal(w, h + 1)];
                if (val_target == 1) {

                    float x_min = (w * sizeBlock) - halfSizeX;
                    float x_max = x_min + sizeBlock;
                    float z_min = ((h + 1) * halfSizeX) - halfSizeZ;
                    float z_max = z_min + sizeBlock;

                    glm::vec3 norm = glm::vec3(0.0f, 0.0f, -1.0f);
                    vl.push_back({glm::vec3(x_min, y_min, z_max), norm, glm::vec2(1, 0)}); // np0
                    vl.push_back({glm::vec3(x_max, y_min, z_max), norm, glm::vec2(0, 0)}); // np1
                    vl.push_back({glm::vec3(x_max, y_max, z_max), norm, glm::vec2(0, 1)}); // np2
                    vl.push_back({glm::vec3(x_min, y_max, z_max), norm, glm::vec2(1, 1)}); // np3
                }
            }
            break;
        case CARDINAL::WEST:
            if (w != 0) {
                val_target = this->data[this->getIndexVal(w - 1, h)];
                if (val_target == 1) {

                    float x_min = ((w - 1) * sizeBlock) - halfSizeX;
                    float x_max = x_min + sizeBlock;
                    float z_min = (h * halfSizeX) - halfSizeZ;
                    float z_max = z_min + sizeBlock;

                    glm::vec3 norm = glm::vec3(-1.0f, 0.0f, 0.0f);
                    vl.push_back({glm::vec3(x_min, y_min, z_min), norm, glm::vec2(1, 0)}); // ep0
                    vl.push_back({glm::vec3(x_min, y_min, z_max), norm, glm::vec2(0, 0)}); // ep1
                    vl.push_back({glm::vec3(x_min, y_max, z_max), norm, glm::vec2(0, 1)}); // ep2
                    vl.push_back({glm::vec3(x_min, y_max, z_min), norm, glm::vec2(1, 1)}); // ep3
                }
            }
            break;
    }

    if (vl.size() > 0) {
        this->vertexData.push_back(vl[0]);
        this->vertexData.push_back(vl[1]);
        this->vertexData.push_back(vl[2]);
        this->vertexData.push_back(vl[2]);
        this->vertexData.push_back(vl[3]);
        this->vertexData.push_back(vl[0]);
    }
}

void Maze::createMap() {

    for (uint32_t h = 0; h < this->height; h++) {
        for (uint32_t w = 0; w < this->width; w++) {
            uint8_t val = this->data[this->getIndexVal(w, h)];
            if (val == 0) {
                for (uint8_t i = (uint8_t)CARDINAL::NORTH; i <= (uint8_t)CARDINAL::WEST; i++) {
                    this->newWall((CARDINAL)i, w, h);
                }
            }
        }
    }
}<|endoftext|>


<commit_before>#include <stdio.h>
#include <algorithm>
#include "CycleTimer.h"

#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif

extern void mandelbrotSerial(
    float x0, float y0, float x1, float y1,
    int width, int height,
    int startRow, int numRows,
    int maxIterations,
    int output[]);

extern void mandelbrotThread(
    int numThreads,
    float x0, float y0, float x1, float y1,
    int width, int height,
    int maxIterations,
    int output[]);

extern void writePPMImage(
    int* data,
    int width, int height,
    const char *filename,
    int maxIterations);

void
scaleAndShift(float& x0, float& x1, float& y0, float& y1,
              float scale,
              float shiftX, float shiftY)
{

    x0 *= scale;
    x1 *= scale;
    y0 *= scale;
    y1 *= scale;
    x0 += shiftX;
    x1 += shiftX;
    y0 += shiftY;
    y1 += shiftY;

}

void usage(const char* progname) {
    printf("Usage: %s [options]\n", progname);
    printf("Program Options:\n");
    printf("  -t  --threads <N>  Use N threads\n");
    printf("  -v  --view <INT>   Use specified view settings\n");
    printf("  -?  --help         This message\n");
}

bool verifyResult (int *gold, int *result, int width, int height) {

    int i, j;

    for (i = 0; i < height; i++) {
        for (j = 0; j < width; j++) {
            if (gold[i * width + j] != result[i * width + j]) {
                printf ("Mismatch : [%d][%d], Expected : %d, Actual : %d\n",
                            i, j, gold[i * width + j], result[i * width + j]);
                return 0;
            }
        }
    }

    return 1;
-}

int main(int argc, char** argv) {

    const unsigned int width = 1200;
    const unsigned int height = 800;
    const int maxIterations = 256;
    int numThreads = 2;

    float x0 = -2;
    float x1 = 1;
    float y0 = -1;
    float y1 = 1;

    // parse commandline options ////////////////////////////////////////////

	for (int i = 1; i < argc; i++) {
		if (i < argc - 1)
		{
			if (strcmp(argv[i], "-threads") == 0 || strcmp(argv[i], "-t") == 0)
			{
				numThreads = atoi(argv[i + 1]);
			}
			else if (strcmp(argv[i], "-view") == 0 || strcmp(argv[i], "-v") == 0)
			{
				int viewIndex = atoi(argv[i + 1]);
				// change view settings
				if (viewIndex == 2) {
					float scaleValue = .015f;
					float shiftX = -.986f;
					float shiftY = .30f;
					scaleAndShift(x0, x1, y0, y1, scaleValue, shiftX, shiftY);
				}
				else if (viewIndex > 1) {
					fprintf(stderr, "Invalid view index\n");
					return 1;
				}
			}
		}
		else
		{
			if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-?") == 0)
			{
				usage(argv[0]);
				return 1;
			}
		}
    }
    // end parsing of commandline options

    int* output_serial = new int[width*height];
    int* output_thread = new int[width*height];

    //
    // Run the serial implementation.  Run the code three times and
    // take the minimum to get a good estimate.
    //
    memset(output_serial, 0, width * height * sizeof(int));
    double minSerial = 1e30;
    for (int i = 0; i < 5; ++i) {
        double startTime = CycleTimer::currentSeconds();
        mandelbrotSerial(x0, y0, x1, y1, width, height, 0, height, maxIterations, output_serial);
        double endTime = CycleTimer::currentSeconds();
        minSerial = std::min(minSerial, endTime - startTime);
    }

    printf("[mandelbrot serial]:\t\t[%.3f] ms\n", minSerial * 1000);
    writePPMImage(output_serial, width, height, "mandelbrot-serial.ppm", maxIterations);

    //
    // Run the threaded version
    //
    memset(output_thread, 0, width * height * sizeof(int));
    double minThread = 1e30;
    for (int i = 0; i < 5; ++i) {
        double startTime = CycleTimer::currentSeconds();
        mandelbrotThread(numThreads, x0, y0, x1, y1, width, height, maxIterations, output_thread);
        double endTime = CycleTimer::currentSeconds();
        minThread = std::min(minThread, endTime - startTime);
    }

    printf("[mandelbrot thread]:\t\t[%.3f] ms\n", minThread * 1000);
    writePPMImage(output_thread, width, height, "mandelbrot-thread.ppm", maxIterations);

    if (! verifyResult (output_serial, output_thread, width, height)) {
        printf ("Error : Output from threads does not match serial output\n");

        delete[] output_serial;
        delete[] output_thread;

        return 1;
    }

    // compute speedup
    printf("\t\t\t\t(%.2fx speedup from %d threads)\n", minSerial/minThread, numThreads);

    delete[] output_serial;
    delete[] output_thread;

    return 0;
}
<commit_msg>Update main.cpp<commit_after>#include <stdio.h>
#include <algorithm>
#include "CycleTimer.h"

#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif

extern void mandelbrotSerial(
    float x0, float y0, float x1, float y1,
    int width, int height,
    int startRow, int numRows,
    int maxIterations,
    int output[]);

extern void mandelbrotThread(
    int numThreads,
    float x0, float y0, float x1, float y1,
    int width, int height,
    int maxIterations,
    int output[]);

extern void writePPMImage(
    int* data,
    int width, int height,
    const char *filename,
    int maxIterations);

void
scaleAndShift(float& x0, float& x1, float& y0, float& y1,
              float scale,
              float shiftX, float shiftY)
{

    x0 *= scale;
    x1 *= scale;
    y0 *= scale;
    y1 *= scale;
    x0 += shiftX;
    x1 += shiftX;
    y0 += shiftY;
    y1 += shiftY;

}

void usage(const char* progname) {
    printf("Usage: %s [options]\n", progname);
    printf("Program Options:\n");
    printf("  -t  --threads <N>  Use N threads\n");
    printf("  -v  --view <INT>   Use specified view settings\n");
    printf("  -?  --help         This message\n");
}

bool verifyResult (int *gold, int *result, int width, int height) {

    int i, j;

    for (i = 0; i < height; i++) {
        for (j = 0; j < width; j++) {
            if (gold[i * width + j] != result[i * width + j]) {
                printf ("Mismatch : [%d][%d], Expected : %d, Actual : %d\n",
                            i, j, gold[i * width + j], result[i * width + j]);
                return 0;
            }
        }
    }

    return 1;
-}

int main(int argc, char** argv) {

    const unsigned int width = 1280;
    const unsigned int height = 960;
    const int maxIterations = 256;
    int numThreads = 2;

    float x0 = -2;
    float x1 = 1;
    float y0 = -1;
    float y1 = 1;

    // parse commandline options ////////////////////////////////////////////

	for (int i = 1; i < argc; i++) {
		if (i < argc - 1)
		{
			if (strcmp(argv[i], "-threads") == 0 || strcmp(argv[i], "-t") == 0)
			{
				numThreads = atoi(argv[i + 1]);
			}
			else if (strcmp(argv[i], "-view") == 0 || strcmp(argv[i], "-v") == 0)
			{
				int viewIndex = atoi(argv[i + 1]);
				// change view settings
				if (viewIndex == 2) {
					float scaleValue = .015f;
					float shiftX = -.986f;
					float shiftY = .30f;
					scaleAndShift(x0, x1, y0, y1, scaleValue, shiftX, shiftY);
				}
				else if (viewIndex > 1) {
					fprintf(stderr, "Invalid view index\n");
					return 1;
				}
			}
		}
		else
		{
			if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-?") == 0)
			{
				usage(argv[0]);
				return 1;
			}
		}
    }
    // end parsing of commandline options

    int* output_serial = new int[width*height];
    int* output_thread = new int[width*height];

    //
    // Run the serial implementation.  Run the code three times and
    // take the minimum to get a good estimate.
    //
    memset(output_serial, 0, width * height * sizeof(int));
    double minSerial = 1e30;
    for (int i = 0; i < 5; ++i) {
        double startTime = CycleTimer::currentSeconds();
        mandelbrotSerial(x0, y0, x1, y1, width, height, 0, height, maxIterations, output_serial);
        double endTime = CycleTimer::currentSeconds();
        minSerial = std::min(minSerial, endTime - startTime);
    }

    printf("[mandelbrot serial]:\t\t[%.3f] ms\n", minSerial * 1000);
    writePPMImage(output_serial, width, height, "mandelbrot-serial.ppm", maxIterations);

    //
    // Run the threaded version
    //
    memset(output_thread, 0, width * height * sizeof(int));
    double minThread = 1e30;
    for (int i = 0; i < 5; ++i) {
        double startTime = CycleTimer::currentSeconds();
        mandelbrotThread(numThreads, x0, y0, x1, y1, width, height, maxIterations, output_thread);
        double endTime = CycleTimer::currentSeconds();
        minThread = std::min(minThread, endTime - startTime);
    }

    printf("[mandelbrot thread]:\t\t[%.3f] ms\n", minThread * 1000);
    writePPMImage(output_thread, width, height, "mandelbrot-thread.ppm", maxIterations);

    if (! verifyResult (output_serial, output_thread, width, height)) {
        printf ("Error : Output from threads does not match serial output\n");

        delete[] output_serial;
        delete[] output_thread;

        return 1;
    }

    // compute speedup
    printf("\t\t\t\t(%.2fx speedup from %d threads)\n", minSerial/minThread, numThreads);

    delete[] output_serial;
    delete[] output_thread;

    return 0;
}
<|endoftext|>


<commit_before>/* ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2013-2015, Numenta, Inc.  Unless you have an agreement
 * with Numenta, Inc., for a separate license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program 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 Affero Public License for more details.
 *
 * You should have received a copy of the GNU Affero Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

#include <algorithm> // std::generate
#include <iostream>
#include <vector>

#include "nupic/algorithms/Anomaly.hpp"

#include "nupic/algorithms/Cells4.hpp"
#include "nupic/algorithms/BacktrackingTMCpp.hpp"
#include "nupic/algorithms/TemporalMemory.hpp"

#include "nupic/algorithms/SpatialPooler.hpp"

#include "nupic/encoders/ScalarEncoder.hpp"

#include "nupic/os/Timer.hpp"
#include "nupic/utils/VectorHelpers.hpp"
#include "nupic/utils/Random.hpp"

namespace examples {

using namespace std;
using namespace nupic;
using namespace nupic::utils;

using nupic::ScalarEncoder;

using nupic::algorithms::spatial_pooler::SpatialPooler;

using TP =     nupic::algorithms::Cells4::Cells4;
using BackTM = nupic::algorithms::backtracking_tm::BacktrackingTMCpp;
using TM =     nupic::algorithms::temporal_memory::TemporalMemory;

using nupic::algorithms::anomaly::Anomaly;
using nupic::algorithms::anomaly::AnomalyMode;

// work-load
void run(UInt EPOCHS = 5000) {
  const UInt COLS = 2048; // number of columns in SP, TP
  const UInt DIM_INPUT = 10000;
  const UInt CELLS = 10; // cells per column in TP
#ifndef NDEBUG
  EPOCHS = 2; // make test faster in Debug
#endif

  std::cout << "starting test. DIM_INPUT=" << DIM_INPUT
  		<< ", DIM=" << COLS << ", CELLS=" << CELLS << std::endl;
  std::cout << "EPOCHS = " << EPOCHS << std::endl;

  // initialize SP, TP, Anomaly, AnomalyLikelihood
  Timer tInit(true);
  ScalarEncoder enc(133, -100.0, 100.0, DIM_INPUT, 0.0, 0.0, false);
  NTA_INFO << "SP (l) local inhibition is slow, so we reduce its data 10x smaller"; //to make it reasonably fast for test, for comparison x10
  SpatialPooler spGlobal(vector<UInt>{DIM_INPUT}, vector<UInt>{COLS}); // Spatial pooler with globalInh
  SpatialPooler spLocal(vector<UInt>{DIM_INPUT}, vector<UInt>{COLS/10u}); // Spatial pooler with local inh
  spGlobal.setGlobalInhibition(true);
  spLocal.setGlobalInhibition(false);

  TP tp(COLS, CELLS, 12, 8, 15, 5, .5f, .8f, 1.0f, .1f, .1f, 0.0f,
            false, 42, true, false);
  BackTM backTM(COLS, CELLS); //TODO get all, described parameters
  TM tm(vector<UInt>{COLS}, CELLS);

  Anomaly an(5, AnomalyMode::PURE);
  Anomaly anLikelihood(5, AnomalyMode::LIKELIHOOD);
  tInit.stop();

  // data for processing input
  vector<UInt> input(DIM_INPUT);
  vector<UInt> outSP(COLS); // active array, output of SP/TP
  vector<UInt> outTP(tp.nCells());
  vector<Real> rIn(COLS); // input for TP (must be Reals)
  vector<Real> rOut(tp.nCells());
  Real res = 0.0; //for anomaly:
  vector<UInt> prevPred_(outSP.size());
  Random rnd;

  // Start a stopwatch timer
  printf("starting:  %d iterations.", EPOCHS);
  Timer tAll(true);
  Timer tRng, tEnc, tSPloc, tSPglob, tTP, tBackTM, tTM,
	tAn, tAnLikelihood;

  //run
  for (UInt e = 0; e < EPOCHS; e++) {
    //Input
//    generate(input.begin(), input.end(), [&] () { return rnd.getUInt32(2); });
    tRng.start();
    const Real r = (Real)(rnd.getUInt32(100) - rnd.getUInt32(100)*rnd.getReal64()); //rnd from range -100..100
    tRng.stop();

    //Encode
    tEnc.start();
    enc.encodeIntoArray(r, input.data());
    tEnc.stop();

    //SP (global x local)
    tSPloc.start();
    fill(outSP.begin(), outSP.end(), 0);
    spLocal.compute(input.data(), true, outSP.data());
    spLocal.stripUnlearnedColumns(outSP.data());
    tSPloc.stop();

    tSPglob.start();
    fill(outSP.begin(), outSP.end(), 0);
    spGlobal.compute(input.data(), true, outSP.data());
    spGlobal.stripUnlearnedColumns(outSP.data());
    vector<UInt> outSPsparse = VectorHelpers::binaryToSparse(outSP);
    tSPglob.stop();

    //TP (TP x BackTM x TM)
    tTP.start();
    rIn = VectorHelpers::castVectorType<UInt, Real>(outSP);
    tp.compute(rIn.data(), rOut.data(), true, true);
    outTP = VectorHelpers::castVectorType<Real, UInt>(rOut);
    tTP.stop();

    tBackTM.start();
    backTM.compute(rIn.data(), true /*learn*/, true /*infer*/);
    const auto backAct = backTM.getActiveState();
    const auto backPred = backTM.getPredictedState();
    const vector<char> vAct(backAct, backAct + backTM.getNumCells());
    const vector<char> bPred(backPred, backPred + backTM.getNumCells());
    tBackTM.stop();

    tTM.start();
    tm.compute(outSPsparse.size(), outSPsparse.data(), true /*learn*/);
    const auto tmAct = tm.getActiveCells();
    tm.activateDendrites(); //must be called before getPredictiveCells
    const auto tmPred = tm.getPredictiveCells();
    //TODO assert tmAct == spOut
    //TODO merge Act + Pred and use for anomaly from TM
    tTM.stop();

    //Anomaly (pure x likelihood)
    tAn.start();
    res = an.compute(outSP /*active*/, prevPred_ /*prev predicted*/);
    tAn.stop();

    tAnLikelihood.start();
    anLikelihood.compute(outSP /*active*/, prevPred_ /*prev predicted*/);
    tAnLikelihood.stop();

    prevPred_ = outTP; //to be used as predicted T-1

    // print
    if (e == EPOCHS - 1) {
      tAll.stop();

      cout << "Epoch = " << e << endl;
      cout << "Anomaly = " << res << endl;
      VectorHelpers::print_vector(VectorHelpers::binaryToSparse<UInt>(outSP), ",", "SP= ");
      VectorHelpers::print_vector(VectorHelpers::binaryToSparse<UInt>(VectorHelpers::cellsToColumns(outTP, CELLS)), ",", "TP= ");
      NTA_CHECK(outSP[69] == 0) << "A value in SP computed incorrectly";
      NTA_CHECK(outTP[42] == 0) << "Incorrect value in TP";
      cout << "==============TIMERS============" << endl;
      cout << "Init:\t" << tInit.getElapsed() << endl;
      cout << "Random:\t" << tRng.getElapsed() << endl;
      cout << "Encode:\t" << tEnc.getElapsed() << endl;
      cout << "SP (l):\t" << tSPloc.getElapsed() << "(x10)" << endl;
      cout << "SP (g):\t" << tSPglob.getElapsed() << endl;
      cout << "TP:\t" << tTP.getElapsed() << endl;
      cout << "TM:\t" << tTM.getElapsed() << endl;
      cout << "BackTM:\t" << tBackTM.getElapsed() << endl;
      cout << "AN:\t" << tAn.getElapsed() << endl;
      cout << "AN:\t" << tAnLikelihood.getElapsed() << endl;

      const size_t timeTotal = (size_t)floor(tAll.getElapsed());
      cout << "Total elapsed time = " << timeTotal << " seconds" << endl;
      if(EPOCHS >= 100) { //show only relevant values, ie don't run in valgrind (ndebug, epochs=5) run
#ifdef _MSC_VER
          const size_t CI_avg_time = (size_t)floor(14*Timer::getSpeed()); //sec
#else
          const size_t CI_avg_time = (size_t)floor(7*Timer::getSpeed()); //sec
#endif
        NTA_CHECK(timeTotal <= CI_avg_time) << //we'll see how stable the time result in CI is, if usable
          "HelloSPTP test slower than expected! (" << timeTotal << ",should be "<< CI_avg_time;
      }
    }
  } //end for

} //end run()
} //-ns
<commit_msg>Hotgym: bump Windows CI time check<commit_after>/* ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2013-2015, Numenta, Inc.  Unless you have an agreement
 * with Numenta, Inc., for a separate license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program 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 Affero Public License for more details.
 *
 * You should have received a copy of the GNU Affero Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

#include <algorithm> // std::generate
#include <iostream>
#include <vector>

#include "nupic/algorithms/Anomaly.hpp"

#include "nupic/algorithms/Cells4.hpp"
#include "nupic/algorithms/BacktrackingTMCpp.hpp"
#include "nupic/algorithms/TemporalMemory.hpp"

#include "nupic/algorithms/SpatialPooler.hpp"

#include "nupic/encoders/ScalarEncoder.hpp"

#include "nupic/os/Timer.hpp"
#include "nupic/utils/VectorHelpers.hpp"
#include "nupic/utils/Random.hpp"

namespace examples {

using namespace std;
using namespace nupic;
using namespace nupic::utils;

using nupic::ScalarEncoder;

using nupic::algorithms::spatial_pooler::SpatialPooler;

using TP =     nupic::algorithms::Cells4::Cells4;
using BackTM = nupic::algorithms::backtracking_tm::BacktrackingTMCpp;
using TM =     nupic::algorithms::temporal_memory::TemporalMemory;

using nupic::algorithms::anomaly::Anomaly;
using nupic::algorithms::anomaly::AnomalyMode;

// work-load
void run(UInt EPOCHS = 5000) {
  const UInt COLS = 2048; // number of columns in SP, TP
  const UInt DIM_INPUT = 10000;
  const UInt CELLS = 10; // cells per column in TP
#ifndef NDEBUG
  EPOCHS = 2; // make test faster in Debug
#endif

  std::cout << "starting test. DIM_INPUT=" << DIM_INPUT
  		<< ", DIM=" << COLS << ", CELLS=" << CELLS << std::endl;
  std::cout << "EPOCHS = " << EPOCHS << std::endl;

  // initialize SP, TP, Anomaly, AnomalyLikelihood
  Timer tInit(true);
  ScalarEncoder enc(133, -100.0, 100.0, DIM_INPUT, 0.0, 0.0, false);
  NTA_INFO << "SP (l) local inhibition is slow, so we reduce its data 10x smaller"; //to make it reasonably fast for test, for comparison x10
  SpatialPooler spGlobal(vector<UInt>{DIM_INPUT}, vector<UInt>{COLS}); // Spatial pooler with globalInh
  SpatialPooler spLocal(vector<UInt>{DIM_INPUT}, vector<UInt>{COLS/10u}); // Spatial pooler with local inh
  spGlobal.setGlobalInhibition(true);
  spLocal.setGlobalInhibition(false);

  TP tp(COLS, CELLS, 12, 8, 15, 5, .5f, .8f, 1.0f, .1f, .1f, 0.0f,
            false, 42, true, false);
  BackTM backTM(COLS, CELLS); //TODO get all, described parameters
  TM tm(vector<UInt>{COLS}, CELLS);

  Anomaly an(5, AnomalyMode::PURE);
  Anomaly anLikelihood(5, AnomalyMode::LIKELIHOOD);
  tInit.stop();

  // data for processing input
  vector<UInt> input(DIM_INPUT);
  vector<UInt> outSP(COLS); // active array, output of SP/TP
  vector<UInt> outTP(tp.nCells());
  vector<Real> rIn(COLS); // input for TP (must be Reals)
  vector<Real> rOut(tp.nCells());
  Real res = 0.0; //for anomaly:
  vector<UInt> prevPred_(outSP.size());
  Random rnd;

  // Start a stopwatch timer
  printf("starting:  %d iterations.", EPOCHS);
  Timer tAll(true);
  Timer tRng, tEnc, tSPloc, tSPglob, tTP, tBackTM, tTM,
	tAn, tAnLikelihood;

  //run
  for (UInt e = 0; e < EPOCHS; e++) {
    //Input
//    generate(input.begin(), input.end(), [&] () { return rnd.getUInt32(2); });
    tRng.start();
    const Real r = (Real)(rnd.getUInt32(100) - rnd.getUInt32(100)*rnd.getReal64()); //rnd from range -100..100
    tRng.stop();

    //Encode
    tEnc.start();
    enc.encodeIntoArray(r, input.data());
    tEnc.stop();

    //SP (global x local)
    tSPloc.start();
    fill(outSP.begin(), outSP.end(), 0);
    spLocal.compute(input.data(), true, outSP.data());
    spLocal.stripUnlearnedColumns(outSP.data());
    tSPloc.stop();

    tSPglob.start();
    fill(outSP.begin(), outSP.end(), 0);
    spGlobal.compute(input.data(), true, outSP.data());
    spGlobal.stripUnlearnedColumns(outSP.data());
    vector<UInt> outSPsparse = VectorHelpers::binaryToSparse(outSP);
    tSPglob.stop();

    //TP (TP x BackTM x TM)
    tTP.start();
    rIn = VectorHelpers::castVectorType<UInt, Real>(outSP);
    tp.compute(rIn.data(), rOut.data(), true, true);
    outTP = VectorHelpers::castVectorType<Real, UInt>(rOut);
    tTP.stop();

    tBackTM.start();
    backTM.compute(rIn.data(), true /*learn*/, true /*infer*/);
    const auto backAct = backTM.getActiveState();
    const auto backPred = backTM.getPredictedState();
    const vector<char> vAct(backAct, backAct + backTM.getNumCells());
    const vector<char> bPred(backPred, backPred + backTM.getNumCells());
    tBackTM.stop();

    tTM.start();
    tm.compute(outSPsparse.size(), outSPsparse.data(), true /*learn*/);
    const auto tmAct = tm.getActiveCells();
    tm.activateDendrites(); //must be called before getPredictiveCells
    const auto tmPred = tm.getPredictiveCells();
    //TODO assert tmAct == spOut
    //TODO merge Act + Pred and use for anomaly from TM
    tTM.stop();

    //Anomaly (pure x likelihood)
    tAn.start();
    res = an.compute(outSP /*active*/, prevPred_ /*prev predicted*/);
    tAn.stop();

    tAnLikelihood.start();
    anLikelihood.compute(outSP /*active*/, prevPred_ /*prev predicted*/);
    tAnLikelihood.stop();

    prevPred_ = outTP; //to be used as predicted T-1

    // print
    if (e == EPOCHS - 1) {
      tAll.stop();

      cout << "Epoch = " << e << endl;
      cout << "Anomaly = " << res << endl;
      VectorHelpers::print_vector(VectorHelpers::binaryToSparse<UInt>(outSP), ",", "SP= ");
      VectorHelpers::print_vector(VectorHelpers::binaryToSparse<UInt>(VectorHelpers::cellsToColumns(outTP, CELLS)), ",", "TP= ");
      NTA_CHECK(outSP[69] == 0) << "A value in SP computed incorrectly";
      NTA_CHECK(outTP[42] == 0) << "Incorrect value in TP";
      cout << "==============TIMERS============" << endl;
      cout << "Init:\t" << tInit.getElapsed() << endl;
      cout << "Random:\t" << tRng.getElapsed() << endl;
      cout << "Encode:\t" << tEnc.getElapsed() << endl;
      cout << "SP (l):\t" << tSPloc.getElapsed() << "(x10)" << endl;
      cout << "SP (g):\t" << tSPglob.getElapsed() << endl;
      cout << "TP:\t" << tTP.getElapsed() << endl;
      cout << "TM:\t" << tTM.getElapsed() << endl;
      cout << "BackTM:\t" << tBackTM.getElapsed() << endl;
      cout << "AN:\t" << tAn.getElapsed() << endl;
      cout << "AN:\t" << tAnLikelihood.getElapsed() << endl;

      const size_t timeTotal = (size_t)floor(tAll.getElapsed());
      cout << "Total elapsed time = " << timeTotal << " seconds" << endl;
      if(EPOCHS >= 100) { //show only relevant values, ie don't run in valgrind (ndebug, epochs=5) run
#ifdef _MSC_VER
          const size_t CI_avg_time = (size_t)floor(30*Timer::getSpeed()); //sec
#else
          const size_t CI_avg_time = (size_t)floor(7*Timer::getSpeed()); //sec
#endif
        NTA_CHECK(timeTotal <= CI_avg_time) << //we'll see how stable the time result in CI is, if usable
          "HelloSPTP test slower than expected! (" << timeTotal << ",should be "<< CI_avg_time;
      }
    }
  } //end for

} //end run()
} //-ns
<|endoftext|>


<commit_before>/*=============================================================================

  Library: CTK

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=============================================================================*/

#include "ctkXnatTreeBrowserMainWindow.h"
#include "ui_ctkXnatTreeBrowserMainWindow.h"

#include "ctkXnatLoginDialog.h"
#include "ctkXnatTreeModel.h"
#include "ctkXnatSession.h"
#include "ctkXnatDataModel.h"
#include "ctkXnatProject.h"
#include "ctkXnatFile.h"

#include <qDebug>

ctkXnatTreeBrowserMainWindow::ctkXnatTreeBrowserMainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::ctkXnatTreeBrowserMainWindow),
  m_Session(0),
  m_TreeModel(new ctkXnatTreeModel())
{
  ui->setupUi(this);

  ui->treeView->setModel(m_TreeModel);
  ui->downloadLabel->hide();

  this->connect(ui->loginButton, SIGNAL(clicked()), SLOT(loginButtonPushed()));
  this->connect(ui->treeView, SIGNAL(clicked(const QModelIndex&)), SLOT(itemSelected(const QModelIndex&)));
  this->connect(ui->downloadButton, SIGNAL(clicked()), SLOT(downloadButtonClicked()));
}

ctkXnatTreeBrowserMainWindow::~ctkXnatTreeBrowserMainWindow()
{
  if (m_Session)
  {
    delete m_Session;
  }
  delete ui;

  delete m_TreeModel;
}

void ctkXnatTreeBrowserMainWindow::loginButtonPushed()
{
  qDebug() << "[XNAT-TREE-VIEW] login button pushed";
  if (m_Session)
  {
    delete m_Session;
    m_Session = 0;
    ui->loginButton->setText("Login");
    ui->loginLabel->setText("Disconnected");
    ui->downloadLabel->hide();

    // nt: download tests... //
    // m_TreeModel->downloadFile (ui->treeView->selectionModel()->currentIndex(), "/Users/nicolastoussaint/Desktop/test.nii.gz");
  }
  else
  {
    ctkXnatLoginDialog loginDialog;
    if (loginDialog.exec() == QDialog::Accepted)
    {
      qDebug() << "[XNAT-TREE-VIEW] accepted settings";
      m_Session = loginDialog.session();
      if (m_Session)
      {
	qDebug() << "[XNAT-TREE-VIEW] session exists";
        ui->loginButton->setText("Logout");
        ui->loginLabel->setText(QString("Connected: %1").arg(m_Session->url().toString()));

	qDebug() << "[XNAT-TREE-VIEW] creating model";
        ctkXnatDataModel* dataModel = m_Session->dataModel();
        m_TreeModel->addDataModel(dataModel);
        ui->treeView->reset();
        ui->downloadLabel->show();
      }
    }
  }
}

void ctkXnatTreeBrowserMainWindow::itemSelected(const QModelIndex &index)
{
  ctkXnatObject* xnatObject = m_TreeModel->xnatObject(index);
  ctkXnatFile* xnatFile = dynamic_cast<ctkXnatFile*>(xnatObject);
  ui->downloadButton->setEnabled(xnatFile != 0);
  ui->downloadLabel->setVisible(!(xnatFile != 0));
}

void ctkXnatTreeBrowserMainWindow::downloadButtonClicked()
{
  const QModelIndex index = ui->treeView->selectionModel()->currentIndex();
  QVariant variant = m_TreeModel->data(index, Qt::DisplayRole);
  QString fileName = variant.value<QString>();
  if ( fileName.length() != 0 )
  {
    m_TreeModel->downloadFile(index, fileName);
  }
}
<commit_msg>removing unused qdebugs<commit_after>/*=============================================================================

  Library: CTK

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=============================================================================*/

#include "ctkXnatTreeBrowserMainWindow.h"
#include "ui_ctkXnatTreeBrowserMainWindow.h"

#include "ctkXnatLoginDialog.h"
#include "ctkXnatTreeModel.h"
#include "ctkXnatSession.h"
#include "ctkXnatDataModel.h"
#include "ctkXnatProject.h"
#include "ctkXnatFile.h"

ctkXnatTreeBrowserMainWindow::ctkXnatTreeBrowserMainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::ctkXnatTreeBrowserMainWindow),
  m_Session(0),
  m_TreeModel(new ctkXnatTreeModel())
{
  ui->setupUi(this);

  ui->treeView->setModel(m_TreeModel);
  ui->downloadLabel->hide();

  this->connect(ui->loginButton, SIGNAL(clicked()), SLOT(loginButtonPushed()));
  this->connect(ui->treeView, SIGNAL(clicked(const QModelIndex&)), SLOT(itemSelected(const QModelIndex&)));
  this->connect(ui->downloadButton, SIGNAL(clicked()), SLOT(downloadButtonClicked()));
}

ctkXnatTreeBrowserMainWindow::~ctkXnatTreeBrowserMainWindow()
{
  if (m_Session)
  {
    delete m_Session;
  }
  delete ui;

  delete m_TreeModel;
}

void ctkXnatTreeBrowserMainWindow::loginButtonPushed()
{
  if (m_Session)
  {
    delete m_Session;
    m_Session = 0;
    ui->loginButton->setText("Login");
    ui->loginLabel->setText("Disconnected");
    ui->downloadLabel->hide();

  }
  else
  {
    ctkXnatLoginDialog loginDialog;
    if (loginDialog.exec() == QDialog::Accepted)
    {
      m_Session = loginDialog.session();
      if (m_Session)
      {
        ui->loginButton->setText("Logout");
        ui->loginLabel->setText(QString("Connected: %1").arg(m_Session->url().toString()));

        ctkXnatDataModel* dataModel = m_Session->dataModel();
        m_TreeModel->addDataModel(dataModel);
        ui->treeView->reset();
        ui->downloadLabel->show();
      }
    }
  }
}

void ctkXnatTreeBrowserMainWindow::itemSelected(const QModelIndex &index)
{
  ctkXnatObject* xnatObject = m_TreeModel->xnatObject(index);
  ctkXnatFile* xnatFile = dynamic_cast<ctkXnatFile*>(xnatObject);
  ui->downloadButton->setEnabled(xnatFile != 0);
  ui->downloadLabel->setVisible(!(xnatFile != 0));
}

void ctkXnatTreeBrowserMainWindow::downloadButtonClicked()
{
  const QModelIndex index = ui->treeView->selectionModel()->currentIndex();
  QVariant variant = m_TreeModel->data(index, Qt::DisplayRole);
  QString fileName = variant.value<QString>();
  if ( fileName.length() != 0 )
  {
    m_TreeModel->downloadFile(index, fileName);
  }
}
<|endoftext|>


<commit_before>/// \file
/// \ingroup tutorial_ntuple
/// \notebook
/// Convert CMS open data from a TTree to RNTuple.
/// This tutorial illustrates data conversion and data processing with RNTuple and RDataFrame.  In contrast to the
/// LHCb open data tutorial, the data model in this tutorial is not tabular but entries have variable lengths vectors
/// Based on RDataFrame's df102_NanoAODDimuonAnalysis.C
///
/// \macro_image
/// \macro_code
///
/// \date April 2019
/// \author The ROOT Team

// NOTE: The RNTuple classes are experimental at this point.
// Functionality, interface, and data format is still subject to changes.
// Do not use for real data!

#include <ROOT/RDataFrame.hxx>
#include <ROOT/RNTuple.hxx>
#include <ROOT/RNTupleDS.hxx>
#include <ROOT/RVec.hxx>

#include <TCanvas.h>
#include <TH1D.h>
#include <TLatex.h>
#include <TStyle.h>

#include <cassert>
#include <cmath>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <utility>

// Import classes from experimental namespace for the time being
using RNTupleReader = ROOT::Experimental::RNTupleReader;
using RNTupleWriter = ROOT::Experimental::RNTupleWriter;
using RNTupleDS = ROOT::Experimental::RNTupleDS;

constexpr char const* kTreeFileName = "http://root.cern.ch/files/NanoAOD_DoubleMuon_CMS2011OpenData.root";
constexpr char const* kNTupleFileName = "ntpl004_dimuon.root";

using ColNames_t = std::vector<std::string>;

// This is a custom action for RDataFrame. It does not support parallelism!
// This action writes data from an RDataFrame entry into an ntuple. It is templated on the
// types of the columns to be written and can be used as a generic file format converter.
template <typename... ColumnTypes_t>
class RNTupleHelper : public ROOT::Detail::RDF::RActionImpl<RNTupleHelper<ColumnTypes_t...>> {
public:
   using Result_t = RNTupleWriter;
private:
   using ColumnValues_t = std::tuple<std::shared_ptr<ColumnTypes_t>...>;

   std::string fNTupleName;
   std::string fRootFile;
   ColNames_t fColNames;
   ColumnValues_t fColumnValues;
   static constexpr const auto fNColumns = std::tuple_size<ColumnValues_t>::value;
   std::shared_ptr<RNTupleWriter> fNTuple;
   int fCounter;

   template<std::size_t... S>
   void InitializeImpl(std::index_sequence<S...>) {
      auto eventModel = ROOT::Experimental::RNTupleModel::Create();
      // Create the fields and the shared pointers to the connected values
      std::initializer_list<int> expander{
         (std::get<S>(fColumnValues) = eventModel->MakeField<ColumnTypes_t>(fColNames[S]), 0)...};
      fNTuple = std::move(RNTupleWriter::Recreate(std::move(eventModel), fNTupleName, fRootFile));
   }

   template<std::size_t... S>
   void ExecImpl(std::index_sequence<S...>, ColumnTypes_t... values) {
      // For every entry, set the destination of the ntuple's default entry's shared pointers to the given values,
      // which are provided by RDataFrame
      std::initializer_list<int> expander{(*std::get<S>(fColumnValues) = values, 0)...};
   }

public:
   RNTupleHelper(std::string_view ntupleName, std::string_view rootFile, const ColNames_t& colNames)
      : fNTupleName(ntupleName), fRootFile(rootFile), fColNames(colNames)
   {
      InitializeImpl(std::make_index_sequence<fNColumns>());
   }

   RNTupleHelper(RNTupleHelper&&) = default;
   RNTupleHelper(const RNTupleHelper&) = delete;
   std::shared_ptr<RNTupleWriter> GetResultPtr() const { return fNTuple; }

   void Initialize()
   {
      fCounter = 0;
   }

   void InitTask(TTreeReader *, unsigned int) {}

   /// This is a method executed at every entry
   void Exec(unsigned int slot, ColumnTypes_t... values)
   {
      // Populate the ntuple's fields data locations with the provided values, then write to disk
      ExecImpl(std::make_index_sequence<fNColumns>(), values...);
      fNTuple->Fill();
      if (++fCounter % 100000 == 0)
         std::cout << "Wrote " << fCounter << " entries" << std::endl;
   }

   void Finalize()
   {
      fNTuple->CommitCluster();
   }

   std::string GetActionName() { return "RNTuple Writer"; }
};

/// A wrapper for ROOT's InvariantMass function that takes std::vector instead of RVecs
template <typename T>
T InvariantMassStdVector(std::vector<T>& pt, std::vector<T>& eta, std::vector<T>& phi, std::vector<T>& mass)
{
   assert(pt.size() == eta.size() && eta.size() == phi.size() && phi.size() == mass.size() && mass.size() == 2);

   // We adopt the memory here, no copy
   ROOT::RVec<float> rvPt(pt);
   ROOT::RVec<float> rvEta(eta);
   ROOT::RVec<float> rvPhi(phi);
   ROOT::RVec<float> rvMass(mass);

   return InvariantMass(rvPt, rvEta, rvPhi, rvMass);
}

// We use an RDataFrame custom snapshotter to convert between TTree and RNTuple.
// The snapshotter is templated; we construct the conversion C++ code as a string and hand it over to Cling
void Convert() {
   // Use df to list the branch types and names of the input tree
   ROOT::RDataFrame df("Events", kTreeFileName);

   // Construct the types for the template instantiation and the column names from the dataframe
   std::string typeList = "<";
   std::string columnList = "{";
   auto columnNames = df.GetColumnNames();
   for (auto name : columnNames) {
      auto typeName = df.GetColumnType(name);
      // Skip ULong64_t for the time being, RNTuple support will be added at a later point
      if (typeName == "ULong64_t") continue;
      columnList += "\"" + name + "\",";
      typeList += typeName + ",";
   }
   *columnList.rbegin() = '}';
   *typeList.rbegin() = '>';

   std::string code = "{";
   // Convert the first 4 million events
   code += "auto df = std::make_unique<ROOT::RDataFrame>(\"Events\", \"" + std::string(kTreeFileName)
         + "\")->Range(0, 4000000);";
   code += "ColNames_t colNames = " + columnList + ";";
   code += "RNTupleHelper" + typeList + " helper{\"Events\", \"" + std::string(kNTupleFileName) + "\", colNames};";
   code += "*df.Book" + typeList + "(std::move(helper), colNames);";
   code += "}";

   gInterpreter->ProcessLine(code.c_str());
}

void ntpl004_dimuon() {
   Convert();

   // Enable mutli-threading only after the conversion because we use RDF's Range() in it,
   // which currently does not support multi-threading
   ROOT::EnableImplicitMT();

   auto df = ROOT::Experimental::MakeNTupleDataFrame("Events", kNTupleFileName);

   // As of this point, the tutorial is identical to df102_NanoAODDimuonAnalysis except the use of
   // InvariantMassStdVector instead of InvariantMass

   // For simplicity, select only events with exactly two muons and require opposite charge
   auto df_2mu = df.Filter("nMuon == 2", "Events with exactly two muons");
   auto df_os = df_2mu.Filter("Muon_charge[0] != Muon_charge[1]", "Muons with opposite charge");

   // Compute invariant mass of the dimuon system
   auto df_mass = df_os.Define("Dimuon_mass", InvariantMassStdVector<float>, {"Muon_pt", "Muon_eta", "Muon_phi", "Muon_mass"});
   auto df_size = df_os.Define("eta_size", "Muon_mass.size()");

   // Make histogram of dimuon mass spectrum
   auto h = df_mass.Histo1D({"Dimuon_mass", "Dimuon_mass", 30000, 0.25, 300}, "Dimuon_mass");

   // Request cut-flow report
   auto report = df_mass.Report();

   // Produce plot
   gStyle->SetOptStat(0); gStyle->SetTextFont(42);
   auto c = new TCanvas("c", "", 800, 700);
   c->SetLogx(); c->SetLogy();

   h->SetTitle("");
   h->GetXaxis()->SetTitle("m_{#mu#mu} (GeV)"); h->GetXaxis()->SetTitleSize(0.04);
   h->GetYaxis()->SetTitle("N_{Events}"); h->GetYaxis()->SetTitleSize(0.04);
   h->DrawCopy();

   TLatex label; label.SetNDC(true);
   label.DrawLatex(0.175, 0.740, "#eta");
   label.DrawLatex(0.205, 0.775, "#rho,#omega");
   label.DrawLatex(0.270, 0.740, "#phi");
   label.DrawLatex(0.400, 0.800, "J/#psi");
   label.DrawLatex(0.415, 0.670, "#psi'");
   label.DrawLatex(0.485, 0.700, "Y(1,2,3S)");
   label.DrawLatex(0.755, 0.680, "Z");
   label.SetTextSize(0.040); label.DrawLatex(0.100, 0.920, "#bf{CMS Open Data}");
   label.SetTextSize(0.030); label.DrawLatex(0.630, 0.920, "#sqrt{s} = 8 TeV, L_{int} = 11.6 fb^{-1}");

   // Print cut-flow report
   report->Print();
}
<commit_msg>[ntuple] cosmetics (NFC)<commit_after>/// \file
/// \ingroup tutorial_ntuple
/// \notebook
/// Convert CMS open data from a TTree to RNTuple.
/// This tutorial illustrates data conversion and data processing with RNTuple and RDataFrame.  In contrast to the
/// LHCb open data tutorial, the data model in this tutorial is not tabular but entries have variable lengths vectors
/// Based on RDataFrame's df102_NanoAODDimuonAnalysis.C
///
/// \macro_image
/// \macro_code
///
/// \date April 2019
/// \author The ROOT Team

// NOTE: The RNTuple classes are experimental at this point.
// Functionality, interface, and data format is still subject to changes.
// Do not use for real data!

#include <ROOT/RDataFrame.hxx>
#include <ROOT/RNTuple.hxx>
#include <ROOT/RNTupleDS.hxx>
#include <ROOT/RVec.hxx>

#include <TCanvas.h>
#include <TH1D.h>
#include <TLatex.h>
#include <TStyle.h>

#include <cassert>
#include <cmath>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <utility>

// Import classes from experimental namespace for the time being
using RNTupleReader = ROOT::Experimental::RNTupleReader;
using RNTupleWriter = ROOT::Experimental::RNTupleWriter;
using RNTupleDS = ROOT::Experimental::RNTupleDS;

constexpr char const* kTreeFileName = "http://root.cern.ch/files/NanoAOD_DoubleMuon_CMS2011OpenData.root";
constexpr char const* kNTupleFileName = "ntpl004_dimuon.root";

using ColNames_t = std::vector<std::string>;

// This is a custom action for RDataFrame. It does not support parallelism!
// This action writes data from an RDataFrame entry into an ntuple. It is templated on the
// types of the columns to be written and can be used as a generic file format converter.
template <typename... ColumnTypes_t>
class RNTupleHelper : public ROOT::Detail::RDF::RActionImpl<RNTupleHelper<ColumnTypes_t...>> {
public:
   using Result_t = RNTupleWriter;
private:
   using ColumnValues_t = std::tuple<std::shared_ptr<ColumnTypes_t>...>;

   std::string fNTupleName;
   std::string fRootFile;
   ColNames_t fColNames;
   ColumnValues_t fColumnValues;
   static constexpr const auto fNColumns = std::tuple_size<ColumnValues_t>::value;
   std::shared_ptr<RNTupleWriter> fNTuple;
   int fCounter;

   template<std::size_t... S>
   void InitializeImpl(std::index_sequence<S...>) {
      auto eventModel = ROOT::Experimental::RNTupleModel::Create();
      // Create the fields and the shared pointers to the connected values
      std::initializer_list<int> expander{
         (std::get<S>(fColumnValues) = eventModel->MakeField<ColumnTypes_t>(fColNames[S]), 0)...};
      fNTuple = std::move(RNTupleWriter::Recreate(std::move(eventModel), fNTupleName, fRootFile));
   }

   template<std::size_t... S>
   void ExecImpl(std::index_sequence<S...>, ColumnTypes_t... values) {
      // For every entry, set the destination of the ntuple's default entry's shared pointers to the given values,
      // which are provided by RDataFrame
      std::initializer_list<int> expander{(*std::get<S>(fColumnValues) = values, 0)...};
   }

public:
   RNTupleHelper(std::string_view ntupleName, std::string_view rootFile, const ColNames_t& colNames)
      : fNTupleName(ntupleName), fRootFile(rootFile), fColNames(colNames)
   {
      InitializeImpl(std::make_index_sequence<fNColumns>());
   }

   RNTupleHelper(RNTupleHelper&&) = default;
   RNTupleHelper(const RNTupleHelper&) = delete;
   std::shared_ptr<RNTupleWriter> GetResultPtr() const { return fNTuple; }

   void Initialize()
   {
      fCounter = 0;
   }

   void InitTask(TTreeReader *, unsigned int) {}

   /// This is a method executed at every entry
   void Exec(unsigned int slot, ColumnTypes_t... values)
   {
      // Populate the ntuple's fields data locations with the provided values, then write to disk
      ExecImpl(std::make_index_sequence<fNColumns>(), values...);
      fNTuple->Fill();
      if (++fCounter % 100000 == 0)
         std::cout << "Wrote " << fCounter << " entries" << std::endl;
   }

   void Finalize()
   {
      fNTuple->CommitCluster();
   }

   std::string GetActionName() { return "RNTuple Writer"; }
};

/// A wrapper for ROOT's InvariantMass function that takes std::vector instead of RVecs
template <typename T>
T InvariantMassStdVector(std::vector<T>& pt, std::vector<T>& eta, std::vector<T>& phi, std::vector<T>& mass)
{
   assert(pt.size() == 2 && eta.size() == 2 && phi.size() == 2 && mass.size() == 2);

   // We adopt the memory here, no copy
   ROOT::RVec<float> rvPt(pt);
   ROOT::RVec<float> rvEta(eta);
   ROOT::RVec<float> rvPhi(phi);
   ROOT::RVec<float> rvMass(mass);

   return InvariantMass(rvPt, rvEta, rvPhi, rvMass);
}

// We use an RDataFrame custom snapshotter to convert between TTree and RNTuple.
// The snapshotter is templated; we construct the conversion C++ code as a string and hand it over to Cling
void Convert() {
   // Use df to list the branch types and names of the input tree
   ROOT::RDataFrame df("Events", kTreeFileName);

   // Construct the types for the template instantiation and the column names from the dataframe
   std::string typeList = "<";
   std::string columnList = "{";
   auto columnNames = df.GetColumnNames();
   for (auto name : columnNames) {
      auto typeName = df.GetColumnType(name);
      // Skip ULong64_t for the time being, RNTuple support will be added at a later point
      if (typeName == "ULong64_t") continue;
      columnList += "\"" + name + "\",";
      typeList += typeName + ",";
   }
   *columnList.rbegin() = '}';
   *typeList.rbegin() = '>';

   std::string code = "{";
   // Convert the first 4 million events
   code += "auto df = std::make_unique<ROOT::RDataFrame>(\"Events\", \"" + std::string(kTreeFileName)
         + "\")->Range(0, 4000000);";
   code += "ColNames_t colNames = " + columnList + ";";
   code += "RNTupleHelper" + typeList + " helper{\"Events\", \"" + std::string(kNTupleFileName) + "\", colNames};";
   code += "*df.Book" + typeList + "(std::move(helper), colNames);";
   code += "}";

   gInterpreter->ProcessLine(code.c_str());
}

void ntpl004_dimuon() {
   Convert();

   // Enable mutli-threading only after the conversion because we use RDF's Range() in it,
   // which currently does not support multi-threading
   ROOT::EnableImplicitMT();

   auto df = ROOT::Experimental::MakeNTupleDataFrame("Events", kNTupleFileName);

   // As of this point, the tutorial is identical to df102_NanoAODDimuonAnalysis except the use of
   // InvariantMassStdVector instead of InvariantMass

   // For simplicity, select only events with exactly two muons and require opposite charge
   auto df_2mu = df.Filter("nMuon == 2", "Events with exactly two muons");
   auto df_os = df_2mu.Filter("Muon_charge[0] != Muon_charge[1]", "Muons with opposite charge");

   // Compute invariant mass of the dimuon system
   auto df_mass = df_os.Define("Dimuon_mass", InvariantMassStdVector<float>, {"Muon_pt", "Muon_eta", "Muon_phi", "Muon_mass"});
   auto df_size = df_os.Define("eta_size", "Muon_mass.size()");

   // Make histogram of dimuon mass spectrum
   auto h = df_mass.Histo1D({"Dimuon_mass", "Dimuon_mass", 30000, 0.25, 300}, "Dimuon_mass");

   // Request cut-flow report
   auto report = df_mass.Report();

   // Produce plot
   gStyle->SetOptStat(0); gStyle->SetTextFont(42);
   auto c = new TCanvas("c", "", 800, 700);
   c->SetLogx(); c->SetLogy();

   h->SetTitle("");
   h->GetXaxis()->SetTitle("m_{#mu#mu} (GeV)"); h->GetXaxis()->SetTitleSize(0.04);
   h->GetYaxis()->SetTitle("N_{Events}"); h->GetYaxis()->SetTitleSize(0.04);
   h->DrawCopy();

   TLatex label; label.SetNDC(true);
   label.DrawLatex(0.175, 0.740, "#eta");
   label.DrawLatex(0.205, 0.775, "#rho,#omega");
   label.DrawLatex(0.270, 0.740, "#phi");
   label.DrawLatex(0.400, 0.800, "J/#psi");
   label.DrawLatex(0.415, 0.670, "#psi'");
   label.DrawLatex(0.485, 0.700, "Y(1,2,3S)");
   label.DrawLatex(0.755, 0.680, "Z");
   label.SetTextSize(0.040); label.DrawLatex(0.100, 0.920, "#bf{CMS Open Data}");
   label.SetTextSize(0.030); label.DrawLatex(0.630, 0.920, "#sqrt{s} = 8 TeV, L_{int} = 11.6 fb^{-1}");

   // Print cut-flow report
   report->Print();
}
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "docsumwriter.h"
#include "attributedfw.h"
#include "docsumstate.h"
#include <vespa/searchlib/attribute/stringbase.h>
#include <vespa/searchlib/attribute/integerbase.h>
#include <vespa/searchlib/attribute/floatbase.h>
#include <vespa/searchlib/attribute/iattributemanager.h>
#include <vespa/searchlib/tensor/i_tensor_attribute.h>
#include <vespa/searchcommon/attribute/iattributecontext.h>
#include <vespa/eval/tensor/tensor.h>
#include <vespa/eval/tensor/serialization/typed_binary_format.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/data/slime/slime.h>

#include <vespa/log/log.h>
LOG_SETUP(".searchlib.docsummary.attributedfw");

using namespace search;
using search::attribute::IAttributeContext;
using search::attribute::IAttributeVector;
using search::attribute::BasicType;
using vespalib::slime::Inserter;

namespace search::docsummary {

AttrDFW::AttrDFW(const vespalib::string & attrName) :
    _attrName(attrName)
{
}

const attribute::IAttributeVector &
AttrDFW::vec(const GetDocsumsState & s) const {
    return *s.getAttribute(getIndex());
}

//-----------------------------------------------------------------------------

class SingleAttrDFW : public AttrDFW
{
public:
    SingleAttrDFW(const vespalib::string & attrName) :
        AttrDFW(attrName)
    { }
    void insertField(uint32_t docid, GetDocsumsState *state, ResType type, Inserter &target) override;
    bool isDefaultValue(uint32_t docid, const GetDocsumsState * state) const override;
};

bool SingleAttrDFW::isDefaultValue(uint32_t docid, const GetDocsumsState * state) const
{
    return vec(*state).isUndefined(docid);
}

void
SingleAttrDFW::insertField(uint32_t docid, GetDocsumsState * state, ResType type, Inserter &target)
{
    const char *s="";
    const IAttributeVector & v = vec(*state);
    switch (type) {
    case RES_INT: {
        uint32_t val = v.getInt(docid);
        target.insertLong(val);
        break;
    }
    case RES_SHORT: {
        uint16_t val = v.getInt(docid);
        target.insertLong(val);
        break;
    }
    case RES_BYTE: {
        uint8_t val = v.getInt(docid);
        target.insertLong(val);
        break;
    }
    case RES_BOOL: {
        uint8_t val = v.getInt(docid);
        target.insertBool(val != 0);
        break;
    }
    case RES_FLOAT: {
        float val = v.getFloat(docid);
        target.insertDouble(val);
        break;
    }
    case RES_DOUBLE: {
        double val = v.getFloat(docid);
        target.insertDouble(val);
        break;
    }
    case RES_INT64: {
        uint64_t val = v.getInt(docid);
        target.insertLong(val);
        break;
    }
    case RES_TENSOR: {
        BasicType::Type t = v.getBasicType();
        switch (t) {
        case BasicType::TENSOR: {
            const tensor::ITensorAttribute *tv = v.asTensorAttribute();
            assert(tv != nullptr);
            const auto tensor = tv->getTensor(docid);
            if (tensor) {
                vespalib::nbostream str;
                vespalib::tensor::TypedBinaryFormat::serialize(str, *tensor);
                target.insertData(vespalib::Memory(str.peek(), str.size()));
            }
        }
        default:
            ;
        }
    }
        break;
    case RES_JSONSTRING:
    case RES_XMLSTRING:
    case RES_FEATUREDATA:
    case RES_LONG_STRING:
    case RES_STRING: {
        s = v.getString(docid, nullptr, 0); // no need to pass in a buffer, this attribute has a string storage.
        target.insertString(vespalib::Memory(s));
        break;
    }
    case RES_LONG_DATA:
    case RES_DATA: {
        s = v.getString(docid, nullptr, 0); // no need to pass in a buffer, this attribute has a string storage.
        target.insertData(vespalib::Memory(s));
        break;
    }
    default:
        // unknown type, will be missing, should not happen
        return;
    }
}

//-----------------------------------------------------------------------------

class MultiAttrDFW : public AttrDFW
{
public:
    MultiAttrDFW(const vespalib::string & attrName) : AttrDFW(attrName) {}
    void insertField(uint32_t docid, GetDocsumsState *state, ResType type, Inserter &target) override;

};

void
MultiAttrDFW::insertField(uint32_t docid, GetDocsumsState *state, ResType, Inserter &target)
{
    using vespalib::slime::Cursor;
    using vespalib::Memory;
    const IAttributeVector & v = vec(*state);
    uint32_t entries = v.getValueCount(docid);
    bool isWeightedSet = v.hasWeightedSetType();

    Cursor &arr = target.insertArray();
    BasicType::Type t = v.getBasicType();
    switch (t) {
    case BasicType::NONE:
    case BasicType::STRING: {
        std::vector<IAttributeVector::WeightedString> elements(entries);
        entries = std::min(entries, v.get(docid, &elements[0], entries));
        for (uint32_t i = 0; i < entries; ++i) {
            const vespalib::string &sv = elements[i].getValue();
            Memory value(sv.c_str(), sv.size());
            if (isWeightedSet) {
                Cursor &elem = arr.addObject();
                elem.setString("item", value);
                elem.setLong("weight", elements[i].getWeight());
            } else {
                arr.addString(value);
            }
        }
        return; }
    case BasicType::BOOL:
    case BasicType::UINT2:
    case BasicType::UINT4:
    case BasicType::INT8:
    case BasicType::INT16:
    case BasicType::INT32:
    case BasicType::INT64: {
        std::vector<IAttributeVector::WeightedInt> elements(entries);
        entries = std::min(entries, v.get(docid, &elements[0], entries));
        for (uint32_t i = 0; i < entries; ++i) {
            if (isWeightedSet) {
                Cursor &elem = arr.addObject();
                elem.setLong("item", elements[i].getValue());
                elem.setLong("weight", elements[i].getWeight());
            } else {
                arr.addLong(elements[i].getValue());
            }
        }
        return; }
    case BasicType::FLOAT:
    case BasicType::DOUBLE: {
        std::vector<IAttributeVector::WeightedFloat> elements(entries);
        entries = std::min(entries, v.get(docid, &elements[0], entries));
        for (uint32_t i = 0; i < entries; ++i) {
            if (isWeightedSet) {
                Cursor &elem = arr.addObject();
                elem.setDouble("item", elements[i].getValue());
                elem.setLong("weight", elements[i].getWeight());
            } else {
                arr.addDouble(elements[i].getValue());
            }
        }
        return; }
    default:
        // should not happen
        LOG(error, "bad value for type: %u\n", t);
        LOG_ASSERT(false);
    }
}

//-----------------------------------------------------------------------------

IDocsumFieldWriter *
AttributeDFWFactory::create(IAttributeManager & vecMan, const char *vecName)
{
    IAttributeContext::UP ctx = vecMan.createContext();
    const IAttributeVector * vec = ctx->getAttribute(vecName);
    if (vec == nullptr) {
        LOG(warning, "No valid attribute vector found: %s", vecName);
        return nullptr;
    }
    if (vec->hasMultiValue()) {
        return new MultiAttrDFW(vec->getName());
    } else {
        return new SingleAttrDFW(vec->getName());
    }
}

}
<commit_msg>Don't insert empty multivalued attribute fields in summary<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "docsumwriter.h"
#include "attributedfw.h"
#include "docsumstate.h"
#include <vespa/searchlib/attribute/stringbase.h>
#include <vespa/searchlib/attribute/integerbase.h>
#include <vespa/searchlib/attribute/floatbase.h>
#include <vespa/searchlib/attribute/iattributemanager.h>
#include <vespa/searchlib/tensor/i_tensor_attribute.h>
#include <vespa/searchcommon/attribute/iattributecontext.h>
#include <vespa/eval/tensor/tensor.h>
#include <vespa/eval/tensor/serialization/typed_binary_format.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/data/slime/slime.h>

#include <vespa/log/log.h>
LOG_SETUP(".searchlib.docsummary.attributedfw");

using namespace search;
using search::attribute::IAttributeContext;
using search::attribute::IAttributeVector;
using search::attribute::BasicType;
using vespalib::slime::Inserter;

namespace search::docsummary {

AttrDFW::AttrDFW(const vespalib::string & attrName) :
    _attrName(attrName)
{
}

const attribute::IAttributeVector &
AttrDFW::vec(const GetDocsumsState & s) const {
    return *s.getAttribute(getIndex());
}

//-----------------------------------------------------------------------------

class SingleAttrDFW : public AttrDFW
{
public:
    SingleAttrDFW(const vespalib::string & attrName) :
        AttrDFW(attrName)
    { }
    void insertField(uint32_t docid, GetDocsumsState *state, ResType type, Inserter &target) override;
    bool isDefaultValue(uint32_t docid, const GetDocsumsState * state) const override;
};

bool SingleAttrDFW::isDefaultValue(uint32_t docid, const GetDocsumsState * state) const
{
    return vec(*state).isUndefined(docid);
}

void
SingleAttrDFW::insertField(uint32_t docid, GetDocsumsState * state, ResType type, Inserter &target)
{
    const char *s="";
    const IAttributeVector & v = vec(*state);
    switch (type) {
    case RES_INT: {
        uint32_t val = v.getInt(docid);
        target.insertLong(val);
        break;
    }
    case RES_SHORT: {
        uint16_t val = v.getInt(docid);
        target.insertLong(val);
        break;
    }
    case RES_BYTE: {
        uint8_t val = v.getInt(docid);
        target.insertLong(val);
        break;
    }
    case RES_BOOL: {
        uint8_t val = v.getInt(docid);
        target.insertBool(val != 0);
        break;
    }
    case RES_FLOAT: {
        float val = v.getFloat(docid);
        target.insertDouble(val);
        break;
    }
    case RES_DOUBLE: {
        double val = v.getFloat(docid);
        target.insertDouble(val);
        break;
    }
    case RES_INT64: {
        uint64_t val = v.getInt(docid);
        target.insertLong(val);
        break;
    }
    case RES_TENSOR: {
        BasicType::Type t = v.getBasicType();
        switch (t) {
        case BasicType::TENSOR: {
            const tensor::ITensorAttribute *tv = v.asTensorAttribute();
            assert(tv != nullptr);
            const auto tensor = tv->getTensor(docid);
            if (tensor) {
                vespalib::nbostream str;
                vespalib::tensor::TypedBinaryFormat::serialize(str, *tensor);
                target.insertData(vespalib::Memory(str.peek(), str.size()));
            }
        }
        default:
            ;
        }
    }
        break;
    case RES_JSONSTRING:
    case RES_XMLSTRING:
    case RES_FEATUREDATA:
    case RES_LONG_STRING:
    case RES_STRING: {
        s = v.getString(docid, nullptr, 0); // no need to pass in a buffer, this attribute has a string storage.
        target.insertString(vespalib::Memory(s));
        break;
    }
    case RES_LONG_DATA:
    case RES_DATA: {
        s = v.getString(docid, nullptr, 0); // no need to pass in a buffer, this attribute has a string storage.
        target.insertData(vespalib::Memory(s));
        break;
    }
    default:
        // unknown type, will be missing, should not happen
        return;
    }
}

//-----------------------------------------------------------------------------

class MultiAttrDFW : public AttrDFW
{
public:
    MultiAttrDFW(const vespalib::string & attrName) : AttrDFW(attrName) {}
    void insertField(uint32_t docid, GetDocsumsState *state, ResType type, Inserter &target) override;

};

void
MultiAttrDFW::insertField(uint32_t docid, GetDocsumsState *state, ResType, Inserter &target)
{
    using vespalib::slime::Cursor;
    using vespalib::Memory;
    const IAttributeVector & v = vec(*state);
    bool isWeightedSet = v.hasWeightedSetType();

    uint32_t entries = v.getValueCount(docid);
    if (entries == 0) {
        return;  // Don't insert empty fields
    }

    Cursor &arr = target.insertArray();
    BasicType::Type t = v.getBasicType();
    switch (t) {
    case BasicType::NONE:
    case BasicType::STRING: {
        std::vector<IAttributeVector::WeightedString> elements(entries);
        entries = std::min(entries, v.get(docid, &elements[0], entries));
        for (uint32_t i = 0; i < entries; ++i) {
            const vespalib::string &sv = elements[i].getValue();
            Memory value(sv.c_str(), sv.size());
            if (isWeightedSet) {
                Cursor &elem = arr.addObject();
                elem.setString("item", value);
                elem.setLong("weight", elements[i].getWeight());
            } else {
                arr.addString(value);
            }
        }
        return; }
    case BasicType::BOOL:
    case BasicType::UINT2:
    case BasicType::UINT4:
    case BasicType::INT8:
    case BasicType::INT16:
    case BasicType::INT32:
    case BasicType::INT64: {
        std::vector<IAttributeVector::WeightedInt> elements(entries);
        entries = std::min(entries, v.get(docid, &elements[0], entries));
        for (uint32_t i = 0; i < entries; ++i) {
            if (isWeightedSet) {
                Cursor &elem = arr.addObject();
                elem.setLong("item", elements[i].getValue());
                elem.setLong("weight", elements[i].getWeight());
            } else {
                arr.addLong(elements[i].getValue());
            }
        }
        return; }
    case BasicType::FLOAT:
    case BasicType::DOUBLE: {
        std::vector<IAttributeVector::WeightedFloat> elements(entries);
        entries = std::min(entries, v.get(docid, &elements[0], entries));
        for (uint32_t i = 0; i < entries; ++i) {
            if (isWeightedSet) {
                Cursor &elem = arr.addObject();
                elem.setDouble("item", elements[i].getValue());
                elem.setLong("weight", elements[i].getWeight());
            } else {
                arr.addDouble(elements[i].getValue());
            }
        }
        return; }
    default:
        // should not happen
        LOG(error, "bad value for type: %u\n", t);
        LOG_ASSERT(false);
    }
}

//-----------------------------------------------------------------------------

IDocsumFieldWriter *
AttributeDFWFactory::create(IAttributeManager & vecMan, const char *vecName)
{
    IAttributeContext::UP ctx = vecMan.createContext();
    const IAttributeVector * vec = ctx->getAttribute(vecName);
    if (vec == nullptr) {
        LOG(warning, "No valid attribute vector found: %s", vecName);
        return nullptr;
    }
    if (vec->hasMultiValue()) {
        return new MultiAttrDFW(vec->getName());
    } else {
        return new SingleAttrDFW(vec->getName());
    }
}

}
<|endoftext|>