<commit_before>/*
 * InterColComm.cpp
 *
 *  Created on: Aug 28, 2008
 *      Author: rasmussn
 */

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "InterColComm.hpp"
#include "HyPerCol.hpp"
#include "../connections/PVConnection.h"

namespace PV {

InterColComm::InterColComm(int* argc, char*** argv) : Communicator(argc, argv)
{
   numPublishers = 0;

   for (int i = 0; i < MAX_PUBLISHERS; i++) {
      publishers[i] = NULL;
   }
}

InterColComm::~InterColComm()
{
   for (int i = 0; i < MAX_PUBLISHERS; i++) {
      if (publishers[i] != NULL) {
         delete publishers[i];
      }
   }
}

int InterColComm::addPublisher(HyPerLayer* pub, int numItems, int numLevels)
{
   int pubId = pub->getLayerId();

#ifdef EXTEND_BORDER_INDEX
   publishers[pubId] = new Publisher(pubId, this, numItems, pub->clayer->loc, numLevels);
#else
   publishers[pubId] = new Publisher(pubId, numNeighbors, size1, numBorders, size2, numLevels);
   publishers[pubId]->setCommunicator(communicator());
#endif

   numPublishers += 1;

   DataStore* store = publishers[pubId]->dataStore();

#ifndef EXTEND_BORDER_INDEX
   for (int i = 0; i < numBorders; i++) {
      for (int delay = 0; delay < numLevels; delay++) {
         int borderIndex = Publisher::borderStoreIndex(i, numNeighbors);
         PVLayerCube* border = (PVLayerCube*) store->buffer(borderIndex, delay);
         pvcube_setAddr(border);
         pub->initBorder(border, borders[i]);
      }
   }
#endif

   return pubId;
}

int InterColComm::subscribe(HyPerConn* conn)
{
   int pubId = conn->preSynapticLayer()->getLayerId();
   assert(pubId < MAX_PUBLISHERS && pubId >= 0);
   return publishers[pubId]->subscribe(conn);
}

int InterColComm::publish(HyPerLayer* pub, PVLayerCube* cube)
{
   int pubId = pub->getLayerId();
   return publishers[pubId]->publish(pub, remoteNeighbors, numNeighbors, borders, numBorders, cube);
}

/**
 * deliver all outstanding published messages
 */
int InterColComm::deliver(HyPerCol* hc, int pubId)
{
#ifdef DEBUG_OUTPUT
   printf("[%d]: InterColComm::deliver: pubId=%d\n", icRank, pubId);  fflush(stdout);
#endif
   return publishers[pubId]->deliver(hc, numNeighbors, numBorders);
}

// deprecated constructor that separates borders from the layer data structure
Publisher::Publisher(int pubId, int numType1, size_t size1, int numType2, size_t size2, int numLevels)
{
   size_t maxSize = (size1 > size2) ? size1 : size2;
   this->pubId = pubId;
   this->comm  = NULL;
   this->numSubscribers = 0;
   this->store = new DataStore(numType1+numType2, maxSize, numLevels);
   for (int i = 0; i < MAX_SUBSCRIBERS; i++) {
      this->connection[i] = NULL;
   }
}

Publisher::Publisher(int pubId, Communicator * comm, int numItems, LayerLoc loc, int numLevels)
{
   size_t dataSize  = numItems * sizeof(float);

   this->pubId = pubId;
   this->comm  = comm;
   this->numSubscribers = 0;

   cube.data = NULL;
   cube.loc = loc;
   cube.numItems = numItems;
   cube.size = dataSize + sizeof(PVLayerCube);  // not really inplace but ok

   const int numBuffers = 1;
   this->store = new DataStore(numBuffers, dataSize, numLevels);

   this->neighborDatatypes = Communicator::newDatatypes(&loc);

   for (int i = 0; i < MAX_SUBSCRIBERS; i++) {
      this->connection[i] = NULL;
   }
}

Publisher::~Publisher()
{
   delete store;
}

int Publisher::publish(HyPerLayer* pub,
                       int neighbors[], int numNeighbors,
                       int borders[], int numBorders,
                       PVLayerCube* cube)
{
   size_t dataSize = cube->numItems * sizeof(pvdata_t);
   assert(dataSize == store->size());

   if (numSubscribers < 1) {
      return 0;  // no one to deliver to
   }

#ifdef PV_USE_MPI
   int icRank = comm->commRank();
   MPI_Comm mpiComm = comm->communicator();

   // don't send interior
   int nreq = 0;
   for (int n = 1; n < NUM_NEIGHBORHOOD; n++) {
      if (neighbors[n] == icRank) continue;  // don't send interior to self
      pvdata_t * recvBuf = cube->data + Communicator::recvOffset(n, &cube->loc);
      pvdata_t * sendBuf = cube->data + Communicator::sendOffset(n, &cube->loc);
#ifdef DEBUG_OUTPUT
      fprintf(stderr, "[%2d]: recv,send to %d, n=%d recvOffset==%ld sendOffset==%ld send[0]==%f\n", icRank, neighbors[n], n, recvOffset(n,loc), sendOffset(n,loc), sendBuf[0]); fflush(stdout);
#endif
      MPI_Irecv(recvBuf, 1, neighborDatatypes[n], neighbors[n], 33, mpiComm,
                &requests[nreq++]);
      MPI_Send( sendBuf, 1, neighborDatatypes[n], neighbors[n], 33, mpiComm);
   }
   assert(nreq == comm->numberOfNeighbors() - 1);

#endif // PV_USE_MPI

   pvdata_t * sendBuf = cube->data + Communicator::sendOffset(LOCAL, &cube->loc);

   // copy layer interior (no margins)
   memcpy(recvBuffer(LOCAL), sendBuf, dataSize);

#ifdef PV_OLD_MPI
   // send/recv to/from neighbors
   for (int i = 0; i < numNeighbors; i++) {
      // Note - cube->data addr need not be correct as it will be wrong copied in from MPI
      void * recvBuf = recvBuffer(i);
      MPI_Irecv(recvBuf, size, MPI_CHAR, neighbors[i], pubId, comm,
            &request[i]);
      MPI_Send(cube, size, MPI_CHAR, neighbors[i], pubId, comm);
#ifdef DEBUG_OUTPUT
      printf("[%d]: Publisher::publish: neighbor=%d pubId=%d sendbuf=%p recvbuf=%p\n",
             icRank, neighbors[i], i, cube, recvBuf);
      fflush(stdout);
#endif
   }
#endif // PV_OLD_MPI

   //
   // transform cube (and copy) for boundary conditions of neighbor slots that
   // don't exist in processor topology (i.e., a hypercolumn at edge of image)
   //
//   for (int i = 0; i < numBorders; i++) {
//      int borderIndex = Publisher::borderStoreIndex(i, numNeighbors);
//      PVLayerCube* border = (PVLayerCube*) recvBuffer(borderIndex);
//      pub->copyToBorder(borders[i], cube, border);
//   }

   return 0;
}

/**
 * deliver all outstanding published messages
 */
int Publisher::deliver(HyPerCol* hc, int numNeighbors, int numBorders)
{
   if (numSubscribers < 1) {
      return 0;  // no one to deliver to
   }

   // deliver delayed information first
   for (int ic = 0; ic < numSubscribers; ic++) {
      HyPerConn* conn = connection[ic];
      int delay = conn->getDelay();
      if (delay > 0) {
         cube.data = (pvdata_t *) store->buffer(LOCAL, delay);
#ifdef DEBUG_OUTPUT
         printf("[%d]: Publisher::deliver: buf=%p\n", icRank, cube.data);
         fflush(stdout);
#endif
         conn->deliver(&cube, LOCAL);
      }
   }

   // deliver current (no delay) information last

#ifdef PV_USE_MPI
   MPI_Waitall(numNeighbors, requests, MPI_STATUSES_IGNORE);
#ifdef DEBUG_OUTPUT
   fprintf(stderr, "[%2d]: waiting for data, count==%d\n", icRank, count); fflush(stdout);
#endif
#endif // PV_USE_MPI

   for (int ic = 0; ic < numSubscribers; ic++) {
      HyPerConn* conn = this->connection[ic];
      if (conn->getDelay() == 0) {
         cube.data = (pvdata_t *) store->buffer(LOCAL);
#ifdef DEBUG_OUTPUT
         printf("[%d]: Publisher::deliver: buf=%p\n", icRank, cube.data);
         fflush(stdout);
#endif
         conn->deliver(&cube, LOCAL);
      }
   }

   return 0;
}

int Publisher::subscribe(HyPerConn* conn)
{
   connection[numSubscribers] = conn;
   numSubscribers += 1;

   return 0;
}

} // end namespace PV
<commit_msg>Fixed bug in call to MPI_Waitall (request size too big).<commit_after>/*
 * InterColComm.cpp
 *
 *  Created on: Aug 28, 2008
 *      Author: rasmussn
 */

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "InterColComm.hpp"
#include "HyPerCol.hpp"
#include "../connections/PVConnection.h"

