kmeraffect.cpp 5.64 KB
Newer Older
Mikael Salson's avatar
Mikael Salson committed
1
/*
2
  This file is part of Vidjil <http://www.vidjil.org>
3
  Copyright (C) 2011-2019 by VidjilNet consortium and Bonsai bioinformatics
4 5 6 7 8
  at CRIStAL (UMR CNRS 9189, Université Lille) and Inria Lille
  Contributors: 
      Mathieu Giraud <mathieu.giraud@vidjil.org>
      Mikaël Salson <mikael.salson@vidjil.org>
      Marc Duez <marc.duez@vidjil.org>
Mikael Salson's avatar
Mikael Salson committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

  "Vidjil" 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 3 of the License, or
  (at your option) any later version.

  "Vidjil" 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 "Vidjil". If not, see <http://www.gnu.org/licenses/>
*/

#include "kmeraffect.h"
25
#include <cassert>
Mikael Salson's avatar
Mikael Salson committed
26 27 28 29 30 31 32 33 34

int affect_strand(const affect_t &affect) {
  return (affect.c & (1 << 7)) ? 1 : -1;
}

char affect_char(const affect_t &affect) {
  return (affect.c & ((1 << 7)-1));
}

35 36 37 38
size_t affect_length(const affect_t &affect) {
  return affect.length;
}

Mikael Salson's avatar
Mikael Salson committed
39 40 41
// KmerAffect class

bool operator==(const affect_t &a1, const affect_t &a2) {
42 43
  return a1.c == a2.c &&
    (affect_char(a1) == AFFECT_AMBIGUOUS_CHAR || affect_char(a1) == AFFECT_UNKNOWN_CHAR
44
     || a1.length == (unsigned char) ~0 || a2.length == (unsigned char)~0 || a1.length == a2.length);
Mikael Salson's avatar
Mikael Salson committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58
}
bool operator<(const affect_t &a1, const affect_t &a2) {
  return a1.c < a2.c;
}
bool operator>(const affect_t &a1, const affect_t &a2) {
  return a1.c > a2.c;
}
bool operator<=(const affect_t &a1, const affect_t &a2) {
  return ! (a1 > a2);
}
bool operator>=(const affect_t &a1, const affect_t &a2) {
  return ! (a1 < a2);
}
bool operator!=(const affect_t &a1, const affect_t &a2) {
59
  return ! (a1 == a2);
Mikael Salson's avatar
Mikael Salson committed
60 61 62
}
string toString(const affect_t &a) {
  string result;
63 64
  result = toStringSigns(a);
  result += toStringValues(a);
Mikael Salson's avatar
Mikael Salson committed
65 66
  return result;
}
67 68

string toStringValues(const affect_t &a){
69
  if(a == AFFECT_UNKNOWN.affect){
70
    return AFFECT_UNKNOWN_TO_STRING;
71 72
  }
  if(a == AFFECT_AMBIGUOUS.affect){
73
    return AFFECT_AMBIGUOUS_TO_STRING;
74
  }
75 76 77 78
  return string(1,affect_char(a));
}

string toStringSigns(const affect_t &a){
79
  if((a == AFFECT_UNKNOWN.affect) || (a == AFFECT_AMBIGUOUS.affect))
80 81 82 83 84
    return " ";
  else
    return (affect_strand(a)==1 ? "+" : "-");
}

Mikael Salson's avatar
Mikael Salson committed
85 86 87 88 89 90 91
ostream &operator<<(ostream &os, const affect_t &a) {
  os << toString(a);
  return os;
}


KmerAffect::KmerAffect() {
92
  *this = AFFECT_UNKNOWN;
Mikael Salson's avatar
Mikael Salson committed
93 94 95 96 97 98 99 100 101 102
}

KmerAffect::KmerAffect(const affect_t &a) {
  affect = a;
}

KmerAffect::KmerAffect(const KmerAffect &ka) {
  affect = ka.affect;
}

103 104 105 106 107 108
KmerAffect::KmerAffect(const KmerAffect &ka, bool reverse) {
  affect = ka.affect;
  if (reverse)
    affect.c ^= (1 << 7);
}

109
KmerAffect::KmerAffect(const string &label,
110
                       int strand, size_t length) {
Mikael Salson's avatar
Mikael Salson committed
111
  affect.c = label[0];
112
  affect.length = length;
Mikael Salson's avatar
Mikael Salson committed
113 114 115 116 117 118
  if (strand == 1)
     affect.c |= (1 << 7);
}

