kmeraffect.h 6.08 KB
Newer Older
Mikaël Salson's avatar
Mikaël Salson committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#ifndef KMER_AFFECT_H
#define KMER_AFFECT_H

#include <string>
#include <iostream>

using namespace std;

/*
  A virtual class for the KmerAffect* would be much better but that would
  imply much more space for the KmerAffect class (which just stores one byte).
  Instead, we would have 8 more bytes for a pointer due to the virtual class plus
  the alignment of types which leads to 16 bytes for a single object instead of 1.
 */

typedef struct affect_s affect_t;
/**
 * This type represents the affectation by itself on the 7 least significant
 * bits and the strand on the most significant bit.  Hence the 7 lsb
 * correspond to the standard ASCII code of the character.  The most
 * significant bit is 0 for the reverse strand and 1 for the forward strand.
 */
struct affect_s {
  // 7 lsb are the label, the msb is the strand (0 -> -, 1 -> +)
  char c;
26
  unsigned char length;
Mikaël Salson's avatar
Mikaël Salson committed
27 28 29 30 31 32 33 34 35 36 37 38
};

/**
 * @return the strand (-1 or +1) associated to the affect_t
 */
int affect_strand(const affect_t &affect);

/**
 * @return the character associated to the affect_t
 */
char affect_char(const affect_t &affect);

39 40 41 42 43
/**
 * @return the length of the kmer associated with the affectation
 */
size_t affect_length(const affect_t &affect);

Mikaël Salson's avatar
Mikaël Salson committed
44 45 46 47 48 49 50
bool operator==(const affect_t &a1, const affect_t &a2);
bool operator<(const affect_t &a1, const affect_t &a2);
bool operator>(const affect_t &a1, const affect_t &a2);
bool operator<=(const affect_t &a1, const affect_t &a2);
bool operator>=(const affect_t &a1, const affect_t &a2);
bool operator!=(const affect_t &a1, const affect_t &a2);
string toString(const affect_t &a);
51 52 53
string toStringValues(const affect_t &a);
string toStringSigns(const affect_t &a);

Mikaël Salson's avatar
Mikaël Salson committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
ostream &operator<<(ostream &os, const affect_t &a);


class KmerAffect {
public:
  affect_t affect;

  /**
   * Construct an unknown affectation.
   * @post isUnknown()
   */
  KmerAffect();

  /**
   * @post affect == a
   */
  KmerAffect(const affect_t &a);

  /**
   * Copy constructor
   */ 
  KmerAffect(const KmerAffect &ka);

77 78 79 80 81
  /*
   * Copy constructor, possibly reversing the strand if 'reverse' is true
   */
  KmerAffect(const KmerAffect &ka, bool reverse);
     
Mikaël Salson's avatar
Mikaël Salson committed
82 83
  /**
   * Construct an affectation as stated by the parameters
84 85
   * @post affect_strand(affect) == strand AND affect_char(affect) == kmer[0] AND
   *       affect_length(affect) == length
Mikaël Salson's avatar
Mikaël Salson committed
86
   */
87
  KmerAffect(const string &label, int strand, size_t length=~0);
88

Mikaël Salson's avatar
Mikaël Salson committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
  /**
   * Add another affectation to the current one.
   * @post The current affectation is not modified if the parameter is the same
   *       affectation as the current one.
   *       If the current affectation is unknown, the affectation is set to the
   *       parameter.
   *       If the label is the same but the strand is different, the strand is
   *       arbitrarily put to forward.
   *       In the other cases, the affectation is set to ambiguous.
   */
  KmerAffect &operator+=(const KmerAffect &);

  /**
   * Affectation
   */
  KmerAffect &operator=(const KmerAffect &ka);

106 107 108 109 110
  /**
   * @return the ambiguous affectation
   */
  static KmerAffect getAmbiguous();

Mikaël Salson's avatar
Mikaël Salson committed
111 112 113 114 115 116 117 118 119 120 121 122 123 124
  /**
   * @return the strand of the affectation
   *         -1 for backward
   *          1 for forward
   *          0 for unknown or ambiguous
   */
  int getStrand() const;