namespace PV {

InterColComm::InterColComm(int* argc, char*** argv) : Communicator(argc, argv)
{
   numPublishers = 0;

   for (int i = 0; i < MAX_PUBLISHERS; i++) {
      publishers[i] = NULL;
   }
}

InterColComm::~InterColComm()
{
   for (int i = 0; i < MAX_PUBLISHERS; i++) {
      if (publishers[i] != NULL) {
         delete publishers[i];
      }
   }
}

int InterColComm::addPublisher(HyPerLayer* pub, int numItems, int numLevels)
{
   int pubId = pub->getLayerId();

#ifdef EXTEND_BORDER_INDEX
   publishers[pubId] = new Publisher(pubId, this, numItems, pub->clayer->loc, numLevels);
#else
   publishers[pubId] = new Publisher(pubId, numNeighbors, size1, numBorders, size2, numLevels);
   publishers[pubId]->setCommunicator(communicator());
#endif

   numPublishers += 1;

   DataStore* store = publishers[pubId]->dataStore();

#ifndef EXTEND_BORDER_INDEX
   for (int i = 0; i < numBorders; i++) {
      for (int delay = 0; delay < numLevels; delay++) {
         int borderIndex = Publisher::borderStoreIndex(i, numNeighbors);
         PVLayerCube* border = (PVLayerCube*) store->buffer(borderIndex, delay);
         pvcube_setAddr(border);
         pub->initBorder(border, borders[i]);
      }
   }
#endif

   return pubId;
}

int InterColComm::subscribe(HyPerConn* conn)
{
   int pubId = conn->preSynapticLayer()->getLayerId();
   assert(pubId < MAX_PUBLISHERS && pubId >= 0);
   return publishers[pubId]->subscribe(conn);
}

int InterColComm::publish(HyPerLayer* pub, PVLayerCube* cube)
{
   int pubId = pub->getLayerId();
   return publishers[pubId]->publish(pub, remoteNeighbors, numNeighbors, borders, numBorders, cube);
}

/**
 * deliver all outstanding published messages
 */
int InterColComm::deliver(HyPerCol* hc, int pubId)
{
#ifdef DEBUG_OUTPUT
   printf("[%d]: InterColComm::deliver: pubId=%d\n", icRank, pubId);  fflush(stdout);
#endif
   return publishers[pubId]->deliver(hc, numNeighbors, numBorders);
}

// deprecated constructor that separates borders from the layer data structure
Publisher::Publisher(int pubId, int numType1, size_t size1, int numType2, size_t size2, int numLevels)
{
   size_t maxSize = (size1 > size2) ? size1 : size2;
   this->pubId = pubId;
   this->comm  = NULL;
   this->numSubscribers = 0;
   this->store = new DataStore(numType1+numType2, maxSize, numLevels);
   for (int i = 0; i < MAX_SUBSCRIBERS; i++) {
      this->connection[i] = NULL;
   }
}

Publisher::Publisher(int pubId, Communicator * comm, int numItems, LayerLoc loc, int numLevels)
{
   size_t dataSize  = numItems * sizeof(float);

   this->pubId = pubId;
   this->comm  = comm;
   this->numSubscribers = 0;

   cube.data = NULL;
   cube.loc = loc;
   cube.numItems = numItems;
   cube.size = dataSize + sizeof(PVLayerCube);  // not really inplace but ok

   const int numBuffers = 1;
   this->store = new DataStore(numBuffers, dataSize, numLevels);

   this->neighborDatatypes = Communicator::newDatatypes(&loc);

   for (int i = 0; i < MAX_SUBSCRIBERS; i++) {
      this->connection[i] = NULL;
   }
}

Publisher::~Publisher()
{
   delete store;
}

int Publisher::publish(HyPerLayer* pub,
                       int neighbors[], int numNeighbors,
                       int borders[], int numBorders,
                       PVLayerCube* cube)
{
   size_t dataSize = cube->numItems * sizeof(pvdata_t);
   assert(dataSize == store->size());

   if (numSubscribers < 1) {
      return 0;  // no one to deliver to
   }

#ifdef PV_USE_MPI
   int icRank = comm->commRank();
   MPI_Comm mpiComm = comm->communicator();

   // don't send interior
   int nreq = 0;
   for (int n = 1; n < NUM_NEIGHBORHOOD; n++) {
      if (neighbors[n] == icRank) continue;  // don't send interior to self
      pvdata_t * recvBuf = cube->data + Communicator::recvOffset(n, &cube->loc);
      pvdata_t * sendBuf = cube->data + Communicator::sendOffset(n, &cube->loc);
#ifdef DEBUG_OUTPUT
      fprintf(stderr, "[%2d]: recv,send to %d, n=%d recvOffset==%ld sendOffset==%ld send[0]==%f\n", icRank, neighbors[n], n, recvOffset(n,loc), sendOffset(n,loc), sendBuf[0]); fflush(stdout);
#endif
      MPI_Irecv(recvBuf, 1, neighborDatatypes[n], neighbors[n], 33, mpiComm,
                &requests[nreq++]);
      MPI_Send( sendBuf, 1, neighborDatatypes[n], neighbors[n], 33, mpiComm);
   }
   assert(nreq == comm->numberOfNeighbors() - 1);

#endif // PV_USE_MPI

   pvdata_t * sendBuf = cube->data + Communicator::sendOffset(LOCAL, &cube->loc);

   // copy layer interior (no margins)
   memcpy(recvBuffer(LOCAL), sendBuf, dataSize);

#ifdef PV_OLD_MPI
   // send/recv to/from neighbors
   for (int i = 0; i < numNeighbors; i++) {
      // Note - cube->data addr need not be correct as it will be wrong copied in from MPI
      void * recvBuf = recvBuffer(i);
      MPI_Irecv(recvBuf, size, MPI_CHAR, neighbors[i], pubId, comm,
            &request[i]);
      MPI_Send(cube, size, MPI_CHAR, neighbors[i], pubId, comm);
#ifdef DEBUG_OUTPUT
      printf("[%d]: Publisher::publish: neighbor=%d pubId=%d sendbuf=%p recvbuf=%p\n",
             icRank, neighbors[i], i, cube, recvBuf);
      fflush(stdout);
#endif
   }
#endif // PV_OLD_MPI

   //
   // transform cube (and copy) for boundary conditions of neighbor slots that
   // don't exist in processor topology (i.e., a hypercolumn at edge of image)
   //
//   for (int i = 0; i < numBorders; i++) {
//      int borderIndex = Publisher::borderStoreIndex(i, numNeighbors);
//      PVLayerCube* border = (PVLayerCube*) recvBuffer(borderIndex);
//      pub->copyToBorder(borders[i], cube, border);
//   }

   return 0;
}

/**
 * deliver all outstanding published messages
 */
int Publisher::deliver(HyPerCol* hc, int numNeighbors, int numBorders)
{
   if (numSubscribers < 1) {
      return 0;  // no one to deliver to
   }

   // deliver delayed information first
   for (int ic = 0; ic < numSubscribers; ic++) {
      HyPerConn* conn = connection[ic];
      int delay = conn->getDelay();
      if (delay > 0) {
         cube.data = (pvdata_t *) store->buffer(LOCAL, delay);
#ifdef DEBUG_OUTPUT
         printf("[%d]: Publisher::deliver: buf=%p\n", icRank, cube.data);
         fflush(stdout);
#endif
         conn->deliver(&cube, LOCAL);
      }
   }

   // deliver current (no delay) information last

#ifdef PV_USE_MPI
   MPI_Waitall(numNeighbors-1, requests, MPI_STATUSES_IGNORE);
#ifdef DEBUG_OUTPUT
   fprintf(stderr, "[%2d]: waiting for data, count==%d\n", icRank, count); fflush(stdout);
#endif
#endif // PV_USE_MPI

   for (int ic = 0; ic < numSubscribers; ic++) {
      HyPerConn* conn = this->connection[ic];
      if (conn->getDelay() == 0) {
         cube.data = (pvdata_t *) store->buffer(LOCAL);
#ifdef DEBUG_OUTPUT
         printf("[%d]: Publisher::deliver: buf=%p\n", icRank, cube.data);
         fflush(stdout);
#endif
         conn->deliver(&cube, LOCAL);
      }
   }

   return 0;
}

int Publisher::subscribe(HyPerConn* conn)
{
   connection[numSubscribers] = conn;
   numSubscribers += 1;

   return 0;
}

} // end namespace PV
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <getopt.h>
#include <functional>
#include <regex>
//#include "intervaltree.hpp"
#include "subcommand.hpp"
#include "stream.hpp"
#include "index.hpp"
#include "position.hpp"
#include "vg.pb.h"
#include "path.hpp"
//#include "genotyper.hpp"
#include "genotypekit.hpp"
#include "path_index.hpp"
#include "vg.hpp"
#include "srpe.hpp"
#include "filter.hpp"
#include "utility.hpp"
#include "Variant.h"
#include "translator.hpp"
#include "Fasta.h"

using namespace std;
using namespace vg;
using namespace vg::subcommand;

void help_srpe(char** argv){
    cerr << "Usage: " << argv[0] << " srpe [options] <data.gam> <graph.vg>" << endl
        << "Options: " << endl
        << "Variant recall:" << endl
        << "   -S / --specific    <VCF>       look up variants in <VCF> in the graph and report only those." << endl
        << "   -R / --recall                  recall (i.e. type) all variant paths stored in the graph." << endl
        << "   -r / --reference   <REF>       reference genome to pull structural variants from." << endl
        << "   -I / --insertions  <INS>       fasta file containing insertion sequences." << endl
        << "Smart genotyping:" << endl
        << "   -a / --augmented   <AUG>       write the intermediate augmented graph to <AUG>." << endl
        << "   -p / --ref-path   <PATHNAME>   find variants relative to <PATHNAME>" << endl
        << endl;
    //<< "-S / --SV-TYPE comma separated list of SV types to detect (default: all)." << endl

}