KmerAffect &KmerAffect::operator+=(const KmerAffect &kmer) {
  if (kmer.affect != affect) {
119
    if (isUnknown())
120
      *this = kmer;
Mikael Salson's avatar
Mikael Salson committed
121
    else if (affect_char(affect) == affect_char(kmer.affect)
122
             && (affect_strand(affect) != affect_strand(kmer.affect))) {
Mikael Salson's avatar
Mikael Salson committed
123
      // Same label but different strand
124 125 126 127
      // -> we put ambiguous, we could have something to say that
      // strand is ambiguous but not the label, but we don't have enough space
      // in 1 byte…
      *this = AFFECT_AMBIGUOUS;
128 129
      affect.length = kmer.getLength();
    } else {
130
      assert(affect.c != kmer.affect.c || getLength() == kmer.getLength());
Mikael Salson's avatar
Mikael Salson committed
131
      *this = AFFECT_AMBIGUOUS;
132
      affect.length = kmer.getLength();
133
    }
Mikael Salson's avatar
Mikael Salson committed
134 135 136 137 138 139 140 141 142 143 144 145 146
  }
  return *this;
}

KmerAffect &KmerAffect::operator=(const KmerAffect &ka) {
  this->affect = ka.affect;
  return *this;
}

bool KmerAffect::hasRevcompSymetry() {
  return false;
}

147 148 149 150
KmerAffect KmerAffect::getAmbiguous() {
  return AFFECT_AMBIGUOUS;
}

Mikael Salson's avatar
Mikael Salson committed
151 152 153 154 155 156 157
int KmerAffect::getStrand() const{
  if (isUnknown() || isAmbiguous())
    return 0;
  return affect_strand(affect);
}

string KmerAffect::getLabel() const {
158
 return ::toStringValues(affect);
Mikael Salson's avatar
Mikael Salson committed
159 160
}

161 162 163 164
unsigned char KmerAffect::getLength() const {
  return affect_length(affect);
}

165 166 167 168
KmerAffect KmerAffect::getUnknown() {
  return AFFECT_UNKNOWN;
}

Mikael Salson's avatar
Mikael Salson committed
169
bool KmerAffect::isAmbiguous() const {
170
  return affect_strand(affect) == 1 && affect_char(affect) == AFFECT_AMBIGUOUS_CHAR;
Mikael Salson's avatar
Mikael Salson committed
171 172
}

173 174 175 176
bool KmerAffect::isNull() const {
  return isUnknown();
}

Mikael Salson's avatar
Mikael Salson committed
177
bool KmerAffect::isUnknown() const {
178
  return affect.c == (int) AFFECT_UNKNOWN_CHAR;
Mikael Salson's avatar
Mikael Salson committed
179 180
}

181 182 183 184
bool KmerAffect::isGeneric() const {
  return !(isUnknown() || isAmbiguous());
}

Mikael Salson's avatar
Mikael Salson committed
185 186 187 188
string KmerAffect::toString() const {
  return ::toString(affect);
}

189 190 191 192 193 194 195 196
string KmerAffect::toStringValues() const {
  return ::toStringValues(affect);
}

string KmerAffect::toStringSigns() const {
  return ::toStringSigns(affect);
}

197 198 199
void KmerAffect::setLength(unsigned char length) {
  affect.length = length;
}
200

Mikael Salson's avatar
Mikael Salson committed
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
bool operator==(const KmerAffect &a1, const KmerAffect &a2) {
  return a1.affect == a2.affect;
}
bool operator<(const KmerAffect &a1, const KmerAffect &a2) {
  return a1.affect < a2.affect;
}
bool operator>(const KmerAffect &a1, const KmerAffect &a2) {
  return a1.affect > a2.affect;
              }
bool operator<=(const KmerAffect &a1, const KmerAffect &a2) {
  return a1.affect <= a2.affect;
}
bool operator>=(const KmerAffect &a1, const KmerAffect &a2) {
  return a1.affect >= a2.affect;
}
bool operator!=(const KmerAffect &a1, const KmerAffect &a2) {
217
  return ! (a1 == a2);
Mikael Salson's avatar
Mikael Salson committed
218 219 220 221 222 223 224
}

ostream &operator<<(ostream &os, const KmerAffect &kmer) {
  os << kmer.affect;
  return os;
}