https://github.com/jttoivon/MODER
Raw File
Tip revision: c485231e5b468ae509306e1aaeebaa0f3004572d authored by Jarkko Toivonen on 31 March 2020, 18:10:18 UTC
Fixed indexing bug.
Tip revision: c485231
orientation.hpp
/*

    MODER is a program to learn DNA binding motifs from SELEX datasets.
    Copyright (C) 2016, 2017  Jarkko Toivonen,
    Department of Computer Science, University of Helsinki

    MODER is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    MODER is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

*/
#ifndef ORIENTATION_HPP
#define ORIENTATION_HPP

#include "matrix.hpp"
#include "boost/tuple/tuple.hpp"

#include <vector>
#include <set>
#include <map>
#include <cassert>

enum {HT=0, HH=1, TT=2, TH=3, RNA_TH=1};

extern const char** orients;
extern const char* dna_orients[];
extern const char* rna_orients[];


class string_to_orientation_type
{
public:

  string_to_orientation_type() 
  {
    for (int i=0; i < 4; ++i) 
      m[orients[i]] = i;
  }

  int
  operator()(const std::string& s)
  {
    return m[s];
  }

private:
  std::map<std::string, int> m;
};

static string_to_orientation_type string_to_orientation;   // WHY THIS ISN'T IN THE CPP FILE??????????????????

int
orientation(int o1, int o2);

int
orientation2(int o1, int o2);  // four different orientations

boost::tuple<dmatrix,dmatrix>
get_matrices_according_to_hetero_orientation(int o, const dmatrix& m1, const dmatrix& m2, bool use_rna);

boost::tuple<std::string,std::string>
get_seeds_according_to_hetero_orientation(int o, const std::string& s1, const std::string& s2, bool use_rna);



// Bits in bitvector "abcdefgh"
//                    76543210
// correspond to following:
// a = TF1 in normal direction in position 1
// b = TF1 in reverse direction in position 1
// c = TF2 in normal direction in position 1
// d = TF2 in reverse direction in position 1
// e = TF1 in normal direction in position 2
// f = TF1 in reverse direction in position 2
// g = TF2 in normal direction in position 2
// h = TF2 in reverse direction in position 2
//
//  First   Second
//  Pos     Pos
//|       |       | 
// a b c d e f g h
//|   |   |   |   |
// TF1 TF2 TF1 TF2
// + - + - + - + -
class hetero_orientation_class
{
public:

  hetero_orientation_class() : v(256, -1)
  {
    /*
    v[128+2] = HT;  // strand
    v[16+4]  = HT;  // reverse strand

    v[128+1] = HH;  // strand
    v[32+4]  = HH;  // reverse strand

    v[64+2]  = TT;  // strand
    v[16+8]  = TT;  // reverse strand

    v[64+1]  = TH;  // strand
    v[32+8]  = TH;  // reverse strand
    */

    for (int o=0; o < 4; ++o) {
      v[a[o][0]] = o;
      v[a[o][1]] = o;
    }
  }


  std::vector<int>
  list(int bits) const       // returns a subset of {HT,HH,TT,TH}
  {
    /*
    std::set<int> result;
    if (t(128+2, i) or t(16+4, i))
      result.insert(HT);
    if (t(128+1, i) or t(32+4, i))
      result.insert(HH);
    if (t(64+2, i) or t(16+8, i))
      result.insert(TT);
    if (t(64+1, i) or t(32+8, i))
      result.insert(TH);

    return std::vector<int>(result.begin(), result.end());
    */
    std::vector<int> result;
    for (int o=0; o < 4; ++o)
      if (this->contains(bits, o))
	result.push_back(o);

    return result;
  }


  std::vector<std::pair<int,int> >
  list2(int bits) const       // returns a subset of {HT,HH,TT,TH}
  {
    std::vector<std::pair<int,int> > result;
    for (int o=0; o < 4; ++o)
      if (this->contains(bits, o, +1))
	result.push_back(std::make_pair(o, +1));
      else if (this->contains(bits, o, -1))
	result.push_back(std::make_pair(o, -1));

    return result;
  }

  bool
  contains(int bits, int orientation, int dir=0) const // dir == -1, 1, or 0   that is, directed or directionless
  {                                                 // Direction is +1 if TF1 is in the first position
    assert(0 <= orientation and orientation < 4);
    assert(bits >= 0);
    assert(bits < 256);

    if (dir == 1)
      return t(a[orientation][0], bits);
    else if (dir == -1)
      return t(a[orientation][1], bits);
    else if (dir == 0)
      return t(a[orientation][0], bits) or t(a[orientation][1], bits);
    else return false;
  }

  /*
  int
  operator()(int i) const
  {
    assert(0 <= i and i < 256);
    return v[i];
  }
  */
private:

  static const int a[4][2];   // first index is orientation, second is strand (0) or reverse strand (1)

  bool
  t(int mask, int bits) const
  {
    return (mask & bits) == mask;
  }

  std::vector<int> v;
};


class homo_orientation_class
{
public:

  homo_orientation_class() : v(256, -1)
  {
    v[8+2]  = HT;
    v[8+1]  = HH;
    v[4+2]  = TT;
    v[4+1]  = HT;
  }


  std::vector<int>
  list(int i) const
  {
    std::vector<int> result;
    if (t(8+2, i) or t(4+1, i))
      result.push_back(HT);
    if (t(8+1, i))
      result.push_back(HH);
    if (t(4+2, i))
      result.push_back(TT);

    return result;
  }

  bool
  contains(int i, int orientation) const
  {
    assert(0 <= orientation and orientation < 3);
    assert(i >= 0);
    assert(i < 16);

    if (orientation == HT)
      return t(a[HT], i) or t(a[TH], i);
    else 
      return t(a[orientation], i);
  }

  /*
  int
  operator()(int i) const
  {
    assert(0 <= i and i < 16);
    return v[i];
  }
  */
private:
  static const int a[4];

  bool
  t(int mask, int code) const
  {
    return (mask & code) == mask;
  }

  std::vector<int> v;
};

extern hetero_orientation_class hetero_orientation;
extern homo_orientation_class get_homo_orientation;

#endif // ORIENTATION_HPP
back to top