int main_srpe(int argc, char** argv){
    string gam_name = "";
    string gam_index_name = "";
    string graph_name = "";
    string xg_name = "";
    string gcsa_name = "";
    string lcp_name = "";

    string spec_vcf = "";
    string ref_fasta = "";
    string ins_fasta = "";

    string augmented_graph_name = "";
    bool augment_paths = true;

    string ref_path = "";

    int max_iter = 2;
    int max_frag_len = 10000;
    int min_soft_clip = 12;

    bool do_all = false;

    vector<string> search_types;
    search_types.push_back("DEL");

    int threads = 1;

    if (argc <= 2) {
        help_srpe(argv);
        return 1;
    }

    int c;
    optind = 2; // force optind past command positional argument
    while (true) {
        static struct option long_options[] =
        {
            {"max-iter", required_argument, 0, 'm'},
            {"xg-index", required_argument, 0, 'x'},
            {"augmented", required_argument, 0, 'a'},
            {"help", no_argument, 0, 'h'},
            {"gcsa-index", required_argument, 0, 'g'},
            {"specific", required_argument, 0, 'S'},
            {"recall", no_argument, 0, 'R'},
            {"insertions", required_argument, 0, 'I'},
            {"reference", required_argument, 0, 'r'},
            {"threads", required_argument, 0, 't'},
            {"ref-path", required_argument, 0, 'p'},
            {0, 0, 0, 0}

        };
        int option_index = 0;
        c = getopt_long (argc, argv, "hx:g:m:S:RI:r:t:a:wp:",
                long_options, &option_index);

        // Detect the end of the options.
        if (c == -1)
            break;

        switch (c)
        {
            case 'a':
                augmented_graph_name = optarg;
                break;
            case 'm':
                max_iter = atoi(optarg);
                break;

            case 't':
                threads = atoi(optarg);
                break;

            case 'R':
                do_all = true;
                break;
            case 'x':
                xg_name = optarg;
                break;
            case 'g':
                gcsa_name = optarg;
                break;
            case 'S':
                spec_vcf = optarg;
                break;
            case 'r':
                ref_fasta = optarg;
                break;
            case 'I':
                ins_fasta = optarg;
                break;
            case 'p':
                ref_path = optarg;
                break;
            case 'h':
            case '?':
            default:
                help_srpe(argv);
                abort();
        }

    }

    omp_set_num_threads(threads);

    //SRPE srpe;

    gam_name = argv[optind];
    //gam_index_name = argv[++optind];
    graph_name = argv[++optind];

    xg::XG* xg_ind = new xg::XG();
    Index gamind;

    vg::VG* graph;

    // if (!xg_name.empty()){
    //     ifstream in(xg_name);
    //     xg_ind->load(in);
    // }
    // if (!gam_index_name.empty()){
    //     gamind.open_read_only(gam_index_name);
    // }
    // else{

    // }

    if (!graph_name.empty()){
        ifstream in(graph_name);
        graph = new VG(in, false);
    }

    // Open a variant call file,
    // hash each variant to an hash ID
    // have in if in the loop below.
    map<string, Locus> name_to_loc;
    // Makes a pathindex, which allows us to query length and push out a VCF with a position
    map<string, PathIndex*> pindexes;
    regex is_alt ("_alt_.*");

    vector<FastaReference*> insertions;
    if (!ins_fasta.empty()){
        FastaReference* ins = new FastaReference();
        insertions.emplace_back(ins);
        ins->open(ins_fasta);

    }

    if (!spec_vcf.empty() && ref_fasta.empty()){
        cerr << "Error: option -S requires a fasta reference using the -r <reference> flag" << endl;
    }
    else if (!spec_vcf.empty()){

        FastaReference* linear_ref = new FastaReference();
        linear_ref->open(ref_fasta);

        for (auto r_path : (graph->paths)._paths){
            if (!regex_match(r_path.first, is_alt)){
                pindexes[r_path.first] = new PathIndex(*graph, r_path.first, true);
            }
        }

        vcflib::VariantCallFile* variant_file = new vcflib::VariantCallFile();
        variant_file->open(spec_vcf);

        string descrip = "";
        descrip = "##INFO=<ID=AD,Number=R,Type=Integer,Description=\"Allele depth for each allele.\"\\>";
        variant_file->addHeaderLine(descrip);

        cout << variant_file->header << endl;

        unordered_map<string, list<Mapping> > graphpaths( (graph->paths)._paths.begin(), (graph->paths)._paths.end() );
        map<string, vcflib::Variant> hash_to_var;
        unordered_map<string, vector<int64_t> > varname_to_nodeid;
        unordered_map<int64_t, int32_t> node_to_depth;
        vector<int64_t> variant_nodes;
        variant_nodes.reserve(10000);

        // Hash a variant from the VCF
        vcflib::Variant var;
        while (variant_file->getNextVariant(var)){
            var.position -= 1;
            var.canonicalize_sv(*linear_ref, insertions, -1);
            string var_id = make_variant_id(var);
            hash_to_var[ var_id ] = var;
            for (int alt_ind = 0; alt_ind <= var.alt.size(); alt_ind++){
                string alt_id = "_alt_" + var_id + "_" + std::to_string(alt_ind);
                list<Mapping> x_path = graphpaths[ alt_id ];
                for (Mapping x_m : x_path){
                    variant_nodes.push_back(x_m.position().node_id());
                    varname_to_nodeid[ alt_id ].push_back(x_m.position().node_id());
                }
            }

        }
        std::function<void(const Alignment& a)> incr = [&](const Alignment& a){
            for (int i = 0; i < a.path().mapping_size(); i++){
                node_to_depth[ a.path().mapping(i).position().node_id() ] += 1;
            }
        };

        gamind.for_alignment_to_nodes(variant_nodes, incr);

        cerr << node_to_depth.size () << " reads in count map" << endl;

        for (auto it : hash_to_var){
            for (int i = 0; i <= it.second.alt.size(); i++){
                int32_t sum_reads = 0;
                string alt_id = "_alt_" + it.first + "_" + std::to_string(i);
                for (int i = 0; i < varname_to_nodeid[ alt_id ].size(); i++){
                    sum_reads += node_to_depth[varname_to_nodeid[ alt_id ][i]];

                }
                #pragma omp critical
                it.second.info["AD"].push_back(std::to_string(sum_reads));
            }
            cout << it.second << endl;
        }

    }
    else if (do_all){
        vector<Support> supports;

        for (auto r_path : (graph->paths)._paths){
            if (!regex_match(r_path.first, is_alt)){
                pindexes[r_path.first] = new PathIndex(*graph, r_path.first, true);
            }
        }
        for (auto x_path : (graph->paths)._paths){
            cerr << x_path.first << endl;
            int32_t support = 0;
            if (regex_match(x_path.first, is_alt)){
                vector<Alignment> alns;
                vector<int64_t> var_node_ids;
                for (Mapping x_m : x_path.second){
                    var_node_ids.push_back(x_m.position().node_id());
                }

                std::function<void(const Alignment&)> incr = [&](const Alignment& a){
                    ++support;
                };
                gamind.for_alignment_to_nodes(var_node_ids, incr);
                cout << support << " reads support " << x_path.first << endl;
            }
        }
    }
    else{

        // First, slurp in our discordant, split-read,
        // one-end-anchored, etc reads.
        // basename = *
        // *.gam.split
        // *.gam.oea
        // *.gam.unmapped
        // *.gam.discordant

        ifstream all_reads;
        all_reads.open(gam_name);
        // Reads with no mismatches.
        vector<Alignment> perfects;
        // Reads with anchored mismatches or indels.
        vector<Alignment> simple_mismatches;
        // All the other reads
        vector<Alignment> complex_reads;

        Filter ff;
        vector<Path> simple_paths;

        // TODO expose at CLI
        int min_depth = 5;

        std::function<void(Alignment&)> get_simples_and_perfects = [&](Alignment& aln){
            if (ff.perfect_filter(aln)){
                #pragma omp critical
                perfects.push_back(aln);
            }
            //else if (ff.simple_filter(aln)){
            else if (true){
                #pragma omp critical
                {
                    simple_mismatches.push_back(aln);
                    Path p = trim_hanging_ends(aln.path());
                    simple_paths.push_back(p);
                }
            }
            // else{
            //     #pragma omp critical
            //     complex_reads.push_back(aln);
            // }
        };

        stream::for_each_parallel(all_reads, get_simples_and_perfects);

        if (true){
            cerr << perfects.size() << " perfect reads." << endl;
            cerr << simple_mismatches.size() << " simple reads." << endl;
            cerr << complex_reads.size() << " more complex reads." << endl;
        }

        // Grab our perfect and simple reads
        // incorporate our simple reads.
        // optionally, incorporate all reads and their paths.
        Translator tt;
        vector<Translation> translations = graph->edit(simple_paths);
        tt.load(translations);

        if (augment_paths){

        }

        // Add both simple and perfect reads to the depth map.
        DepthMap dm(graph->size());
        vector<Path> translated;
        translated.reserve(100000);
        for (auto x : simple_mismatches){
            translated.push_back(  tt.translate(x.path()));
        }
        for (auto y : perfects){
            translated.push_back(tt.translate(y.path()));
        }

        dm.fill(translated);

        // Save memory (maybe???) by disposing of our perfects and simples.
        // TODO is clear enough?
        simple_mismatches.clear();
        perfects.clear();

        // Rip out any nodes supported by an insufficient number of reads.
        std::function<void(Node*)> remove_low_depth_nodes = [&](Node* n){
            if (dm.get_depth(n->id()) < min_depth){
                #pragma omp critical
                {
                    graph->destroy_node(n);
                }
            }
        };
        graph->for_each_node_parallel(remove_low_depth_nodes);
        graph->remove_orphan_edges();

        if (!augmented_graph_name.empty()){
            ofstream augstream;
            augstream.open(augmented_graph_name);
            graph->serialize_to_ostream(augstream);
        }
        // You could call SNPs right here. We should also check known variants at this stage.
        // Call snarlmanager, tossing out trivial snarls
        // Report them as either loci or VCF records
        SnarlFinder* snf = new CactusUltrabubbleFinder(*graph, ref_path, true);

        SnarlManager snarl_manager = snf->find_snarls();
        vector<const Snarl*> snarl_roots = snarl_manager.top_level_snarls();
        TraversalFinder* trav_finder;
        if (augment_paths){

        }
        else{
            trav_finder = new ExhaustiveTraversalFinder(*graph, snarl_manager);

        }

        bool justSNPs = false;
        if (justSNPs){
            for (auto x : snarl_roots){
                vector<SnarlTraversal> site_traversals = trav_finder->find_traversals(*x);
                for (auto t : site_traversals){
                    //cout << t.start() << " ";
                    for (auto zed : t.visits()){
                        //cout << zed.node_id() << ", ";
                    }
                    //cout <<  endl;
                }
            }
        }

        // Read in all our nasty discordant/split/clipped reads and
        // filter the nice ones from the nasty ones.

        double expected_insert_size = 500.0;
        double expected_insert_sd = 100.0;

        std::unordered_map<string, Alignment> mates_by_name;
        vector<Alignment> complex_singles;
        vector<Alignment> complex_pairs;

        // for every read in our nasty set, try to normalize it. If we succeed,
        // grab its mate (if appropriate) and generate an IMPRECISE variant based on the two.
        // Place that IMPRECISE candidate somewhere within its predicted range in the graph.

        // If desired, remap our unmapped and nasty reads. This will help us to augment our depth map.

        // call variants

    }

    return 0;
}

static Subcommand vg_srpe ("srpe", "graph-external SV detection", main_srpe);

<commit_msg>Add a few declarations we'll need later.<commit_after>#include <iostream>
#include <vector>
#include <getopt.h>
#include <functional>
#include <regex>
//#include "intervaltree.hpp"
#include "subcommand.hpp"
#include "stream.hpp"
#include "index.hpp"
#include "position.hpp"
#include "vg.pb.h"
#include "path.hpp"
//#include "genotyper.hpp"
#include "genotypekit.hpp"
#include "path_index.hpp"
#include "vg.hpp"
#include "srpe.hpp"
#include "filter.hpp"
#include "utility.hpp"
#include "Variant.h"
#include "translator.hpp"
#include "Fasta.h"

using namespace std;
using namespace vg;
using namespace vg::subcommand;

#define DEBUG

void help_srpe(char** argv){
    cerr << "Usage: " << argv[0] << " srpe [options] <data.gam> <graph.vg>" << endl
        << "Options: " << endl
        << "Variant recall:" << endl
        << "   -S / --specific    <VCF>       look up variants in <VCF> in the graph and report only those." << endl
        << "   -R / --recall                  recall (i.e. type) all variant paths stored in the graph." << endl
        << "   -r / --reference   <REF>       reference genome to pull structural variants from." << endl
        << "   -I / --insertions  <INS>       fasta file containing insertion sequences." << endl
        << "Smart genotyping:" << endl
        << "   -a / --augmented   <AUG>       write the intermediate augmented graph to <AUG>." << endl
        << "   -p / --ref-path   <PATHNAME>   find variants relative to <PATHNAME>" << endl
        << endl;
    //<< "-S / --SV-TYPE comma separated list of SV types to detect (default: all)." << endl

}