  /**
   * @return the label of the affectation.
   *         In that case, the string consists of the first letter only
   */
  string getLabel() const;

125 126 127 128 129
  /**
   * @return the length of such an affectation
   */
  unsigned char getLength() const;

130 131 132 133 134
  /**
   * @return the unknown affectation
   */
  static KmerAffect getUnknown();

Mikaël Salson's avatar
Mikaël Salson committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
  /**
   * @return true iff the class does not take care of the strand
   *         (false in our case).
   */
  static bool hasRevcompSymetry();

  /**
   * @return true iff the affectation should be considered as ambiguous.
   */
  bool isAmbiguous() const;

  /**
   * @return true iff the affectation is unkwown yet.
   */
  bool isUnknown() const;

151 152 153 154
  /**
   * @return true iff the value is the same as the one given by default constructor
   */
  bool isNull() const;
155 156 157 158 159
  
  /**
  * @return true if the K-mer is not odd (ambiguous or unknown)
  */
  bool isGeneric() const;
160

Mikaël Salson's avatar
Mikaël Salson committed
161
  string toString() const;
162 163
string toStringValues()const;
string toStringSigns() const;
164 165

 void setLength(unsigned char length);
Mikaël Salson's avatar
Mikaël Salson committed
166 167 168 169 170 171 172 173 174 175 176
};


bool operator==(const KmerAffect &a1, const KmerAffect &a2);
bool operator<(const KmerAffect &a1, const KmerAffect &a2);
bool operator>(const KmerAffect &a1, const KmerAffect &a2);
bool operator<=(const KmerAffect &a1, const KmerAffect &a2);
bool operator>=(const KmerAffect &a1, const KmerAffect &a2);
bool operator!=(const KmerAffect &a1, const KmerAffect &a2);
ostream &operator<<(ostream &os, const KmerAffect &kmer);

177
#define AFFECT_NOT_UNKNOWN_SYMBOL "*"
178 179
#define AFFECT_AMBIGUOUS_SYMBOL "\0"
#define AFFECT_UNKNOWN_SYMBOL "\1"
180 181 182

/* Those are just shortcuts to access the *_SYMBOL constant with a char
 * type */
183 184
#define AFFECT_AMBIGUOUS_CHAR (AFFECT_AMBIGUOUS_SYMBOL[0])
#define AFFECT_UNKNOWN_CHAR (AFFECT_UNKNOWN_SYMBOL[0])
185

186 187 188 189 190
/* Define how an ambiguous kmeraffect looks like in a string */
#define AFFECT_AMBIGUOUS_TO_STRING "?"

/* Define how an unknown kmeraffect looks like in a string */
#define AFFECT_UNKNOWN_TO_STRING "_"
191

192 193 194
/* Define how meny specific k-mers exist. For now there is only ambiguous and unknown. */
#define SPECIFIC_KMERS_NUMBER 2

195 196 197 198
/**
 * Constant defining any not-unknown affectation
 * Could be used by .getIndexLoad(), but now any non-AFFECT_UNKNOWN kmer will work.
 */
199
const KmerAffect AFFECT_NOT_UNKNOWN = KmerAffect(AFFECT_NOT_UNKNOWN_SYMBOL, 0, -1);
200

Mikaël Salson's avatar
Mikaël Salson committed
201 202 203
/**
 * Constant defining the unknown affectation (not known yet)
 */
204
const KmerAffect AFFECT_UNKNOWN = KmerAffect(AFFECT_UNKNOWN_SYMBOL, 0, 1);
205

Mikaël Salson's avatar
Mikaël Salson committed
206 207 208
/**
 * Constant defining the ambiguous affectation (many possibilities)
 */
209
const KmerAffect AFFECT_AMBIGUOUS = KmerAffect(AFFECT_AMBIGUOUS_SYMBOL, 1, -1);
Mikaël Salson's avatar
Mikaël Salson committed
210

211 212
const KmerAffect AFFECT_V = KmerAffect("V", 1);
const KmerAffect AFFECT_J = KmerAffect("J", 1);
Mikaël Salson's avatar
Mikaël Salson committed
213

214 215
const KmerAffect AFFECT_V_BWD = KmerAffect("V", -1);
const KmerAffect AFFECT_J_BWD = KmerAffect("J", -1);
Mikaël Salson's avatar
Mikaël Salson committed
216 217 218 219

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif