source: branches/items/GDE/PROBCONS/probcons/Sequence.h

Last change on this file was 10405, checked in by aboeckma, 11 years ago

added probcons

File size: 12.4 KB
Line 
1/////////////////////////////////////////////////////////////////
2// Sequence.h
3//
4// Class for reading/manipulating single sequence character data.
5/////////////////////////////////////////////////////////////////
6
7#ifndef SEQUENCE_H
8#define SEQUENCE_H
9
10#include <string>
11#include <fstream>
12#include <iostream>
13#include <cctype>
14#include <cstdlib>
15#include "SafeVector.h"
16#include "FileBuffer.h"
17
18/////////////////////////////////////////////////////////////////
19// Sequence
20//
21// Class for storing sequence information.
22/////////////////////////////////////////////////////////////////
23
24class Sequence {
25
26  bool isValid;                // a boolean indicating whether the sequence data is valid or not
27  string header;               // string containing the comment line of the FASTA file
28  SafeVector<char> *data;      // pointer to character data
29  int length;                  // length of the sequence
30  int sequenceLabel;           // integer sequence label, typically to indicate the ordering of sequences
31                               //   in a Multi-FASTA file
32  int inputLabel;              // position of sequence in original input
33
34  /////////////////////////////////////////////////////////////////
35  // Sequence::Sequence()
36  //
37  // Default constructor.  Does nothing.
38  /////////////////////////////////////////////////////////////////
39
40  Sequence () : isValid (false), header (""), data (NULL), length (0), sequenceLabel (0), inputLabel (0) {}
41
42 public:
43
44  /////////////////////////////////////////////////////////////////
45  // Sequence::Sequence()
46  //
47  // Constructor.  Reads the sequence from a FileBuffer.
48  /////////////////////////////////////////////////////////////////
49
50  Sequence (FileBuffer &infile, bool stripGaps = false) : isValid (false), header ("~"), data (NULL), length(0), sequenceLabel (0), inputLabel (0) {
51
52    // read until the first non-blank line
53    while (!infile.eof()){
54      infile.GetLine (header);
55      if (header.length() != 0) break;
56    }
57
58    // check to make sure that it is a correct header line
59    if (header[0] == '>'){
60
61      // if so, remove the leading ">"
62      header = header.substr (1);
63
64      // remove any leading or trailing white space in the header comment
65      while (header.length() > 0 && isspace (header[0])) header = header.substr (1);
66      while (header.length() > 0 && isspace (header[header.length() - 1])) header = header.substr(0, header.length() - 1);
67
68      // get ready to read the data[] array; note that data[0] is always '@'
69      char ch;
70      data = new SafeVector<char>; assert (data);
71      data->push_back ('@');
72
73      // get a character from the file
74      while (infile.Get(ch)){
75
76        // if we've reached a new comment line, put the character back and stop
77        if (ch == '>'){ infile.UnGet(); break; }
78
79        // skip whitespace
80        if (isspace (ch)) continue;
81
82        // substitute gap character
83        if (ch == '.') ch = '-';
84        if (stripGaps && ch == '-') continue;
85
86        // check for known characters
87        if (!((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '*' || ch == '-')){
88          cerr << "ERROR: Unknown character encountered: " << ch << endl;
89          exit (1);
90        }
91
92        // everything's ok so far, so just store this character.
93        data->push_back(ch);
94        ++length;
95      }
96
97      // sequence must contain data in order to be valid
98      isValid = length > 0;
99      if (!isValid){
100        delete data;
101        data = NULL;
102      }
103    }
104  }
105
106 
107  /////////////////////////////////////////////////////////////////
108  // Sequence::Sequence()
109  //
110  // Constructor.  Builds a sequence from existing data.  Note
111  // that the data must use one-based indexing where data[0] should
112  // be set to '@'.
113  /////////////////////////////////////////////////////////////////
114
115  Sequence (SafeVector<char> *data, string header, int length, int sequenceLabel, int inputLabel) :
116    isValid (data != NULL), header(header), data(data), length (length), sequenceLabel (sequenceLabel), inputLabel (inputLabel) {
117      assert (data);
118      assert ((*data)[0] == '@');
119  }
120
121  /////////////////////////////////////////////////////////////////
122  // Sequence::Sequence()
123  //
124  // Destructor.  Release allocated memory.
125  /////////////////////////////////////////////////////////////////
126
127  ~Sequence (){
128    if (data){
129      assert (isValid);
130      delete data;
131      data = NULL;
132      isValid = false;
133    }
134  }
135
136  /////////////////////////////////////////////////////////////////
137  // Sequence::GetHeader()
138  //
139  // Return the string comment associated with this sequence.
140  /////////////////////////////////////////////////////////////////
141
142  string GetHeader () const {
143    return header;
144  }
145
146  /////////////////////////////////////////////////////////////////
147  // Sequence::GetName()
148  //
149  // Return the first word of the string comment associated with this sequence.
150  /////////////////////////////////////////////////////////////////
151
152  string GetName () const {
153    char name[1024];
154    sscanf (header.c_str(), "%s", name);
155    return string(name);
156  }
157
158  /////////////////////////////////////////////////////////////////
159  // Sequence::GetDataPtr()
160  //
161  // Return the iterator to data associated with this sequence.
162  /////////////////////////////////////////////////////////////////
163
164  SafeVector<char>::iterator GetDataPtr(){
165    assert (isValid);
166    assert (data);
167    return data->begin();
168  }
169
170  /////////////////////////////////////////////////////////////////
171  // Sequence::GetPosition()
172  //
173  // Return the character at position i.  Recall that the character
174  // data is stored with one-based indexing.
175  /////////////////////////////////////////////////////////////////
176
177  char GetPosition (int i) const {
178    assert (isValid);
179    assert (data);
180    assert (i >= 1 && i <= length);
181    return (*data)[i];
182  }
183
184  /////////////////////////////////////////////////////////////////
185  // Sequence::SetLabel()
186  //
187  // Sets the sequence label to i.
188  /////////////////////////////////////////////////////////////////
189
190  void SetLabel (int i){
191    assert (isValid);
192    sequenceLabel = i;
193    inputLabel = i;
194  }
195
196  /////////////////////////////////////////////////////////////////
197  // Sequence::SetSortLabel()
198  //
199  // Sets the sequence sorting label to i.
200  /////////////////////////////////////////////////////////////////
201
202  void SetSortLabel (int i){
203    assert (isValid);
204    sequenceLabel = i;
205  }
206
207  /////////////////////////////////////////////////////////////////
208  // Sequence::GetLabel()
209  //
210  // Retrieves the input label.
211  /////////////////////////////////////////////////////////////////
212
213  int GetLabel () const {
214    assert (isValid);
215    return inputLabel;
216  }
217
218  /////////////////////////////////////////////////////////////////
219  // Sequence::GetSortLabel()
220  //
221  // Retrieves the sorting label.
222  /////////////////////////////////////////////////////////////////
223
224  int GetSortLabel () const {
225    assert (isValid);
226    return sequenceLabel;
227  }
228
229  /////////////////////////////////////////////////////////////////
230  // Sequence::Fail()
231  //
232  // Checks to see if the sequence successfully loaded.
233  /////////////////////////////////////////////////////////////////
234
235  bool Fail () const {
236    return !isValid;
237  }
238
239  /////////////////////////////////////////////////////////////////
240  // Sequence::Length()
241  //
242  // Returns the length of the sequence.
243  /////////////////////////////////////////////////////////////////
244
245  int GetLength () const {
246    assert (isValid);
247    assert (data);
248    return length;
249  }
250
251  /////////////////////////////////////////////////////////////////
252  // Sequence::WriteMFA()
253  //
254  // Writes the sequence to outfile in MFA format.  Uses numColumns
255  // columns per line.  If useIndex is set to false, then the
256  // header is printed as normal, but if useIndex is true, then
257  // ">S###" is printed where ### represents the sequence label.
258  /////////////////////////////////////////////////////////////////
259
260  void WriteMFA (ostream &outfile, int numColumns, bool useIndex = false) const {
261    assert (isValid);
262    assert (data);
263    assert (!outfile.fail());
264
265    // print out heading
266    if (useIndex)
267      outfile << ">S" << GetLabel() << endl;
268    else
269      outfile << ">" << header << endl;
270
271    // print out character data
272    int ct = 1;
273    for (; ct <= length; ct++){
274      outfile << (*data)[ct];
275      if (ct % numColumns == 0) outfile << endl;
276    }
277    if ((ct-1) % numColumns != 0) outfile << endl;
278  }
279
280  /////////////////////////////////////////////////////////////////
281  // Sequence::Clone()
282  //
283  // Returns a new deep copy of the seqeuence.
284  /////////////////////////////////////////////////////////////////
285
286  Sequence *Clone () const {
287    Sequence *ret = new Sequence();
288    assert (ret);
289
290    ret->isValid = isValid;
291    ret->header = header;
292    ret->data = new SafeVector<char>; assert (ret->data);
293    *(ret->data) = *data;
294    ret->length = length;
295    ret->sequenceLabel = sequenceLabel;
296    ret->inputLabel = inputLabel;
297
298    return ret;
299  }
300
301  /////////////////////////////////////////////////////////////////
302  // Sequence::GetRange()
303  //
304  // Returns a new sequence object consisting of a range of
305  // characters from the current seuquence.
306  /////////////////////////////////////////////////////////////////
307
308  Sequence *GetRange (int start, int end) const {
309    Sequence *ret = new Sequence();
310    assert (ret);
311
312    assert (start >= 1 && start <= length);
313    assert (end >= 1 && end <= length);
314    assert (start <= end);
315
316    ret->isValid = isValid;
317    ret->header = header;
318    ret->data = new SafeVector<char>; assert (ret->data);
319    ret->data->push_back ('@');
320    for (int i = start; i <= end; i++)
321      ret->data->push_back ((*data)[i]);
322    ret->length = end - start + 1;
323    ret->sequenceLabel = sequenceLabel;
324    ret->inputLabel = inputLabel;
325
326    return ret;
327  }
328
329  /////////////////////////////////////////////////////////////////
330  // Sequence::AddGaps()
331  //
332  // Given an SafeVector<char> containing the skeleton for an
333  // alignment and the identity of the current character, this
334  // routine will create a new sequence with all necesssary gaps added.
335  // For instance,
336  //    alignment = "XXXBBYYYBBYYXX"
337  //    id = 'X'
338  // will perform the transformation
339  //    "ATGCAGTCA" --> "ATGCC---GT--CA"
340  //                    (XXXBBYYYBBYYXX)
341  /////////////////////////////////////////////////////////////////
342
343  Sequence *AddGaps (SafeVector<char> *alignment, char id){
344    Sequence *ret = new Sequence();
345    assert (ret);
346
347    ret->isValid = isValid;
348    ret->header = header;
349    ret->data = new SafeVector<char>; assert (ret->data);
350    ret->length = (int) alignment->size();
351    ret->sequenceLabel = sequenceLabel;
352    ret->inputLabel = inputLabel;
353    ret->data->push_back ('@');
354
355    SafeVector<char>::iterator dataIter = data->begin() + 1;
356    for (SafeVector<char>::iterator iter = alignment->begin(); iter != alignment->end(); ++iter){
357      if (*iter == 'B' || *iter == id){
358        ret->data->push_back (*dataIter);
359        ++dataIter;
360      }
361      else
362        ret->data->push_back ('-');
363    }
364
365    return ret;
366  }
367
368  /////////////////////////////////////////////////////////////////
369  // Sequence::GetString()
370  //
371  // Returns the sequence as a string with gaps removed.
372  /////////////////////////////////////////////////////////////////
373
374  string GetString (){
375    string s = "";
376    for (int i = 1; i <= length; i++){
377      if ((*data)[i] != '-') s += (*data)[i];
378    }
379    return s;
380  }
381
382
383  /////////////////////////////////////////////////////////////////
384  // Sequence::GetMapping()
385  //
386  // Returns a SafeVector<int> containing the indices of every
387  // character in the sequence.  For instance, if the data is
388  // "ATGCC---GT--CA", the method returns {1,2,3,4,5,9,10,13,14}.
389  /////////////////////////////////////////////////////////////////
390
391  SafeVector<int> *GetMapping () const {
392    SafeVector<int> *ret = new SafeVector<int>(1, 0);
393    for (int i = 1; i <= length; i++){
394      if ((*data)[i] != '-') ret->push_back (i);
395    }
396    return ret;
397  }
398
399  /////////////////////////////////////////////////////////////////
400  // Sequence::Highlight()
401  //
402  // Changes all positions with score >= cutoff to upper case and
403  // all positions with score < cutoff to lower case.
404  /////////////////////////////////////////////////////////////////
405
406  void Highlight (const SafeVector<float> &scores, const float cutoff){
407    for (int i = 1; i <= length; i++){
408      if (scores[i-1] >= cutoff)
409        (*data)[i] = toupper ((*data)[i]);
410      else
411        (*data)[i] = tolower ((*data)[i]);
412    }
413  }
414};
415
416#endif
Note: See TracBrowser for help on using the repository browser.