int main_srpe(int argc, char** argv){
    string gam_name = "";
    string gam_index_name = "";
    string graph_name = "";
    string xg_name = "";
    string gcsa_name = "";
    string lcp_name = "";

    string spec_vcf = "";
    string ref_fasta = "";
    string ins_fasta = "";

    string augmented_graph_name = "";
    bool augment_paths = true;

    string ref_path = "";

    int max_iter = 2;
    int max_frag_len = 10000;
    int min_soft_clip = 12;

    bool do_all = false;

    vector<string> search_types;
    search_types.push_back("DEL");

    int threads = 1;

    if (argc <= 2) {
        help_srpe(argv);
        return 1;
    }

    int c;
    optind = 2; // force optind past command positional argument
    while (true) {
        static struct option long_options[] =
        {
            {"max-iter", required_argument, 0, 'm'},
            {"xg-index", required_argument, 0, 'x'},
            {"augmented", required_argument, 0, 'a'},
            {"help", no_argument, 0, 'h'},
            {"gcsa-index", required_argument, 0, 'g'},
            {"specific", required_argument, 0, 'S'},
            {"recall", no_argument, 0, 'R'},
            {"insertions", required_argument, 0, 'I'},
            {"reference", required_argument, 0, 'r'},
            {"threads", required_argument, 0, 't'},
            {"ref-path", required_argument, 0, 'p'},
            {0, 0, 0, 0}

        };
        int option_index = 0;
        c = getopt_long (argc, argv, "hx:g:m:S:RI:r:t:a:wp:",
                long_options, &option_index);

        // Detect the end of the options.
        if (c == -1)
            break;

        switch (c)
        {
            case 'a':
                augmented_graph_name = optarg;
                break;
            case 'm':
                max_iter = atoi(optarg);
                break;

            case 't':
                threads = atoi(optarg);
                break;

            case 'R':
                do_all = true;
                break;
            case 'x':
                xg_name = optarg;
                break;
            case 'g':
                gcsa_name = optarg;
                break;
            case 'S':
                spec_vcf = optarg;
                break;
            case 'r':
                ref_fasta = optarg;
                break;
            case 'I':
                ins_fasta = optarg;
                break;
            case 'p':
                ref_path = optarg;
                break;
            case 'h':
            case '?':
            default:
                help_srpe(argv);
                abort();
        }

    }

    omp_set_num_threads(threads);

    //SRPE srpe;

    gam_name = argv[optind];
    //gam_index_name = argv[++optind];
    graph_name = argv[++optind];

    xg::XG* xg_ind = new xg::XG();
    Index gamind;

    vg::VG* graph;

    // if (!xg_name.empty()){
    //     ifstream in(xg_name);
    //     xg_ind->load(in);
    // }
    // if (!gam_index_name.empty()){
    //     gamind.open_read_only(gam_index_name);
    // }
    // else{

    // }

    if (!graph_name.empty()){
        ifstream in(graph_name);
        graph = new VG(in, false);
    }

    // Open a variant call file,
    // hash each variant to an hash ID
    // have in if in the loop below.
    map<string, Locus> name_to_loc;
    // Makes a pathindex, which allows us to query length and push out a VCF with a position
    map<string, PathIndex*> pindexes;
    regex is_alt ("_alt_.*");

    vector<FastaReference*> insertions;
    if (!ins_fasta.empty()){
        FastaReference* ins = new FastaReference();
        insertions.emplace_back(ins);
        ins->open(ins_fasta);

    }

    if (!spec_vcf.empty() && ref_fasta.empty()){
        cerr << "Error: option -S requires a fasta reference using the -r <reference> flag" << endl;
    }
    else if (!spec_vcf.empty()){

        FastaReference* linear_ref = new FastaReference();
        linear_ref->open(ref_fasta);

        for (auto r_path : (graph->paths)._paths){
            if (!regex_match(r_path.first, is_alt)){
                pindexes[r_path.first] = new PathIndex(*graph, r_path.first, true);
            }
        }

        vcflib::VariantCallFile* variant_file = new vcflib::VariantCallFile();
        variant_file->open(spec_vcf);

        string descrip = "";
        descrip = "##INFO=<ID=AD,Number=R,Type=Integer,Description=\"Allele depth for each allele.\"\\>";
        variant_file->addHeaderLine(descrip);

        cout << variant_file->header << endl;

        unordered_map<string, list<Mapping> > graphpaths( (graph->paths)._paths.begin(), (graph->paths)._paths.end() );
        map<string, vcflib::Variant> hash_to_var;
        unordered_map<string, vector<int64_t> > varname_to_nodeid;
        unordered_map<int64_t, int32_t> node_to_depth;
        vector<int64_t> variant_nodes;
        variant_nodes.reserve(10000);

        // Hash a variant from the VCF
        vcflib::Variant var;
        while (variant_file->getNextVariant(var)){
            var.position -= 1;
            var.canonicalize_sv(*linear_ref, insertions, -1);
            string var_id = make_variant_id(var);
            hash_to_var[ var_id ] = var;
            for (int alt_ind = 0; alt_ind <= var.alt.size(); alt_ind++){
                string alt_id = "_alt_" + var_id + "_" + std::to_string(alt_ind);
                list<Mapping> x_path = graphpaths[ alt_id ];
                for (Mapping x_m : x_path){
                    variant_nodes.push_back(x_m.position().node_id());
                    varname_to_nodeid[ alt_id ].push_back(x_m.position().node_id());
                }
            }

        }
        std::function<void(const Alignment& a)> incr = [&](const Alignment& a){
            for (int i = 0; i < a.path().mapping_size(); i++){
                node_to_depth[ a.path().mapping(i).position().node_id() ] += 1;
            }
        };

        gamind.for_alignment_to_nodes(variant_nodes, incr);

        cerr << node_to_depth.size () << " reads in count map" << endl;

        for (auto it : hash_to_var){
            for (int i = 0; i <= it.second.alt.size(); i++){
                int32_t sum_reads = 0;
                string alt_id = "_alt_" + it.first + "_" + std::to_string(i);
                for (int i = 0; i < varname_to_nodeid[ alt_id ].size(); i++){
                    sum_reads += node_to_depth[varname_to_nodeid[ alt_id ][i]];

                }
                #pragma omp critical
                it.second.info["AD"].push_back(std::to_string(sum_reads));
            }
            cout << it.second << endl;
        }

    }
    else if (do_all){
        vector<Support> supports;

        for (auto r_path : (graph->paths)._paths){
            if (!regex_match(r_path.first, is_alt)){
                pindexes[r_path.first] = new PathIndex(*graph, r_path.first, true);
            }
        }
        for (auto x_path : (graph->paths)._paths){
            cerr << x_path.first << endl;
            int32_t support = 0;
            if (regex_match(x_path.first, is_alt)){
                vector<Alignment> alns;
                vector<int64_t> var_node_ids;
                for (Mapping x_m : x_path.second){
                    var_node_ids.push_back(x_m.position().node_id());
                }

                std::function<void(const Alignment&)> incr = [&](const Alignment& a){
                    ++support;
                };
                gamind.for_alignment_to_nodes(var_node_ids, incr);
                cout << support << " reads support " << x_path.first << endl;
            }
        }
    }
    else{

        // First, slurp in our discordant, split-read,
        // one-end-anchored, etc reads.
        // basename = *
        // *.gam.split
        // *.gam.oea
        // *.gam.unmapped
        // *.gam.discordant

        ifstream all_reads;
        all_reads.open(gam_name);
        // Reads with no mismatches.
        vector<Alignment> perfects;
        // Reads with anchored mismatches or indels.
        vector<Alignment> simple_mismatches;
        // All the other reads
        vector<Alignment> complex_reads;

        Filter ff;
        vector<Path> simple_paths;

        // TODO expose at CLI
        int min_depth = 5;

        std::function<void(Alignment&)> get_simples_and_perfects = [&](Alignment& aln){
            if (ff.perfect_filter(aln)){
                #pragma omp critical
                perfects.push_back(aln);
            }
            //else if (ff.simple_filter(aln)){
            else if (true){
                #pragma omp critical
                {
                    simple_mismatches.push_back(aln);
                    Path p = trim_hanging_ends(aln.path());
                    simple_paths.push_back(p);
                }
            }
            // else{
            //     #pragma omp critical
            //     complex_reads.push_back(aln);
            // }
        };

        stream::for_each_parallel(all_reads, get_simples_and_perfects);

        if (true){
            cerr << perfects.size() << " perfect reads." << endl;
            cerr << simple_mismatches.size() << " simple reads." << endl;
            cerr << complex_reads.size() << " more complex reads." << endl;
        }

        // Grab our perfect and simple reads
        // incorporate our simple reads.
        // optionally, incorporate all reads and their paths.
        Translator tt;
        vector<Translation> translations = graph->edit(simple_paths);
        tt.load(translations);

        if (augment_paths){

        }

        // Add both simple and perfect reads to the depth map.
        DepthMap dm(graph->size());
        vector<Path> translated;
        translated.reserve(100000);
        for (auto x : simple_mismatches){
            translated.push_back(  tt.translate(x.path()));
        }
        for (auto y : perfects){
            translated.push_back(tt.translate(y.path()));
        }

        dm.fill(translated);

        // Save memory (maybe???) by disposing of our perfects and simples.
        // TODO is clear enough?
        simple_mismatches.clear();
        perfects.clear();

        // Rip out any nodes supported by an insufficient number of reads.
        std::function<void(Node*)> remove_low_depth_nodes = [&](Node* n){
            if (dm.get_depth(n->id()) < min_depth){
                #pragma omp critical
                {
                    graph->destroy_node(n);
                }
            }
        };
        graph->for_each_node_parallel(remove_low_depth_nodes);
        graph->remove_orphan_edges();

        if (!augmented_graph_name.empty()){
            ofstream augstream;
            augstream.open(augmented_graph_name);
            graph->serialize_to_ostream(augstream);
        }
        // You could call SNPs right here. We should also check known variants at this stage.
        // Call snarlmanager, tossing out trivial snarls
        // Report them as either loci or VCF records
        SnarlFinder* snf = new CactusUltrabubbleFinder(*graph, ref_path, true);

        SnarlManager snarl_manager = snf->find_snarls();
        vector<const Snarl*> snarl_roots = snarl_manager.top_level_snarls();
        TraversalFinder* trav_finder;
        if (augment_paths){

        }
        else{
            trav_finder = new ExhaustiveTraversalFinder(*graph, snarl_manager);

        }

        vector<vector<Locus> > locus_buffer;
        int thread_count = omp_get_num_threads();
        locus_buffer.resize(thread_count);

        vcflib::VariantCallFile* vcf = nullptr;
        vector<PathIndex*> pindexes;

        bool justSNPs = false;
        if (justSNPs){

            for (auto x : snarl_roots){
                vector<SnarlTraversal> site_traversals = trav_finder->find_traversals(*x);
                for (auto t : site_traversals){
                    //cout << t.start() << " ";
                    for (auto zed : t.visits()){
                        //cout << zed.node_id() << ", ";
                    }
                    //cout <<  endl;
                }
            }
        }

        // Read in all our nasty discordant/split/clipped reads and
        // filter the nice ones from the nasty ones.

        double expected_insert_size = 500.0;
        double expected_insert_sd = 100.0;

        std::unordered_map<string, Alignment> mates_by_name;
        vector<Alignment> complex_singles;
        vector<Alignment> complex_pairs;

        // for every read in our nasty set, try to normalize it. If we succeed,
        // grab its mate (if appropriate) and generate an IMPRECISE variant based on the two.
        // Place that IMPRECISE candidate somewhere within its predicted range in the graph.

        // If desired, remap our unmapped and nasty reads. This will help us to augment our depth map.

        // call variants

    }

    return 0;
}

static Subcommand vg_srpe ("srpe", "graph-external SV detection", main_srpe);

<|endoftext|>


<commit_before>/*
    TSIframework . Framework for Taller de Sistemes Interactius I
    Universitat Pompeu Fabra

    Copyright (c) 2009 Daniel Gallardo Grassot <daniel.gallardo@upf.edu>

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use,
    copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following
    conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.

*/

#ifndef TANGIBLE_HPP_INCLUDED
#define TANGIBLE_HPP_INCLUDED
#include "Graphic.hpp"
#include "DirectPoint.h"
#include "Shapes.hpp"
#include "tuioApp.h"
#include "InputGestureBasicObjects.h"
#include "InputGestureDirectObjects.h"
#include "InputGestureObjectFinger.h"

template< int figure_id>
class Tangible:public tuio::CanObjectFinger < tuio::CanBasicObjects < tuio::CanDirectObjects < Graphic > > >
{
    private:
        tuio::DirectObject data;
        bool enable;
    public:
        Tangible():enable(false){
            data.f_id = figure_id;
        }
        virtual ~Tangible(){}
        virtual tuio::DirectObject& GetPoint(){return data;}
        virtual bool IsEnabled(){return enable;}
    protected:
        void Enable(bool flag = true){enable = flag;}
        ///Graphic methods
        virtual void draw(){
            ///not needed, it is drawn by FigureFeedback
//            ofPushMatrix();
//            ofTranslate(p.xpos,p.ypos);
//            ofRotate(angle*180/M_PI);
//            shapes::Figure_shape::Instance().drawShape(fid);
//            ofPopMatrix();
        }
        virtual void update(){}
        virtual void resize(int x, int y){}
    public:
        ///CanDirectObjects methods
        virtual void newObject(int32 s_id, int32 f_id, tuio::DirectObject * object){
            if( data.f_id == f_id){
                data = tuio::DirectObject(*object);
                Enable(true);
            }
        }
        virtual void removeObject(int32 s_id, int32 f_id){
            if( data.f_id == f_id ){
                Enable(false);
            }
        }
        virtual void updateTuioObject(int32 id, int32 f_id ,float xpos,float ypos, float angle, float xspeed,float yspeed,float rspeed,float maccel, float raccel){
            if( data.f_id == f_id){
                data = tuio::DirectObject( id,  f_id , xpos, ypos,  angle,  xspeed, yspeed, rspeed, maccel,  raccel);
            }
        }
        ///CanObjectFinger methods
        virtual void objectFingerAdd(tuio::DirectObject* obj, tuio::DirectFinger* finger) {}
        virtual void objectFingerUpdate(tuio::DirectObject* obj, tuio::DirectFinger* finger) {}
        virtual void objectFingerRemove(tuio::DirectObject* obj, tuio::DirectFinger* finger) {}
        virtual void objectFingerTap(tuio::DirectObject* obj, float x, float y) {}
};

template <class Base, int triangle_distance>
class ShowAngleArrow:public Base
{
    public:
    virtual tuio::DirectObject& GetPoint(){return Base::GetPoint();}
    virtual bool IsEnabled(){return Base::IsEnabled();}
    protected:
    virtual void draw(){
        if(IsEnabled()){
            ofPushMatrix();
            ofTranslate(GetPoint().xpos*ofGetWidth(), GetPoint().ypos*ofGetHeight());
            ofRotate(GetPoint().angle*180/M_PI);
            ofTranslate(0,triangle_distance);
            ofSetColor(0xFFFFFF);
            ofTriangle(-7,5,0,0,7,5);
            ofPopMatrix();
            Base::draw();
        }
    }
};

#endif // TANGIBLE_HPP_INCLUDED
<commit_msg>Tangible no longer CanBasicFingers<commit_after>/*
    TSIframework . Framework for Taller de Sistemes Interactius I
    Universitat Pompeu Fabra

    Copyright (c) 2009 Daniel Gallardo Grassot <daniel.gallardo@upf.edu>

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use,
    copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following
    conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.

*/

#ifndef TANGIBLE_HPP_INCLUDED
#define TANGIBLE_HPP_INCLUDED
#include "Graphic.hpp"
#include "DirectPoint.h"
#include "Shapes.hpp"
#include "tuioApp.h"
#include "InputGestureBasicObjects.h"
#include "InputGestureDirectObjects.h"
#include "InputGestureObjectFinger.h"

