Next version of JABA
[jabaws.git] / binaries / src / clustalw / src / fileInput / PearsonFileParser.cpp
1 /**
2  * Author: Mark Larkin
3  * 
4  * Copyright (c) 2007 Des Higgins, Julie Thompson and Toby Gibson.  
5  */
6 /** 
7  * Changes: 
8  *
9  * Mark 24-1-2007. I am now using the char "delimiter" for the delimiter when using
10  * getline. This is to get around the problem of some files having '\r'.
11  *
12  * 10-02-07,Nigel Brown(EMBL): Changed ifstream to InFileStream to handle
13  * cross-platform end-of-lines and removed delimiter member.
14  *
15  * 28-12-07,Paul McGettigan : replaced array processing with string processing this fixes bug #72
16  *
17  * 9-2-2008, Paul McGettigan : fixed problem where space after '>' but before sequence name was causing
18  *                             alignment to fail due to no sequence name being read in
19  * 15-2-2008, Paul McGettigan : fixed bug 91 where Pseudo -FASTA format files were not being processed as 
20  *                              previously in v1.83
21  */
22
23 #ifdef HAVE_CONFIG_H
24     #include "config.h"
25 #endif
26 #include "PearsonFileParser.h"
27
28 namespace clustalw
29 {
30
31 /**
32  * Constructor for the Pearson file parser.
33  * @param filePath 
34  * @return 
35  */
36 PearsonFileParser::PearsonFileParser(string filePath)
37 {
38     fileName = filePath;
39     fillCharTab();
40 }
41
42
43 /**
44  * reads fasta/pearson file in one go instead of calling getSeq for
45  * each single sequence.
46  *
47  * FIXME AW: only PearsonFileParser::getSeqRange is special, rest is the
48  * same. should be defined in FileParser and then overloaded in special
49  * cases like here
50  */
51 vector<Sequence>
52 PearsonFileParser::getSeqRange(int firstSeq, int nSeqsToRead, string *offendingSeq)
53 {
54     string characterSeq = "";
55     string name = "";
56     string title = "";
57     string blank = "";
58     string greater = ">";
59     //_line[0] = EOS;
60     vector<Sequence> seqRangeVector;
61     
62     string line;
63     
64     
65     //int i, j;
66     int nSeqsRead = 0;
67     unsigned char c;
68     char delim;
69     int _currentSeqNum = 0; // Not at any sequence yet!
70     
71     try
72     {
73        delim=FileParser::getDelimiter(fileName);
74        //cout << "delim = " << delim << endl;
75        ifstream _fileIn;
76        _fileIn.open(fileName.c_str(),ios::in);
77
78         // Read in lines until we get to the begining of sequence firstSeq.
79         string line="";
80
81         do {
82           std::getline(_fileIn,line,delim);
83           if(line.substr(0,1) == greater){
84               _currentSeqNum++;
85           }
86         } while(_currentSeqNum <firstSeq);
87         
88         
89         while (nSeqsRead < nSeqsToRead)
90         {
91             // get sequence name from current line (excluded '>' and read up to first ' ' or MAXNAMES
92             // remove the first char i.e. '>'
93             name=line.substr(1,MAXNAMES);
94             //if(name.find(">") != string::npos){
95             //  andreas wilm: exit if angle bracket within header?
96             //}
97             
98             while(name.substr(0,1)==" "){
99                 name=name.substr(1,MAXNAMES);
100             }
101             //int i;
102             //i = name.find(" ");
103             if(name.find(" ") != string::npos){
104                 name=name.substr(0,name.find(" "));
105             }
106             utilityObject->rTrim(&name); // also replaces linef
107
108             name=utilityObject->blankToUnderscore(name); // replace blanks with '_'
109             
110             
111             // Read in lines until we get to the begining of next sequence.
112             
113             title = ""; // No title information
114             
115             while(std::getline(_fileIn,line,delim) ){
116                  
117                string::const_iterator iterator1 = line.begin();
118                 while(iterator1 != line.end()){
119
120                     // Andreas Wilm (UCD): exit if angle brackets within sequence
121                     if(*iterator1=='>' && iterator1!=line.begin()) {
122                         /* error output handled in Clustal.cpp
123                         cerr << "\nMultiple angle brackets inside sequence found:"
124                              << " invalid format.\n"
125                              << "Maybe you forgot a linebreak between sequences?\n";
126                         */
127                         
128                         parseExitCode=BADFORMAT;
129                         _fileIn.close();
130                         seqRangeVector.clear();
131                         return seqRangeVector;
132                     }
133                        
134                     if(*iterator1 =='\n' || *iterator1 =='\r' || *iterator1 == EOS || *iterator1 =='>'){
135                         break;
136                     }
137                     c = *iterator1;
138
139                     c = chartab[c];
140                     if(c){
141                         characterSeq.append(1,c);
142                     }
143                     iterator1++;
144                 }
145                 if(*iterator1 == '>'){
146                     break;
147                } 
148             }
149             
150             // check sequence
151             if ((int)characterSeq.length() > userParameters->getMaxAllowedSeqLength())
152             {
153                 /* error output handled in Clustal.cpp */
154                 parseExitCode=SEQUENCETOOBIG;
155                 if (offendingSeq!=NULL)
156                     offendingSeq->assign(name);
157                 _fileIn.close();
158                 seqRangeVector.clear();
159                 return seqRangeVector;
160             }
161             else if (characterSeq.length() == 0)
162             {
163                 parseExitCode=EMPTYSEQUENCE;
164                 if (offendingSeq!=NULL)
165                     offendingSeq->assign(name);
166                 _fileIn.close();
167                 seqRangeVector.clear();
168                 return seqRangeVector;
169             }
170
171             seqRangeVector.push_back(Sequence(characterSeq, name, title));
172             characterSeq = "";
173             nSeqsRead++;
174         } // while (nSeqsRead < nSeqsToRead)
175
176         _fileIn.close();
177
178         return seqRangeVector;
179     }
180
181     catch(...)
182     {
183         cerr << "There was an exception in the PearsonFileParser::getSeqRange function.\n"
184              << "Need to end program\n";
185         exit(1);
186     }
187 }
188
189
190
191 /**
192  * The function getSeq is used to get the sequence 'seqNum' in the file. It returns a
193  * sequence object containing the sequence.
194  * Deprecated: where possible use faster getSeqRange which reads
195  * sequences in one go
196  * @param seqNum The number of the sequence to get.
197  * @return 
198  */
199     Sequence PearsonFileParser::getSeq(int seqNum, string *offendingSeq)
200 {
201     //char _line[MAXLINE + 1];
202     //char tseq[MAXLINE + 1];
203     //char sname[MAXNAMES + 1];
204     //sname [MAXNAMES] = '\0';
205     string characterSeq = "";
206     string name = "";
207     string title = "";
208     string blank = "";
209     string greater = ">";
210     //_line[0] = EOS;
211     
212     string line;
213     
214     cerr << "Use of PearsonFileParser::getSeq is deprecated!\n";
215     //int i, j;
216     unsigned char c;
217     char delim;
218     int _currentSeqNum = 0; // Not at any sequence yet!
219     
220     try
221     {
222         /*
223         _fileIn = new InFileStream; //nige
224         _fileIn->open(fileName.c_str());  //nige
225         _fileIn->seekg(0, std::ios::beg); // start at the beginning
226        */
227        delim=FileParser::getDelimiter(fileName);
228        //cout << "delim = " << delim << endl;
229        ifstream _fileIn;
230        _fileIn.open(fileName.c_str(),ios::in);
231
232         //////////////////////////////////////////////////
233         //PMcG replace char array with string processing
234         //////////////////////////////////////////////////
235
236         // Read in lines until we get to the begining of sequence seqNum.
237         string line="";
238
239         do {
240           std::getline(_fileIn,line,delim);
241           if(line.substr(0,1) == greater){
242             _currentSeqNum++;
243           }
244         } while(_currentSeqNum <seqNum);
245         
246         
247         // get sequence name from current line (excluded '>' and read up to first ' ' or MAXNAMES
248         // remove the first char i.e. '>'
249         name=line.substr(1,MAXNAMES);
250            
251         //////////////////////////////////////
252         // PMcG 9-2-2008 need to handle spaces at start of sequence name to conform to 1.83 handling
253         //////////////////////////////////////
254         while(name.substr(0,1)==" "){
255           name=name.substr(1,MAXNAMES);
256         }
257         //int i;
258         //i = name.find(" ");
259         if(name.find(" ") != string::npos){
260           name=name.substr(0,name.find(" "));
261         } 
262         name=utilityObject->blankToUnderscore(name); // replace blanks with '_'
263
264
265         // Read in lines until we get to the begining of sequence seqNum.
266           
267         /* PMcG replace char array with string processing
268         while (_currentSeqNum != seqNum)
269         {
270             while(*_line != '>')
271             {
272                 if(!_fileIn->getline(_line, MAXLINE + 1))
273                 {
274                     freeFileResources(_fileIn);
275                     return Sequence(blank, blank, blank);
276                 }
277             }
278             ++_currentSeqNum;
279             if(_currentSeqNum == seqNum) // Found the sequence
280             {
281                 break;
282             }
283             // Get next line so that we are past the '>' line
284             _fileIn->getline(_line, MAXLINE + 1);
285         }
286
287         // line contains the name of the sequence
288         for (i = 1; i <= strlen(_line); i++)
289         {
290             if (_line[i] != ' ')
291             {
292                 break;
293             }
294         }
295         strncpy(sname, _line + i, MAXNAMES); // remember entryname 
296         for (i = 1; i <= strlen(sname); i++)
297         {
298             if (sname[i] == ' ')
299             {
300                 break;
301             }
302         }
303         sname[i] = EOS;
304         utilityObject->rTrim(sname);
305         utilityObject->blankToUnderscore(sname); // replace blanks with '_'
306         name = string(sname);        
307         */
308         
309         title = ""; // No title information
310
311         string seqLine = "";
312         while(std::getline(_fileIn,seqLine,delim) ){
313           string::const_iterator iterator1 = seqLine.begin();
314           while(iterator1 != seqLine.end()){
315             if(*iterator1 =='\n' || *iterator1 =='\r' || *iterator1 == EOS || *iterator1 =='>'){
316               break;
317             }
318             c = *iterator1;
319             c = chartab[c];
320             // PMcG 15-02-2008 bug 91
321             // strip out spaces and numbers from pseudo_fasta files
322             // but need to maintain gaps if present in sequence input
323             // to replicate behaviour of v1.83
324             //if(*iterator1 != ' ' && !isdigit(*iterator1)){
325             if(c){
326               characterSeq.append(1,c);
327             }
328             iterator1++;
329           }
330           if(*iterator1 == '>'){
331             break;
332           }
333         }
334  /*
335         while (_fileIn->getline(_line, MAXLINE + 1))
336         {
337             for (i = 0; i <= MAXLINE; i++)
338             {
339                 c = _line[i];
340                 if (c == '\n' || c == EOS || c == '>')
341                 {
342                     break;
343                 }
344
345                 c = chartab[c];
346                 if (c)
347                 {
348                     characterSeq += c;
349                 }
350             }
351             if (c == '>')
352             {
353                 break;
354             }
355         }
356 */
357
358         _fileIn.close();
359
360         if ((int)characterSeq.length() > userParameters->getMaxAllowedSeqLength())
361         {
362             parseExitCode=SEQUENCETOOBIG;
363             // return empty seq
364             return Sequence(blank, blank, blank);
365         }
366         else if (characterSeq.length() == 0)
367         {
368             parseExitCode=EMPTYSEQUENCE;
369             // return empty seq
370             return Sequence(blank, blank, blank);
371         }
372         
373         return Sequence(characterSeq, name, title);
374     }
375
376     catch(...)
377     {
378         cerr << "There was an exception in the PearsonFileParser::getSeq function.\n"
379              << "Need to end program\n";
380         exit(1);
381     }
382 }
383
384 /**
385  * The function countSeqs, counts the number of sequences in a file.
386  * @return The number of sequences in the file.
387  */
388 int PearsonFileParser::countSeqs()
389 {
390     //char line[1000 + 1];
391     int _nseqs = 0;
392     string line2;
393     char delim;
394
395     try
396     {
397         //_fileIn = new InFileStream;  //nige
398         //_fileIn->open(fileName.c_str());  //nige
399         delim=FileParser::getDelimiter(fileName);
400         ifstream _fileIn;
401         _fileIn.open(fileName.c_str(),ios::in);
402
403     
404         if(!_fileIn.is_open())
405         {
406             return 0; // No sequences found!
407         }
408     
409         /* while ((*_fileIn) >> line2/@_fileIn->getline(line, 1000 + 1)@/)
410            {
411            /@if(_nseqs == 50)
412            {
413            cout << "\n\n" << line << "\n\n";
414            exit(1);
415            }@/
416             */
417         while (std::getline(_fileIn,line2,delim)) {                 
418             if (line2[0] == '>')
419                 {
420                     _nseqs++;
421                 }
422         }
423         _fileIn.close();
424         return _nseqs;
425     }
426     catch(...)
427     {
428         freeFileResources(_fileIn);
429         cerr << "An exception has occured in the function PearsonFileParser::countSeqs()\n"
430              << "Program needs to terminate.\nPlease contact the Clustal developers\n";
431         exit(1);    
432     }
433 }
434
435 /**
436  * There is no secondary structure information in the Pearson file. This is here to 
437  * set the structPenalties to NONE.
438  * @param gapPenaltyMask 
439  * @param secStructMask 
440  * @param secStructName 
441  * @param structPenalties 
442  * @param length 
443  */
444 void PearsonFileParser::getSecStructure(vector<char>& gapPenaltyMask, 
445                          vector<char>& secStructMask, string& secStructName, 
446                           int &structPenalties, int length)
447 {
448     structPenalties = NONE;
449 }
450
451 }
452
453