Next version of JABA
[jabaws.git] / binaries / src / clustalw / src / fileInput / RSFFileParser.cpp
1 /**
2  * Author: Mark Larkin
3  * 
4  * Copyright (c) 2007 Des Higgins, Julie Thompson and Toby Gibson.  
5  */
6 /**
7  * Changes:
8  *
9  * 10-02-07,Nigel Brown(EMBL): changed ifstream to InFileStream to handle
10  * cross-platform end-of-lines.
11  */
12
13 #ifdef HAVE_CONFIG_H
14     #include "config.h"
15 #endif
16 #include "RSFFileParser.h"
17
18 namespace clustalw
19 {
20
21 /**
22  * Constructor sets up the chartab array.
23  * @param filePath 
24  */
25 RSFFileParser::RSFFileParser(string filePath)
26 {
27     fileName = filePath; 
28     fillCharTab();
29 }
30
31     vector<Sequence> RSFFileParser::getSeqRange(int firstSeq, int no, string *offendingSeq)
32 {
33     vector<Sequence> seqRangeVector;
34     int i;
35
36     for (i=0; i<no; i++)
37     { 
38         Sequence tempSeq = getSeq(firstSeq + i, offendingSeq);
39         if (parseExitCode!=OK) {
40             seqRangeVector.clear();
41             return seqRangeVector;
42         }
43         seqRangeVector.push_back(tempSeq);
44     }
45     return seqRangeVector;
46 }
47
48     
49 /**
50  * get the sequence seqNum from the file.
51  * @param seqNum The number of the sequence to get.
52  * @return The sequence seqNum.
53  */
54     Sequence RSFFileParser::getSeq(int seqNum, string *offendingSeq)
55 {
56     char _line[MAXLINE + 1];
57     char _sname[MAXNAMES + 1];
58     string characterSeq = "";
59     string name = "";
60     string title = "";
61     string blank = "";
62     _line[0] = EOS;
63     
64     int i;
65     unsigned char c;
66     int _currentSeqNum = 0; // Not at any sequence yet!
67     
68     try
69     {
70         _fileIn = new InFileStream;  //nige
71         _fileIn->open(fileName.c_str());  //nige
72         _fileIn->seekg(0, std::ios::beg); // start at the beginning
73         
74         // Need to get the cursor to the begining of the correct sequence.
75         // This will be the case when we get to the seqNum {
76         while (_currentSeqNum != seqNum)
77         {
78             while(*_line != '{')
79             {
80                 if(!_fileIn->getline(_line, MAXLINE + 1)) // If we cannot get anymore!
81                 {
82                     _fileIn->close();
83                     return Sequence(blank, blank, blank);
84                 }
85             }
86             ++_currentSeqNum;
87             if(_currentSeqNum == seqNum) // Found the sequence
88             {
89                 break;
90             }
91             // Get next line so that we are past the '{' line
92             _fileIn->getline(_line, MAXLINE + 1);
93         }
94
95         while (!keyword(_line, "name"))
96         {
97             if (!_fileIn->getline(_line, MAXLINE + 1))
98             {
99                 _fileIn->close();
100                 return Sequence(blank, blank, blank);
101             }
102         }
103         for (i = 5; i <= (int)strlen(_line); i++)
104         {
105             if (_line[i] != ' ')
106             {
107                 break;
108             }
109         }
110         strncpy(_sname, _line + i, MAXNAMES); // remember entryname
111         for (i = 0; i <= (int)strlen(_sname); i++)
112         {
113             if (_sname[i] == ' ')
114             {
115                 _sname[i] = EOS;
116                 break;
117             }
118         }
119
120         _sname[MAXNAMES] = EOS;
121         utilityObject->rTrim(_sname);
122         utilityObject->blankToUnderscore(_sname); // replace blanks with '_'
123         name = string(_sname);
124
125
126         while (!keyword(_line, "sequence"))
127         {
128             if (!_fileIn->getline(_line, MAXLINE + 1))
129             {
130                 _fileIn->close();
131                 return Sequence(blank, blank, blank);
132             }
133         }
134             
135         while (_fileIn->getline(_line, MAXLINE + 1))
136         {
137             for (i = 0; i <= MAXLINE; i++)
138             {
139                 c = _line[i];
140                 if (c == EOS || c == '}')
141                 {
142                     break;
143                 }
144                  // EOL
145                 if (c == '.')
146                 {
147                     characterSeq += '-';
148                 }
149                 c = chartab[c];
150                 if (c)
151                 {
152                     characterSeq += c;
153                 }
154             }
155             if (c == '}')
156             {
157                 break;
158             }
159         }
160         _fileIn->close();
161         
162         if ((int)characterSeq.length() > userParameters->getMaxAllowedSeqLength())
163         {
164             parseExitCode=SEQUENCETOOBIG;
165             if (offendingSeq!=NULL)
166                 offendingSeq->assign(name);
167             // return empty seq
168             return Sequence(blank, blank, blank);
169         }
170         return Sequence(characterSeq, name, title);
171     }
172     catch(...)
173     {
174         _fileIn->close();
175         cerr << "There was an exception in the RSFFileParser::getSeq function.\n"
176              << "Need to end program\n";
177         exit(1);
178     }            
179 }
180
181 /**
182  * count the number of sequences in a GCG RSF alignment file 
183  * @return The number of sequences in the file.
184  */
185 int RSFFileParser::countSeqs()
186 {
187     char _line[MAXLINE + 1];
188     int numSeqs;
189
190     try
191     {
192         numSeqs = 0;
193         _fileIn = new InFileStream;  //nige
194         _fileIn->open(fileName.c_str());  //nige
195         _fileIn->seekg(0, std::ios::beg); // start at the beginning
196                 
197         if(!_fileIn->is_open())
198         {
199             return 0; // No sequences found!
200         }
201                         
202         // skip the comments 
203         while (_fileIn->getline(_line, MAXLINE + 1))
204         {
205             // NOTE needed to change to -1 and -2 (it was -2 and -3)
206             // This is because getline does not put the \n in!
207             if (_line[strlen(_line) - 1] == '.' && _line[strlen(_line) - 2] == '.')
208             {
209                 break;
210             }
211         }
212
213         while (_fileIn->getline(_line, MAXLINE + 1))
214         {
215             if (*_line == '{')
216             {
217                 numSeqs++;
218             }
219         }
220         _fileIn->close();
221         return numSeqs;
222     }
223     catch(...)
224     {
225         _fileIn->close();
226         cerr << "An exception has occured in the function RSFFileParser::countSeqs()\n"
227              << "Program needs to terminate.\nPlease contact the Clustal developers\n";
228         exit(1);    
229     }    
230 }
231
232 /**
233  * Get the secondary structure information from the file.
234  * @param gapPenaltyMask 
235  * @param secStructMask 
236  * @param secStructName 
237  * @param structPenalties 
238  * @param length 
239  */
240 void RSFFileParser::getSecStructure(vector<char>& gapPenaltyMask, vector<char>& secStructMask,
241                      string& secStructName, int &structPenalties, int length)
242 {
243     char _title[MAXLINE + 1];
244     char _line[MAXLINE + 1];
245     char _lin2[MAXLINE + 1];
246     char _sname[MAXNAMES + 1];
247     int i;
248     _line[0] = EOS;
249     
250     try
251     {
252         secStructMask.clear();
253         secStructMask.assign(length, '.');        
254         _fileIn = new InFileStream;  //nige
255         _fileIn->open(fileName.c_str());  //nige
256         _fileIn->seekg(0, std::ios::beg); // Need to start at begining
257                 
258         // skip the comments 
259         while (_fileIn->getline(_line, MAXLINE + 1))
260         {
261             if (_line[strlen(_line) - 1] == '.' && _line[strlen(_line) - 2] == '.')
262             {
263                 break;
264             }
265         }
266
267         // find the start of the sequence entry 
268         for (;;)
269         {
270             while (_fileIn->getline(_line, MAXLINE + 1))
271                 if (*_line == '{')
272                 {
273                     break;
274                 }
275
276             while (!keyword(_line, "name"))
277             {
278                 if (!_fileIn->getline(_line, MAXLINE + 1))
279                 {
280                     _fileIn->close();
281                     return;
282                 }
283             }
284         
285             for (i = 5; i <= (int)strlen(_line); i++)
286             {
287                 if (_line[i] != ' ')
288                 {
289                     break;
290                 }
291             }
292             strncpy(_sname, _line + i, MAXNAMES); // remember entryname
293             for (i = 0; i <= (int)strlen(_sname); i++)
294             {
295                 if (_sname[i] == ' ')
296                 {
297                     _sname[i] = EOS;
298                     break;
299                 }
300             }
301             _sname[MAXNAMES] = EOS;
302             utilityObject->rTrim(_sname);
303             utilityObject->blankToUnderscore(_sname); // replace blanks with '_'
304
305             // look for secondary structure feature table / gap penalty mask
306             while (_fileIn->getline(_line, MAXLINE + 1))
307             {
308                 if (keyword(_line, "feature"))
309                 {
310                     if (userParameters->getInteractive())
311                     {
312                         strcpy(_title, "Found secondary structure in alignment file: ");
313                         strcat(_title, _sname);
314                         (*_lin2) = utilityObject->promptForYesNo(_title,
315                             "Use it to set local gap penalties ");
316                     }
317                     else
318                     {
319                         (*_lin2) = 'y';
320                     }
321                     if ((*_lin2 != 'n') && (*_lin2 != 'N'))
322                     {
323                         structPenalties = SECST;
324                         secStructMask.assign(length, '.');
325                         do
326                         {
327                             if (keyword(_line, "feature"))
328                             {
329                                 getRSFFeature(&_line[7], secStructMask, length);
330                             }
331                             _fileIn->getline(_line, MAXLINE + 1);
332                         }
333                         while (!keyword(_line, "sequence"));
334                     }
335                     else
336                     {
337                         do
338                         {
339                             _fileIn->getline(_line, MAXLINE + 1);
340                         }
341                         while (!keyword(_line, "sequence"));
342                     }
343                     secStructName = string(_sname);
344                 }
345                 else if (keyword(_line, "sequence"))
346                 {
347                     break;
348                 }
349
350                 if (structPenalties != NONE)
351                 {
352                     break;
353                 }
354             }
355         }
356         _fileIn->close();
357     }
358     catch(...)
359     {
360         _fileIn->close();
361         cerr << "An exception has occured in the function RSFFileParser::getSecStructure()\n"
362              << "Program needs to terminate.\nPlease contact the Clustal developers\n";
363         exit(1);
364     }    
365 }
366
367 /**
368  * get a feature from the file. Called by getSecStructure
369  * @param line 
370  * @param secStructMask 
371  * @param length 
372  */
373 void RSFFileParser::getRSFFeature(char* line, vector<char>& secStructMask, int length)
374 {
375     char c, s;
376     char str1[MAXLINE + 1], str2[MAXLINE + 1], feature[MAXLINE + 1];
377     int i, tmp, startPos, endPos;
378
379     try
380     {
381         if (sscanf(line, "%d%d%d%s%s%s", &startPos, &endPos, &tmp, str1, str2,
382             feature) != 6)
383         {
384             return;
385         }
386
387         if (strcmp(feature, "HELIX") == 0)
388         {
389             c = 'A';
390             s = '$';
391         }
392         else if (strcmp(feature, "STRAND") == 0)
393         {
394             c = 'B';
395             s = '%';
396         }
397         else
398         {
399             return ;
400         }
401
402         if (startPos >= length || endPos >= length)
403         {
404             return ;
405         }
406         secStructMask[startPos - 1] = s;
407         for (i = startPos; i < endPos - 1; i++)
408         {
409             secStructMask[i] = c;
410         }
411         secStructMask[endPos - 1] = s;
412     }
413     catch(...)
414     {
415         cerr << "An exception has occured in the function RSFFileParser::getRSFFeature()\n"
416              << "Program needs to terminate.\nPlease contact the Clustal developers\n";
417         exit(1);    
418     }
419 }
420
421 /**
422  * keyword checks if code is on the line!
423  * @param line 
424  * @param code 
425  * @return 
426  */
427 bool RSFFileParser::keyword(char *line, const char *code)
428 {
429     int i;
430     char key[MAXLINE];
431
432     for (i = 0; !isspace(line[i]) && line[i] != EOS; i++)
433     {
434         key[i] = line[i];
435     }
436     key[i] = EOS;
437     return (strcmp(key, code) == 0);
438 }
439
440 }
441
442