template< int figure_id>
class Tangible:public tuio::CanObjectFinger < tuio::CanDirectObjects < Graphic > >
{
    private:
        tuio::DirectObject * data;
        bool enable;
    public:
        Tangible():enable(false){
        }
        virtual ~Tangible(){}
        virtual tuio::DirectObject& GetPoint(){return *data;}
        virtual bool IsEnabled(){return enable;}
    protected:
        void Enable(bool flag = true){enable = flag;}
        ///Graphic methods
        virtual void draw(){
            ///not needed, it is drawn by FigureFeedback
//            ofPushMatrix();
//            ofTranslate(p.xpos,p.ypos);
//            ofRotate(angle*180/M_PI);
//            shapes::Figure_shape::Instance().drawShape(fid);
//            ofPopMatrix();
        }
        virtual void update(){}
        virtual void resize(int x, int y){}
    public:
        ///CanDirectObjects methods
        virtual void newObject(int32 s_id, int32 f_id, tuio::DirectObject * object){
            if( figure_id == f_id){
                data = object;
                Enable(true);
            }
        }
        virtual void removeObject(int32 s_id, int32 f_id){
            if( figure_id == f_id ){
                //data = NULL //???
                Enable(false);
            }
        }
        ///CanObjectFinger methods
        virtual void objectFingerAdd(tuio::DirectObject* obj, tuio::DirectFinger* finger) {}
        virtual void objectFingerUpdate(tuio::DirectObject* obj, tuio::DirectFinger* finger) {}
        virtual void objectFingerRemove(tuio::DirectObject* obj, tuio::DirectFinger* finger) {}
        virtual void objectFingerTap(tuio::DirectObject* obj, float x, float y) {}
};

template <class Base, int triangle_distance>
class ShowAngleArrow:public Base
{
    public:
    virtual tuio::DirectObject& GetPoint(){return Base::GetPoint();}
    virtual bool IsEnabled(){return Base::IsEnabled();}
    protected:
    virtual void draw(){
        if(IsEnabled()){
            ofPushMatrix();
            ofTranslate(GetPoint().xpos*ofGetWidth(), GetPoint().ypos*ofGetHeight());
            ofRotate(GetPoint().angle*180/M_PI);
            ofTranslate(0,triangle_distance);
            ofSetColor(0xFFFFFF);
            ofTriangle(-7,5,0,0,7,5);
            ofPopMatrix();
            Base::draw();
        }
    }
};

#include "Tangible-ShowObjectSlider.h"

#endif // TANGIBLE_HPP_INCLUDED
<|endoftext|>


<commit_before>#include "linuxapi.h"

#ifdef __linux__
#include <X11/X.h>
#include <X11/Xlib.h>
#include <GL/glx.h>

#undef Always // in X11/X.h
#undef PSize

#include <Tempest/Window>
#include <Tempest/Event>
#include <Tempest/DisplaySettings>

#include <unordered_map>
#include <fstream>
#include <Tempest/Assert>

#include <iostream>
#include "core/wrappers/atomic.h"

typedef Window HWND;

using namespace Tempest;

static std::unordered_map<HWND, Tempest::Window*> wndWx;

static Display*  dpy  = 0;
static HWND      root = 0;

static const long event_mask = 0xFFFFFF;

static HWND pin( LinuxAPI::Window* w ){
  return *((HWND*)w);
  }

static void xProc(XEvent& xev, HWND &hWnd, bool &quit);

static Atom& wmDeleteMessage(){
  static Atom w  = XInternAtom( dpy, "WM_DELETE_WINDOW", 0);
  return w;
  }

static LinuxAPI::Window* X11_CreateWindow( int w, int h,
                                           Tempest::Window::ShowMode m ){
  HWND * win = new HWND;
  GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
  XVisualInfo * vi = glXChooseVisual(dpy, 0, att);
  XSetWindowAttributes    swa;

  Colormap cmap;
  cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);

  swa.colormap   = cmap;
  swa.event_mask = event_mask ^ (ResizeRedirectMask);

  *win = XCreateWindow( dpy, root, 0, 0, w, h,
                        0, vi->depth, InputOutput, vi->visual,
                        CWColormap | CWEventMask, &swa );
  XSetWMProtocols(dpy, *win, &wmDeleteMessage(), 1);

  XStoreName(dpy, *win, "Tempest Application");

  XFreeColormap( dpy, cmap );
  XFree(vi);
  return (LinuxAPI::Window*)win;
  }

LinuxAPI::LinuxAPI() {
  TranslateKeyPair k[] = {
    { XK_KP_Left,   Event::K_Left   },
    { XK_KP_Right,  Event::K_Right  },
    { XK_KP_Up,     Event::K_Up     },
    { XK_KP_Down,   Event::K_Down   },

    { XK_Escape, Event::K_ESCAPE },
    { XK_BackSpace,   Event::K_Back   },
    { XK_Delete, Event::K_Delete },
    { XK_Insert, Event::K_Insert },
    { XK_Home,   Event::K_Home   },
    { XK_End,    Event::K_End    },
    { XK_Pause,  Event::K_Pause  },
    { XK_Return, Event::K_Return },

    { XK_F1,     Event::K_F1 },
    { 0x30,      Event::K_0  },
    { 0x41,      Event::K_A  },

    { 0,         Event::K_NoKey }
    };

  setupKeyTranslate(k);
  setFuncKeysCount(24);
  }

LinuxAPI::~LinuxAPI() {
  }

void *LinuxAPI::display() {
  return dpy;
  }

bool LinuxAPI::testDisplaySettings( const DisplaySettings & s ) {
  return 1;
  }

bool LinuxAPI::setDisplaySettings( const DisplaySettings &s ) {
  return 0;
  }

Size LinuxAPI::implScreenSize() {
  Screen * scr = XDefaultScreenOfDisplay(dpy);
  int w = XWidthOfScreen (scr);
  int h = XHeightOfScreen(scr);

  return Size(w,h);
  }

void LinuxAPI::startApplication(ApplicationInitArgs *) {
  dpy = XOpenDisplay(NULL);

  if(dpy == NULL) {
    T_ASSERT_X( dpy, "cannot connect to X server!");
    exit(0);
    }

  root = DefaultRootWindow(dpy);
  }

void LinuxAPI::endApplication() {
  XCloseDisplay(dpy);
  }

static void render( Tempest::Window* w ){
  if( w->showMode()!=Tempest::Window::Minimized && w->isActive() )
    w->render();
  }

int LinuxAPI::nextEvent(bool &quit) {
  XEvent xev;
  memset(&xev,0,sizeof(xev));

  if( !XPending(dpy) ){
    XNextEvent(dpy, &xev);
    for( auto i=wndWx.begin(); i!=wndWx.end(); ++i )
      render( i->second );
    return 0;
    }

  xProc( xev, xev.xclient.window, quit);
  //Sleep(0);
  return 0;
  }

int LinuxAPI::nextEvents(bool &quit) {
  XEvent xev;
  memset(&xev,0,sizeof(xev));

  while( !quit ){
    if( XPending( dpy ) ){
      XNextEvent(dpy, &xev);
      xProc( xev, xev.xclient.window, quit );
      } else {
      for( auto i=wndWx.begin(); i!=wndWx.end(); ++i )
        render( i->second );
      return 0;
      }
    }

  return 0;
  }

LinuxAPI::Window *LinuxAPI::createWindow(int w, int h) {
  return X11_CreateWindow(w, h, Tempest::Window::Normal );
  }

SystemAPI::Window *LinuxAPI::createWindowMaximized() {
  return X11_CreateWindow( 800, 600, Tempest::Window::Maximized );
  }

SystemAPI::Window *LinuxAPI::createWindowMinimized() {
  return X11_CreateWindow( 800, 600, Tempest::Window::Minimized );
  }

SystemAPI::Window *LinuxAPI::createWindowFullScr() {
  return X11_CreateWindow( 800, 600, Tempest::Window::FullScreen );
  }

Widget* LinuxAPI::addOverlay(WindowOverlay *ov) {
  if( wndWx.empty() ){
    delete ov;
    return 0;
    }

  Tempest::Window* w = wndWx.begin()->second;
  SystemAPI::addOverlay(w, ov);
  return ov;
  }

Point LinuxAPI::windowClientPos( SystemAPI::Window * hWnd ) {
  XWindowAttributes xwa;
  XGetWindowAttributes(dpy, pin(hWnd), &xwa);

  return Point( xwa.x, xwa.y );
  }

Size LinuxAPI::windowClientRect( SystemAPI::Window * hWnd ) {
  XWindowAttributes xwa;
  XGetWindowAttributes(dpy, pin(hWnd), &xwa);

  return Size( xwa.width, xwa.height );
  }

void LinuxAPI::deleteWindow( Window *w ) {
  XDestroyWindow(dpy, pin(w));
  wndWx.erase( pin(w) );
  delete (HWND*)w;
  }

void LinuxAPI::show(Window *hWnd) {
  XMapWindow(dpy, pin(hWnd) );
  }

void LinuxAPI::setGeometry( Window *hw, int x, int y, int w, int h ) {
  XMoveResizeWindow( dpy, *((::Window*)hw), x, y, w, h );
  }

void LinuxAPI::bind( Window *w, Tempest::Window *wx ) {
  wndWx[ pin(w) ] = wx;
  }

LinuxAPI::CpuInfo LinuxAPI::cpuInfoImpl(){
  CpuInfo info;
  memset(&info, 0, sizeof(info));

  info.cpuCount = 1;
  return info;
  }

LinuxAPI::File *LinuxAPI::fopenImpl( const char *fname, const char *mode ) {
  return SystemAPI::fopenImpl( fname, mode );
  }

LinuxAPI::File *LinuxAPI::fopenImpl( const char16_t *fname, const char *mode ) {
  return SystemAPI::fopenImpl( toUtf8(fname).data(), mode );
  }

static Event::MouseButton toButton( XButtonEvent& msg ){
  if( msg.button==Button1 )
    return Event::ButtonLeft;

  if( msg.button==Button3 )
    return Event::ButtonRight;

  if( msg.button==Button2 )
    return Event::ButtonMid;

  return Event::ButtonNone;
  }

static Tempest::KeyEvent makeKeyEvent( XKeyEvent& k,
                                       bool scut = false ){
  Tempest::KeyEvent::KeyType e = SystemAPI::translateKey(k.keycode);

  if( !scut ){
    if( Event::K_0<=e && e<= Event::K_9 )
      e = Tempest::KeyEvent::K_NoKey;

    if( Event::K_A<=e && e<= Event::K_Z )
      e = Tempest::KeyEvent::K_NoKey;
    }

  return Tempest::KeyEvent( e );
  }

void xProc( XEvent& xev, HWND &hWnd, bool &quit ) {
    Tempest::Window* w = 0;
    std::unordered_map<HWND, Tempest::Window*>::iterator i
        = wndWx.find( hWnd );

    if( i!= wndWx.end() )
      w = i->second;

    if( !w )
      return;

    {
      HWND root;
      int x, y;
      unsigned ww, hh, border, depth;

      if( XGetGeometry(dpy, hWnd, &root, &x, &y, &ww, &hh, &border, &depth) ){
        SystemAPI::moveEvent( w, x, y );
        SystemAPI::sizeEvent( w, ww, hh );
        }
    }

    std::cout <<"xev = " << xev.type << std::endl;
    switch( xev.type ) {
      case Expose:
        if ( xev.xexpose.count == 0){
          render( w );
          }
        break;

    /*
      case WM_CHAR:
      {
         Tempest::KeyEvent e = Tempest::KeyEvent( uint32_t(wParam) );

         DWORD wrd[3] = {
           VK_RETURN,
           VK_BACK,
           0
           };

         if( 0 == *std::find( wrd, wrd+2, wParam) ){
           Tempest::KeyEvent ed( e.key, e.u16, Event::KeyDown );
           SystemAPI::emitEvent(w, ed);

           Tempest::KeyEvent eu( e.key, e.u16, Event::KeyUp );
           SystemAPI::emitEvent(w, eu);
           }
      }
      break;*/

      case KeyPressMask:
      {
         SystemAPI::emitEvent( w,
                               makeKeyEvent( xev.xkey ),
                               makeKeyEvent( xev.xkey, true),
                               Event::KeyDown );
      }
      break;

      case KeyRelease:
      {
         SystemAPI::emitEvent( w,
                               makeKeyEvent( xev.xkey ),
                               makeKeyEvent( xev.xkey, true),
                               Event::KeyUp );
      }
      break;

      case ButtonPress:
      case ButtonRelease: {
        bool isWheel = false;
        if( xev.type==ButtonPress && XPending(dpy) ){
          XEvent ev;
          XPeekEvent(dpy, &ev);
          isWheel = (ev.type==ButtonRelease);
          }

        if( isWheel ){
          int ticks = 0;
          if( xev.xbutton.button == Button4 ) {
            ticks = 1;
            }
          else if ( xev.xbutton.button == Button5 ) {
            ticks = -1;
            }
          Tempest::MouseEvent e( xev.xbutton.x,
                                 xev.xbutton.y,
                                 Tempest::Event::ButtonNone,
                                 ticks,
                                 0,
                                 Event::MouseWheel );
          SystemAPI::emitEvent(w, e);
          } else {
          MouseEvent e( xev.xbutton.x,
                        xev.xbutton.y,
                        toButton( xev.xbutton ),
                        0,
                        0,
                        xev.type==ButtonPress ? Event::MouseDown : Event::MouseUp );
          SystemAPI::emitEvent(w, e);
          }
        }
        break;

      case MotionNotify: {
        MouseEvent e( xev.xmotion.x,
                      xev.xmotion.y,
                      Event::ButtonNone,
                      0,
                      0,
                      Event::MouseMove  );
        std::cout << "motion" << std::endl;
        SystemAPI::emitEvent(w, e);
        }
        break;
/*
      case WM_ACTIVATEAPP:
      {
          bool a = (wParam==TRUE);
          SystemAPI::activateEvent(w,a);

          if( !a && w->isFullScreenMode() ){
            ShowWindow( hWnd, SW_MINIMIZE );
            }
      }
      break;*/

      case ClientMessage:{
        if( xev.xclient.data.l[0] == long(wmDeleteMessage()) ){
          Tempest::CloseEvent e;
          SystemAPI::emitEvent(w, e);
          if( !e.isAccepted() )
            quit = true;
          }
        }
        break;

      case DestroyNotify:{
        quit = true;
        }
        break;

      default: break;
      }

    return;
    }

#endif
<commit_msg>improve wheel recognation<commit_after>#include "linuxapi.h"

#ifdef __linux__
#include <X11/X.h>
#include <X11/Xlib.h>
#include <GL/glx.h>

#undef Always // in X11/X.h
#undef PSize

#include <Tempest/Window>
#include <Tempest/Event>
#include <Tempest/DisplaySettings>

#include <unordered_map>
#include <fstream>
#include <Tempest/Assert>

#include <iostream>
#include "core/wrappers/atomic.h"

typedef Window HWND;

using namespace Tempest;

static std::unordered_map<HWND, Tempest::Window*> wndWx;

static Display*  dpy  = 0;
static HWND      root = 0;

static const long event_mask = 0xFFFFFF;

static HWND pin( LinuxAPI::Window* w ){
  return *((HWND*)w);
  }

static void xProc(XEvent& xev, HWND &hWnd, bool &quit);

static Atom& wmDeleteMessage(){
  static Atom w  = XInternAtom( dpy, "WM_DELETE_WINDOW", 0);
  return w;
  }

static LinuxAPI::Window* X11_CreateWindow( int w, int h,
                                           Tempest::Window::ShowMode m ){
  HWND * win = new HWND;
  GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
  XVisualInfo * vi = glXChooseVisual(dpy, 0, att);
  XSetWindowAttributes    swa;

  Colormap cmap;
  cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);

  swa.colormap   = cmap;
  swa.event_mask = event_mask ^ (ResizeRedirectMask);

  *win = XCreateWindow( dpy, root, 0, 0, w, h,
                        0, vi->depth, InputOutput, vi->visual,
                        CWColormap | CWEventMask, &swa );
  XSetWMProtocols(dpy, *win, &wmDeleteMessage(), 1);

  XStoreName(dpy, *win, "Tempest Application");

  XFreeColormap( dpy, cmap );
  XFree(vi);
  return (LinuxAPI::Window*)win;
  }

LinuxAPI::LinuxAPI() {
  TranslateKeyPair k[] = {
    { XK_KP_Left,   Event::K_Left   },
    { XK_KP_Right,  Event::K_Right  },
    { XK_KP_Up,     Event::K_Up     },
    { XK_KP_Down,   Event::K_Down   },

    { XK_Escape, Event::K_ESCAPE },
    { XK_BackSpace,   Event::K_Back   },
    { XK_Delete, Event::K_Delete },
    { XK_Insert, Event::K_Insert },
    { XK_Home,   Event::K_Home   },
    { XK_End,    Event::K_End    },
    { XK_Pause,  Event::K_Pause  },
    { XK_Return, Event::K_Return },

    { XK_F1,     Event::K_F1 },
    { 0x30,      Event::K_0  },
    { 0x41,      Event::K_A  },

    { 0,         Event::K_NoKey }
    };

  setupKeyTranslate(k);
  setFuncKeysCount(24);
  }

LinuxAPI::~LinuxAPI() {
  }

void *LinuxAPI::display() {
  return dpy;
  }

bool LinuxAPI::testDisplaySettings( const DisplaySettings & s ) {
  return 1;
  }

bool LinuxAPI::setDisplaySettings( const DisplaySettings &s ) {
  return 0;
  }

Size LinuxAPI::implScreenSize() {
  Screen * scr = XDefaultScreenOfDisplay(dpy);
  int w = XWidthOfScreen (scr);
  int h = XHeightOfScreen(scr);

  return Size(w,h);
  }

void LinuxAPI::startApplication(ApplicationInitArgs *) {
  dpy = XOpenDisplay(NULL);

  if(dpy == NULL) {
    T_ASSERT_X( dpy, "cannot connect to X server!");
    exit(0);
    }

  root = DefaultRootWindow(dpy);
  }

void LinuxAPI::endApplication() {
  XCloseDisplay(dpy);
  }

static void render( Tempest::Window* w ){
  if( w->showMode()!=Tempest::Window::Minimized && w->isActive() )
    w->render();
  }

int LinuxAPI::nextEvent(bool &quit) {
  XEvent xev;
  memset(&xev,0,sizeof(xev));

  if( !XPending(dpy) ){
    XNextEvent(dpy, &xev);
    for( auto i=wndWx.begin(); i!=wndWx.end(); ++i )
      render( i->second );
    return 0;
    }

  xProc( xev, xev.xclient.window, quit);
  //Sleep(0);
  return 0;
  }

int LinuxAPI::nextEvents(bool &quit) {
  XEvent xev;
  memset(&xev,0,sizeof(xev));

  while( !quit ){
    if( XPending( dpy ) ){
      XNextEvent(dpy, &xev);
      xProc( xev, xev.xclient.window, quit );
      } else {
      for( auto i=wndWx.begin(); i!=wndWx.end(); ++i )
        render( i->second );
      return 0;
      }
    }

  return 0;
  }

LinuxAPI::Window *LinuxAPI::createWindow(int w, int h) {
  return X11_CreateWindow(w, h, Tempest::Window::Normal );
  }

SystemAPI::Window *LinuxAPI::createWindowMaximized() {
  return X11_CreateWindow( 800, 600, Tempest::Window::Maximized );
  }

SystemAPI::Window *LinuxAPI::createWindowMinimized() {
  return X11_CreateWindow( 800, 600, Tempest::Window::Minimized );
  }

SystemAPI::Window *LinuxAPI::createWindowFullScr() {
  return X11_CreateWindow( 800, 600, Tempest::Window::FullScreen );
  }

Widget* LinuxAPI::addOverlay(WindowOverlay *ov) {
  if( wndWx.empty() ){
    delete ov;
    return 0;
    }

  Tempest::Window* w = wndWx.begin()->second;
  SystemAPI::addOverlay(w, ov);
  return ov;
  }

Point LinuxAPI::windowClientPos( SystemAPI::Window * hWnd ) {
  XWindowAttributes xwa;
  XGetWindowAttributes(dpy, pin(hWnd), &xwa);

  return Point( xwa.x, xwa.y );
  }

Size LinuxAPI::windowClientRect( SystemAPI::Window * hWnd ) {
  XWindowAttributes xwa;
  XGetWindowAttributes(dpy, pin(hWnd), &xwa);

  return Size( xwa.width, xwa.height );
  }

void LinuxAPI::deleteWindow( Window *w ) {
  XDestroyWindow(dpy, pin(w));
  wndWx.erase( pin(w) );
  delete (HWND*)w;
  }

void LinuxAPI::show(Window *hWnd) {
  XMapWindow(dpy, pin(hWnd) );
  }

void LinuxAPI::setGeometry( Window *hw, int x, int y, int w, int h ) {
  XMoveResizeWindow( dpy, *((::Window*)hw), x, y, w, h );
  }

void LinuxAPI::bind( Window *w, Tempest::Window *wx ) {
  wndWx[ pin(w) ] = wx;
  }

LinuxAPI::CpuInfo LinuxAPI::cpuInfoImpl(){
  CpuInfo info;
  memset(&info, 0, sizeof(info));

  info.cpuCount = 1;
  return info;
  }

LinuxAPI::File *LinuxAPI::fopenImpl( const char *fname, const char *mode ) {
  return SystemAPI::fopenImpl( fname, mode );
  }

LinuxAPI::File *LinuxAPI::fopenImpl( const char16_t *fname, const char *mode ) {
  return SystemAPI::fopenImpl( toUtf8(fname).data(), mode );
  }

static Event::MouseButton toButton( XButtonEvent& msg ){
  if( msg.button==Button1 )
    return Event::ButtonLeft;

  if( msg.button==Button3 )
    return Event::ButtonRight;

  if( msg.button==Button2 )
    return Event::ButtonMid;

  return Event::ButtonNone;
  }

static Tempest::KeyEvent makeKeyEvent( XKeyEvent& k,
                                       bool scut = false ){
  Tempest::KeyEvent::KeyType e = SystemAPI::translateKey(k.keycode);

  if( !scut ){
    if( Event::K_0<=e && e<= Event::K_9 )
      e = Tempest::KeyEvent::K_NoKey;

    if( Event::K_A<=e && e<= Event::K_Z )
      e = Tempest::KeyEvent::K_NoKey;
    }

  return Tempest::KeyEvent( e );
  }

void xProc( XEvent& xev, HWND &hWnd, bool &quit ) {
    Tempest::Window* w = 0;
    std::unordered_map<HWND, Tempest::Window*>::iterator i
        = wndWx.find( hWnd );

    if( i!= wndWx.end() )
      w = i->second;

    if( !w )
      return;

    {
      HWND root;
      int x, y;
      unsigned ww, hh, border, depth;

      if( XGetGeometry(dpy, hWnd, &root, &x, &y, &ww, &hh, &border, &depth) ){
        SystemAPI::moveEvent( w, x, y );
        SystemAPI::sizeEvent( w, ww, hh );
        }
    }

    std::cout <<"xev = " << xev.type << std::endl;
    switch( xev.type ) {
      case Expose:
        if ( xev.xexpose.count == 0){
          render( w );
          }
        break;

    /*
      case WM_CHAR:
      {
         Tempest::KeyEvent e = Tempest::KeyEvent( uint32_t(wParam) );

         DWORD wrd[3] = {
           VK_RETURN,
           VK_BACK,
           0
           };

         if( 0 == *std::find( wrd, wrd+2, wParam) ){
           Tempest::KeyEvent ed( e.key, e.u16, Event::KeyDown );
           SystemAPI::emitEvent(w, ed);

           Tempest::KeyEvent eu( e.key, e.u16, Event::KeyUp );
           SystemAPI::emitEvent(w, eu);
           }
      }
      break;*/

      case KeyPressMask:
      {
         SystemAPI::emitEvent( w,
                               makeKeyEvent( xev.xkey ),
                               makeKeyEvent( xev.xkey, true),
                               Event::KeyDown );
      }
      break;

      case KeyRelease:
      {
         SystemAPI::emitEvent( w,
                               makeKeyEvent( xev.xkey ),
                               makeKeyEvent( xev.xkey, true),
                               Event::KeyUp );
      }
      break;

      case ButtonPress:
      case ButtonRelease: {
        bool isWheel = false;
        if( xev.type==ButtonPress && XPending(dpy) &&
            (xev.xbutton.button == Button4 || xev.xbutton.button == Button5) ){
          XEvent ev;
          XPeekEvent(dpy, &ev);
          isWheel = (ev.type==ButtonRelease);
          }

        if( isWheel ){
          int ticks = 0;
          if( xev.xbutton.button == Button4 ) {
            ticks = 1;
            }
          else if ( xev.xbutton.button == Button5 ) {
            ticks = -1;
            }
          Tempest::MouseEvent e( xev.xbutton.x,
                                 xev.xbutton.y,
                                 Tempest::Event::ButtonNone,
                                 ticks,
                                 0,
                                 Event::MouseWheel );
          SystemAPI::emitEvent(w, e);
          } else {
          MouseEvent e( xev.xbutton.x,
                        xev.xbutton.y,
                        toButton( xev.xbutton ),
                        0,
                        0,
                        xev.type==ButtonPress ? Event::MouseDown : Event::MouseUp );
          SystemAPI::emitEvent(w, e);
          }
        }
        break;

      case MotionNotify: {
        MouseEvent e( xev.xmotion.x,
                      xev.xmotion.y,
                      Event::ButtonNone,
                      0,
                      0,
                      Event::MouseMove  );
        std::cout << "motion" << std::endl;
        SystemAPI::emitEvent(w, e);
        }
        break;
/*
      case WM_ACTIVATEAPP:
      {
          bool a = (wParam==TRUE);
          SystemAPI::activateEvent(w,a);

          if( !a && w->isFullScreenMode() ){
            ShowWindow( hWnd, SW_MINIMIZE );
            }
      }
      break;*/

      case ClientMessage:{
        if( xev.xclient.data.l[0] == long(wmDeleteMessage()) ){
          Tempest::CloseEvent e;
          SystemAPI::emitEvent(w, e);
          if( !e.isAccepted() )
            quit = true;
          }
        }
        break;

      case DestroyNotify:{
        quit = true;
        }
        break;

      default: break;
      }

    return;
    }

#endif
<|endoftext|>


<commit_before>#ifndef DEAMORTIZED_HASH_SET
#define DEAMORTIZED_HASH_SET

#include <cstdint>
#include <functional>
#include <cstdlib>
#include <cassert>
#include <cstddef>
#include <memory>
#include <vector>

using std::vector;
using std::pair;
using std::make_pair;

#include "tlsf_allocator.hpp"

template<typename Key,
         typename Hash = std::hash<Key>,
         typename Equal = std::equal_to<Key>,
         typename Allocate = TlsfAllocator<Key> >
class LimitedHashSet {
  typedef std::size_t size_t;
public:

  LimitedHashSet& operator=(const LimitedHashSet&) = delete;
  LimitedHashSet(const LimitedHashSet&) = delete;
  LimitedHashSet(LimitedHashSet&&) = delete;
  LimitedHashSet& operator=(LimitedHashSet&&) = delete;

public:

  struct Slot {
    bool occupied;
    Key key;
  };
  Hash hasher;
  Equal equaler;
  typedef typename Allocate::template rebind<Slot>::other A;
  A allocator;
  size_t capacity, size;
  Slot * data;
  size_t progress;
  enum ACT : char {
    CLEAR, INIT, RESET, FILL
  } state;

public:

  // TODO: overload for std::swap
  // TODO: copy and move and assignment constructors
  void swap(LimitedHashSet & that) {
    std::swap(allocator, that.allocator);
    std::swap(capacity, that.capacity);
    std::swap(size, that.size);
    std::swap(data, that.data);
    std::swap(progress, that.progress);
    std::swap(state, that.state);
  }

  explicit LimitedHashSet(const Allocate& a, const size_t capacity)
    : hasher(), equaler(), allocator(a), capacity(capacity), size(0),
      data(allocator.allocate(capacity)), progress(0), state(INIT)
  {}

  // TODO: this need to take state into account
  ~LimitedHashSet() {
    switch (state) {
    case CLEAR:
      while (progress < capacity) {
        allocator.destroy(&data[progress++]);
      }
      break;
    case INIT: // no data - still initializing
      break;
    case RESET: // no data - not even initialized yet
      break;
    case FILL:
      for (size_t i = 0; i < capacity; ++i) {
        if (data[i].occupied) {
          allocator.destroy(&data[i]);
        }
      }
    }
    allocator.deallocate(data, capacity);
  }

  void clear(const size_t left) {
    assert ((0 == capacity) || (state == FILL) || (state == CLEAR));
    if (state == FILL) {
      progress = 0;
    }
    state = CLEAR;
    const size_t many = left ? ((capacity - progress + left - 1)/left) : (capacity - progress);
    for (size_t i = 0; i < many; ++i) {
      if (data[progress].occupied) allocator.destroy(&data[progress]);
      ++progress;
    }
  }

  void init(const size_t left) {
    assert ((0 == capacity) || (state == RESET) || (state == INIT));
    if (RESET == state) {
      progress = 0;
    }
    state = INIT;
    const size_t many = left ? ((capacity - progress + left - 1)/left) : (capacity - progress);
    for (size_t i = 0; i < many; ++i) {
      data[progress].occupied = false;
      ++progress;
    }
  }

  void reset(const size_t new_capacity) {
    assert ((0 == capacity) || (state == CLEAR));
    state = RESET;
    size = 0;
    if (new_capacity != capacity) {
      allocator.deallocate(data, capacity);
      capacity = new_capacity;
      data = allocator.allocate(capacity);
    }
    progress = 0;
  }

  void fill(const size_t left, const LimitedHashSet& that) {
    assert ((0 == capacity) || (state == FILL) || (state == INIT));
    if (INIT == state) {
      progress = 0;
    }
    state = FILL;
    // don't care about *my* progress
    const size_t many = left ? ((that.capacity - progress + left - 1)/left) : (capacity - progress);
    for (size_t i = 0; i < many; ++i) {
      if (that.data[progress].occupied) insert(that.data[progress].key);
      ++progress;
    }
  }

  void catch_up(const vector<pair<Key *, pair<size_t, size_t> > > & moved_back) {
    for (const auto & kft : moved_back) {
      if ((kft.second.first >= progress)
          and (kft.second.second < progress)) {
        insert(*kft.first);
      }
    }
  }

private:

  // find a key. capacity must be > 0. if key is not present, returns
  // location where it would be if it were newly placed.
  size_t locate(const Key& k) const {
    const size_t cap_mask = capacity-1;
    auto h = hasher(k) & cap_mask;
    while (true) {
      if (not data[h].occupied)    return h;
      if (equaler(data[h].key, k)) return h;
      h = (h+1) & cap_mask;
    }
  }

  // i < j <= k, mod capacity
  static bool cyclic_between(const size_t& i, const size_t& j, const size_t& k) {
    return (((i < j) and (j <= k))
            or ((i < j) and (k < i))
            or ((j <= k) and (k < i)));
  }

public:
  Key* find(const Key& k) {
    if (NULL == data) return nullptr;
    const size_t i = locate(k);
    if (data[i].occupied && equaler(data[i].key, k)) {
      return &data[i].key;
    }
    return nullptr;
  }

public:

  vector<pair<Key *, pair<size_t, size_t> > > erase(const Key& k) {
    vector<pair<Key *, pair<size_t, size_t> > > ans;
    const size_t cap_mask = capacity-1;
    size_t start = locate(k); // the empty location
    if (not data[start].occupied) return ans;
    data[start].occupied = false;
    data[start].key.~Key();
    --size;
    size_t i = (start + 1) & cap_mask;
    while (data[i].occupied) {
      const size_t h = hasher(data[i].key) & cap_mask;
      if (not cyclic_between(start,h,i)) {
        data[start].occupied = true;
        new (&data[start].key) Key(std::move(data[i].key));
        start = i;
        data[i].occupied = false;
        ans.push_back(make_pair(&data[start].key, make_pair(i, start)));
        //data[i].key.~Key(); // no : already moved it?
      }
      i = (i+1) & cap_mask;
    }
    return ans;
  }

  bool insert(const Key& k) {
    const size_t i = locate(k);
    if (data[i].occupied) return false;
    new (&data[i].key) Key(k);
    ++size;
    data[i].occupied = true;
    return true;
  }

};

// IDEA: store hash values, ones means "empty"

template<typename Key,
         typename Hash = std::hash<Key>,
         typename Equal = std::equal_to<Key>,
         typename Allocate = TlsfAllocator<Key> >
struct DeamortizedHashSet {

  DeamortizedHashSet() :
    allocator(), far(allocator,0), near(allocator,32) {
    near.init(1);
    near.state = LimitedHashSet<Key, Hash, Equal,Allocate>::ACT::FILL;
  }

  Allocate allocator;
  LimitedHashSet<Key, Hash, Equal, Allocate> far, near;
  // 1/4: clear old
  // 1/4: init new
  // 1/2: fill new

  enum ACT : char {
    CLEAR, MAKE_BIGGER, INIT_BIGGER, MAKE_SMALLER, INIT_SMALLER, FILL, SWAP, RELAX
  };

  // how much time you have to do this
  pair<ACT, size_t> get_act_help() const {
    if (near.size < near.capacity/8) return make_pair(SWAP, 1);
    if (near.size < 3*(near.capacity/16)) return make_pair(FILL, near.size - near.capacity/8);
    if (near.size < 7*(near.capacity/32) - 1) return make_pair(INIT_SMALLER, near.size - 3*(near.capacity/16));
    if (near.size < 7*(near.capacity/32)) return make_pair(MAKE_SMALLER, near.size - 3*(near.capacity/16));
    if (near.size < near.capacity/4) return make_pair(CLEAR, near.size - 7*(near.capacity/32));
    if (near.size < 5*(near.capacity/16)) return make_pair(CLEAR, 5*(near.capacity/16) - near.size);
    if (near.size < 5*(near.capacity/16) + 1) return make_pair(MAKE_BIGGER, 5*(near.capacity/16) - near.size);
    if (near.size < 3*(near.capacity/8)) return make_pair(INIT_BIGGER, 3*(near.capacity/8) - near.size);
    if (near.size < near.capacity/2) return make_pair(FILL, near.capacity/2 - near.size);
    return make_pair(SWAP, 1);
  }

  pair<ACT, size_t> get_act() const {
    if ((near.capacity <= 32) and (near.size < 7)) return make_pair(RELAX, 0);
    return get_act_help();
  }

  void erase(const Key& k) {
    vector<pair<Key *, pair<size_t, size_t> > >  moved_back = near.erase(k);
    const auto act = get_act();
    switch (act.first) {
    case RELAX:
      break;
    case CLEAR:
      far.clear(act.second);
      break;
    case MAKE_BIGGER:
      far.reset(near.capacity*2);
    case INIT_BIGGER:
      far.init(act.second);
      break;
    case MAKE_SMALLER:
      far.reset(near.capacity/2);
    case INIT_SMALLER:
      far.init(act.second);
      break;
    case FILL:
      far.fill(act.second, near);
      far.erase(k);
      far.catch_up(moved_back);
      break;
    default: // SWAP
      far.swap(near);
      far.erase(k);
    }
  }

  bool insert(const Key& k) {
    const bool ans = near.insert(k);
    const auto act = get_act();
    switch (act.first) {
    case RELAX:
      break;
    case CLEAR:
      far.clear(act.second);
      break;
    case MAKE_BIGGER:
      far.reset(near.capacity*2);
    case INIT_BIGGER:
      far.init(act.second);
      break;
    case MAKE_SMALLER:
      far.reset(near.capacity/2);
    case INIT_SMALLER:
      far.init(act.second);
      break;
    case FILL:
      far.fill(act.second, near);
      far.insert(k);
      break;
    default: // SWAP
      far.swap(near);
      near.insert(k);
    }
    return ans;
  }
};

#endif // LINEAR_HASH_SET
<commit_msg>reset after commit is OK<commit_after>#ifndef DEAMORTIZED_HASH_SET
#define DEAMORTIZED_HASH_SET

#include <cstdint>
#include <functional>
#include <cstdlib>
#include <cassert>
#include <cstddef>
#include <memory>
#include <vector>

using std::vector;
using std::pair;
using std::make_pair;

#include "tlsf_allocator.hpp"

template<typename Key,
         typename Hash = std::hash<Key>,
         typename Equal = std::equal_to<Key>,
         typename Allocate = TlsfAllocator<Key> >
class LimitedHashSet {
  typedef std::size_t size_t;
public:

  LimitedHashSet& operator=(const LimitedHashSet&) = delete;
  LimitedHashSet(const LimitedHashSet&) = delete;
  LimitedHashSet(LimitedHashSet&&) = delete;
  LimitedHashSet& operator=(LimitedHashSet&&) = delete;

public:

  struct Slot {
    bool occupied;
    Key key;
  };
  Hash hasher;
  Equal equaler;
  typedef typename Allocate::template rebind<Slot>::other A;
  A allocator;
  size_t capacity, size;
  Slot * data;
  size_t progress;
  enum ACT : char {
    CLEAR, INIT, RESET, FILL
  } state;

public:

  // TODO: overload for std::swap
  // TODO: copy and move and assignment constructors
  void swap(LimitedHashSet & that) {
    std::swap(allocator, that.allocator);
    std::swap(capacity, that.capacity);
    std::swap(size, that.size);
    std::swap(data, that.data);
    std::swap(progress, that.progress);
    std::swap(state, that.state);
  }

  explicit LimitedHashSet(const Allocate& a, const size_t capacity)
    : hasher(), equaler(), allocator(a), capacity(capacity), size(0),
      data(allocator.allocate(capacity)), progress(0), state(INIT)
  {}

  // TODO: this need to take state into account
  ~LimitedHashSet() {
    switch (state) {
    case CLEAR:
      while (progress < capacity) {
        allocator.destroy(&data[progress++]);
      }
      break;
    case INIT: // no data - still initializing
      break;
    case RESET: // no data - not even initialized yet
      break;
    case FILL:
      for (size_t i = 0; i < capacity; ++i) {
        if (data[i].occupied) {
          allocator.destroy(&data[i]);
        }
      }
    }
    allocator.deallocate(data, capacity);
  }

  void clear(const size_t left) {
    assert ((0 == capacity) || (state == FILL) || (state == CLEAR));
    if (state == FILL) {
      progress = 0;
    }
    state = CLEAR;
    const size_t many = left ? ((capacity - progress + left - 1)/left) : (capacity - progress);
    for (size_t i = 0; i < many; ++i) {
      if (data[progress].occupied) allocator.destroy(&data[progress]);
      ++progress;
    }
  }

  void init(const size_t left) {
    assert ((0 == capacity) || (state == RESET) || (state == INIT));
    if (RESET == state) {
      progress = 0;
    }
    state = INIT;
    const size_t many = left ? ((capacity - progress + left - 1)/left) : (capacity - progress);
    for (size_t i = 0; i < many; ++i) {
      data[progress].occupied = false;
      ++progress;
    }
  }

  void reset(const size_t new_capacity) {
    assert ((0 == capacity) || (state == CLEAR) || (INIT == state));
    state = RESET;
    size = 0;
    if (new_capacity != capacity) {
      allocator.deallocate(data, capacity);
      capacity = new_capacity;
      data = allocator.allocate(capacity);
    }
    progress = 0;
  }

  void fill(const size_t left, const LimitedHashSet& that) {
    assert ((0 == capacity) || (state == FILL) || (state == INIT));
    if (INIT == state) {
      progress = 0;
    }
    state = FILL;
    // don't care about *my* progress
    const size_t many = left ? ((that.capacity - progress + left - 1)/left) : (capacity - progress);
    for (size_t i = 0; i < many; ++i) {
      if (that.data[progress].occupied) insert(that.data[progress].key);
      ++progress;
    }
  }

  void catch_up(const vector<pair<Key *, pair<size_t, size_t> > > & moved_back) {
    for (const auto & kft : moved_back) {
      if ((kft.second.first >= progress)
          and (kft.second.second < progress)) {
        insert(*kft.first);
      }
    }
  }

private:

  // find a key. capacity must be > 0. if key is not present, returns
  // location where it would be if it were newly placed.
  size_t locate(const Key& k) const {
    const size_t cap_mask = capacity-1;
    auto h = hasher(k) & cap_mask;
    while (true) {
      if (not data[h].occupied)    return h;
      if (equaler(data[h].key, k)) return h;
      h = (h+1) & cap_mask;
    }
  }

  // i < j <= k, mod capacity
  static bool cyclic_between(const size_t& i, const size_t& j, const size_t& k) {
    return (((i < j) and (j <= k))
            or ((i < j) and (k < i))
            or ((j <= k) and (k < i)));
  }

public:
  Key* find(const Key& k) {
    if (NULL == data) return nullptr;
    const size_t i = locate(k);
    if (data[i].occupied && equaler(data[i].key, k)) {
      return &data[i].key;
    }
    return nullptr;
  }

public:

  vector<pair<Key *, pair<size_t, size_t> > > erase(const Key& k) {
    vector<pair<Key *, pair<size_t, size_t> > > ans;
    const size_t cap_mask = capacity-1;
    size_t start = locate(k); // the empty location
    if (not data[start].occupied) return ans;
    data[start].occupied = false;
    data[start].key.~Key();
    --size;
    size_t i = (start + 1) & cap_mask;
    while (data[i].occupied) {
      const size_t h = hasher(data[i].key) & cap_mask;
      if (not cyclic_between(start,h,i)) {
        data[start].occupied = true;
        new (&data[start].key) Key(std::move(data[i].key));
        start = i;
        data[i].occupied = false;
        ans.push_back(make_pair(&data[start].key, make_pair(i, start)));
        //data[i].key.~Key(); // no : already moved it?
      }
      i = (i+1) & cap_mask;
    }
    return ans;
  }

  bool insert(const Key& k) {
    const size_t i = locate(k);
    if (data[i].occupied) return false;
    new (&data[i].key) Key(k);
    ++size;
    data[i].occupied = true;
    return true;
  }

};

// IDEA: store hash values, ones means "empty"

template<typename Key,
         typename Hash = std::hash<Key>,
         typename Equal = std::equal_to<Key>,
         typename Allocate = TlsfAllocator<Key> >
struct DeamortizedHashSet {

  DeamortizedHashSet() :
    allocator(), far(allocator,0), near(allocator,32) {
    near.init(1);
    near.state = LimitedHashSet<Key, Hash, Equal,Allocate>::ACT::FILL;
  }

  Allocate allocator;
  LimitedHashSet<Key, Hash, Equal, Allocate> far, near;
  // 1/4: clear old
  // 1/4: init new
  // 1/2: fill new

  enum ACT : char {
    CLEAR, MAKE_BIGGER, INIT_BIGGER, MAKE_SMALLER, INIT_SMALLER, FILL, SWAP, RELAX
  };

  // how much time you have to do this
  pair<ACT, size_t> get_act_help() const {
    if (near.size < near.capacity/8) return make_pair(SWAP, 1);
    if (near.size < 3*(near.capacity/16)) return make_pair(FILL, near.size - near.capacity/8);
    if (near.size < 7*(near.capacity/32) - 1) return make_pair(INIT_SMALLER, near.size - 3*(near.capacity/16));
    if (near.size < 7*(near.capacity/32)) return make_pair(MAKE_SMALLER, near.size - 3*(near.capacity/16));
    if (near.size < near.capacity/4) return make_pair(CLEAR, near.size - 7*(near.capacity/32));
    if (near.size < 5*(near.capacity/16)) return make_pair(CLEAR, 5*(near.capacity/16) - near.size);
    if (near.size < 5*(near.capacity/16) + 1) return make_pair(MAKE_BIGGER, 5*(near.capacity/16) - near.size);
    if (near.size < 3*(near.capacity/8)) return make_pair(INIT_BIGGER, 3*(near.capacity/8) - near.size);
    if (near.size < near.capacity/2) return make_pair(FILL, near.capacity/2 - near.size);
    return make_pair(SWAP, 1);
  }

  pair<ACT, size_t> get_act() const {
    if ((near.capacity <= 32) and (near.size < 7)) return make_pair(RELAX, 0);
    return get_act_help();
  }

  void erase(const Key& k) {
    vector<pair<Key *, pair<size_t, size_t> > >  moved_back = near.erase(k);
    const auto act = get_act();
    switch (act.first) {
    case RELAX:
      break;
    case CLEAR:
      far.clear(act.second);
      break;
    case MAKE_BIGGER:
      far.reset(near.capacity*2);
    case INIT_BIGGER:
      far.init(act.second);
      break;
    case MAKE_SMALLER:
      far.reset(near.capacity/2);
    case INIT_SMALLER:
      far.init(act.second);
      break;
    case FILL:
      far.fill(act.second, near);
      far.erase(k);
      far.catch_up(moved_back);
      break;
    default: // SWAP
      far.swap(near);
      far.erase(k);
    }
  }

  bool insert(const Key& k) {
    const bool ans = near.insert(k);
    const auto act = get_act();
    switch (act.first) {
    case RELAX:
      break;
    case CLEAR:
      far.clear(act.second);
      break;
    case MAKE_BIGGER:
      far.reset(near.capacity*2);
    case INIT_BIGGER:
      far.init(act.second);
      break;
    case MAKE_SMALLER:
      far.reset(near.capacity/2);
    case INIT_SMALLER:
      far.init(act.second);
      break;
    case FILL:
      far.fill(act.second, near);
      far.insert(k);
      break;
    default: // SWAP
      far.swap(near);
      near.insert(k);
    }
    return ans;
  }
};

#endif // LINEAR_HASH_SET
<|endoftext|>


<commit_before>#include "inverseIndexStorageBloomierFilter.h"
#ifdef OPENMP
#include <omp.h>
#endif
InverseIndexStorageBloomierFilter::InverseIndexStorageBloomierFilter(const size_t pSizeOfInverseIndex, const size_t pMaxBinSize, const size_t pMaximalFeatures) {
	mInverseIndex = new std::vector<BloomierFilter* > (pSizeOfInverseIndex);
	mMaxBinSize = pMaxBinSize;
	mM = 3500;
	mK = 5;
	mQ = 7;
}
InverseIndexStorageBloomierFilter::~InverseIndexStorageBloomierFilter() {

}
size_t InverseIndexStorageBloomierFilter::size() const{
	return mInverseIndex->size();
}
const vsize_t* InverseIndexStorageBloomierFilter::getElement(size_t pVectorId, size_t pHashValue) {
    return (*mInverseIndex)[pVectorId]->get(pHashValue);
}
void InverseIndexStorageBloomierFilter::insert(size_t pVectorId, size_t pHashValue, size_t pInstance) {
    if ((*mInverseIndex)[pVectorId] == NULL) {
        (*mInverseIndex)[pVectorId] = new BloomierFilter(mM, mK, mQ, 100, mMaxBinSize);
    }
#ifdef OPENMP
#pragma omp critical
#endif
    (*mInverseIndex)[pVectorId]->set(pHashValue, pInstance);
}<commit_msg>Playing around with parameters<commit_after>#include "inverseIndexStorageBloomierFilter.h"
#ifdef OPENMP
#include <omp.h>
#endif
InverseIndexStorageBloomierFilter::InverseIndexStorageBloomierFilter(const size_t pSizeOfInverseIndex, const size_t pMaxBinSize, const size_t pMaximalFeatures) {
	mInverseIndex = new std::vector<BloomierFilter* > (pSizeOfInverseIndex);
	mMaxBinSize = pMaxBinSize;
	mM = 10000;
	mK = 5;
	mQ = 7;
}
InverseIndexStorageBloomierFilter::~InverseIndexStorageBloomierFilter() {

}
size_t InverseIndexStorageBloomierFilter::size() const{
	return mInverseIndex->size();
}
const vsize_t* InverseIndexStorageBloomierFilter::getElement(size_t pVectorId, size_t pHashValue) {
    return (*mInverseIndex)[pVectorId]->get(pHashValue);
}
void InverseIndexStorageBloomierFilter::insert(size_t pVectorId, size_t pHashValue, size_t pInstance) {
    if ((*mInverseIndex)[pVectorId] == NULL) {
        (*mInverseIndex)[pVectorId] = new BloomierFilter(mM, mK, mQ, 100, mMaxBinSize);
    }
#ifdef OPENMP
#pragma omp critical
#endif
    (*mInverseIndex)[pVectorId]->set(pHashValue, pInstance);
}<|endoftext|>