]> git.donarmstrong.com Git - mothur.git/blob - engine.cpp
modifications to commands to add headers to list file.
[mothur.git] / engine.cpp
1 /*
2  *  engine.cpp
3  *  
4  *
5  *  Created by Pat Schloss on 8/15/08.
6  *  Copyright 2008 Patrick D. Schloss. All rights reserved.
7  *
8  *  There's a TON of duplicated code between InteractEngine and BatchEngine
9  *  I couldn't figure out how to transition between ifstream (batch) and cin (interact)
10  *  Fix later, don't have time now.
11  *
12  */
13
14
15 #include "engine.hpp"
16
17 /***********************************************************************/
18 Engine::Engine(){
19         try {
20                 cFactory = CommandFactory::getInstance();
21                 mout = MothurOut::getInstance();
22         }
23         catch(exception& e) {
24                 mout->errorOut(e, "Engine", "Engine");
25                 exit(1);
26         }
27 }
28 /***********************************************************************/
29
30 /***********************************************************************/
31
32 InteractEngine::InteractEngine(string path){
33
34         
35         string temppath = path.substr(0, (path.find_last_of("othur")-5));
36         
37         //this will happen if you set the path variable to contain mothur's exe location
38         if (temppath == "") { path = mout->findProgramPath("mothur"); }
39         
40         mout->argv = path;
41 }
42
43 /***********************************************************************/
44
45 InteractEngine::~InteractEngine(){}
46
47 /***********************************************************************/
48 //This function allows the user to input commands one line at a time until they quit.
49 //If the command is garbage it does nothing.
50 bool InteractEngine::getInput(){
51         try {
52                 string input = "";
53                 string commandName = "";
54                 string options = "";
55                 int quitCommandCalled = 0;
56                 
57                 while(quitCommandCalled != 1){
58
59                         #ifdef USE_MPI
60                                 int pid, processors;
61                                 MPI_Status status;
62                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
63                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
64                                 
65                                 if (pid == 0) {
66                                 
67                         #endif
68                     
69                         if (mout->changedSeqNames) { mout->mothurOut("[WARNING]: your sequence names contained ':'.  I changed them to '_' to avoid problems in your downstream analysis.\n"); }
70                     
71                         mout->mothurOutEndLine();
72                         
73                         input = getCommand();   
74                         mout->mothurOutEndLine();       
75                         
76                         if (mout->control_pressed) { input = "quit()"; }
77                         
78                         //allow user to omit the () on the quit command
79                         if (input == "quit") { input = "quit()"; }
80
81                         
82                         #ifdef USE_MPI
83                                 //send commandName
84                                 for(int i = 1; i < processors; i++) { 
85                                                 int length = input.length();
86                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
87                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
88         
89                                         }
90                                 }else {
91                                         int length;
92                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
93                                         //recieve container
94                                         char* tempBuf = new char[length];
95                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
96                                         
97                                         input = tempBuf;
98                                         if (input.length() > length) { input = input.substr(0, length);  }
99                                         delete tempBuf; 
100                                 }
101
102                         
103                         #endif
104                 
105                         CommandOptionParser parser(input);
106                         commandName = parser.getCommandString();
107         
108                         options = parser.getOptionString();
109                         
110                         if (commandName != "") {
111                                         mout->executing = true;
112                                         #ifdef USE_MPI
113                                                 int pid;
114                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
115                                                 
116                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
117                                         //cout << pid << " is in execute " << commandName << endl;
118                                         #endif
119                                         //executes valid command
120                     mout->changedSeqNames = false;
121                                         mout->runParse = true;
122                                         mout->clearGroups();
123                                         mout->clearAllGroups();
124                                         mout->Treenames.clear();
125                                         mout->saveNextLabel = "";
126                     mout->commandInputsConvertError = false;
127                                         mout->printedSharedHeaders = false;
128                                         mout->currentSharedBinLabels.clear();
129                                         mout->sharedBinLabelsInFile.clear();
130                     mout->printedListHeaders = false;
131                     mout->listBinLabelsInFile.clear();
132                                                         
133                                         Command* command = cFactory->getCommand(commandName, options);
134                                         if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
135                                         else { quitCommandCalled = command->execute(); }
136                                                         
137                                         //if we aborted command
138                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
139
140                                         mout->control_pressed = 0;
141                                         mout->executing = false;
142                                                                                 
143                                         #ifdef USE_MPI
144                                                 }
145                                         #endif
146                                 }else {         
147                                         mout->mothurOut("Invalid."); 
148                                         mout->mothurOutEndLine();
149                                 }
150                 }       
151                 return 1;
152         }
153         catch(exception& e) {
154                 mout->errorOut(e, "InteractEngine", "getInput");
155                 exit(1);
156         }
157 }
158 /***********************************************************************/
159 string Engine::getCommand()  {
160         try {
161         
162                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
163                         #ifdef USE_READLINE
164                                 char* nextCommand = NULL;
165                                 nextCommand = readline("mothur > ");
166                                 
167                                 if(nextCommand != NULL) {  add_history(nextCommand);  } 
168                                 else{ //^D causes null string and we want it to quit mothur
169                                         nextCommand = strdup("quit");
170                                         mout->mothurOut(nextCommand);
171                                 }       
172                                 
173                                 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
174                                 return nextCommand;
175                         #else
176                                 string nextCommand = "";
177                                 mout->mothurOut("mothur > ");
178                                 getline(cin, nextCommand);
179                                 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
180                                 
181                                 return nextCommand;
182                         #endif
183                 #else
184                                 string nextCommand = "";
185                                 
186                                 mout->mothurOut("mothur > ");
187                                 getline(cin, nextCommand);
188                                 mout->mothurOutJustToLog(toString(nextCommand));
189                                 
190                                 return nextCommand;
191                 #endif
192         
193                                                 
194         }
195         catch(exception& e) {
196                 mout->errorOut(e, "Engine", "getCommand");
197                 exit(1);
198         }
199 }
200 /***********************************************************************/
201 //This function opens the batchfile to be used by BatchEngine::getInput.
202 BatchEngine::BatchEngine(string path, string batchFileName){
203         try {
204         
205                 openedBatch = mout->openInputFile(batchFileName, inputBatchFile);
206                 
207                 string temppath = path.substr(0, (path.find_last_of("othur")-5));
208         
209                 //this will happen if you set the path variable to contain mothur's exe location
210                 if (temppath == "") { path = mout->findProgramPath("mothur"); }
211                 
212                 mout->argv = path;
213                                 
214         }
215         catch(exception& e) {
216                 mout->errorOut(e, "BatchEngine", "BatchEngine");
217                 exit(1);
218         }
219 }
220
221 /***********************************************************************/
222
223 BatchEngine::~BatchEngine(){    }
224
225 /***********************************************************************/
226 //This Function allows the user to run a batchfile containing several commands on Dotur
227 bool BatchEngine::getInput(){
228         try {
229                 //check if this is a valid batchfile
230                 if (openedBatch == 1) {  
231                         mout->mothurOut("unable to open batchfile");  
232                         mout->mothurOutEndLine();
233                         return 1; 
234                 }
235         
236                 string input = "";
237                 string commandName = "";
238                 string options = "";
239                 
240                 //CommandFactory cFactory;
241                 int quitCommandCalled = 0;
242             int count = 0;
243                 while(quitCommandCalled != 1){
244                         
245                         #ifdef USE_MPI
246                                 int pid, processors;
247                                 MPI_Status status;
248                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
249                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
250                                 
251                                 if (pid == 0) {
252                                 
253                         #endif
254                         
255                         input = getNextCommand(inputBatchFile);
256                         count++;
257                         
258                         #ifdef USE_MPI
259                                 //send commandName
260                                 for(int i = 1; i < processors; i++) { 
261                                                 int length = input.length();
262                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
263                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
264         
265                                         }
266                                 }else {
267                                         int length;
268                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
269                                         //recieve container
270                                         char* tempBuf = new char[length];
271                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
272                                         
273                                         input = tempBuf;
274                                         if (input.length() > length) { input = input.substr(0, length);  }
275                                         delete tempBuf; 
276                                 }
277
278                         
279                         #endif
280
281                         
282                         
283                         if (input[0] != '#') {
284                                 if (mout->changedSeqNames) { mout->mothurOut("[WARNING]: your sequence names contained ':'.  I changed them to '_' to avoid problems in your downstream analysis.\n"); }
285                                 mout->mothurOutEndLine();
286                                 mout->mothurOut("mothur > " + input);
287                                 mout->mothurOutEndLine();
288                                                         
289                                 if (mout->control_pressed) { input = "quit()"; }
290                                 
291                                 //allow user to omit the () on the quit command
292                                 if (input == "quit") { input = "quit()"; }
293
294                                 CommandOptionParser parser(input);
295                                 commandName = parser.getCommandString();
296                                 options = parser.getOptionString();
297                                                                                 
298                                 if (commandName != "") {
299                                         mout->executing = true;
300                                         #ifdef USE_MPI
301                                                 int pid;
302                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
303                                                 
304 //cout << pid << " is here " << commandName << '\t' << count << endl;
305                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
306                                         #endif
307                                         //executes valid command
308                     mout->changedSeqNames = false;
309                                         mout->runParse = true;
310                                         mout->clearGroups();
311                                         mout->clearAllGroups();
312                                         mout->Treenames.clear();
313                                         mout->saveNextLabel = "";
314                                         mout->commandInputsConvertError = false;
315                     mout->printedSharedHeaders = false;
316                     mout->currentSharedBinLabels.clear();
317                     mout->sharedBinLabelsInFile.clear();
318                     mout->printedListHeaders = false;
319                     mout->listBinLabelsInFile.clear();
320
321                                                         
322                                         Command* command = cFactory->getCommand(commandName, options);
323                                         if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
324                                         else { quitCommandCalled = command->execute(); }
325                                                         
326                                         //if we aborted command
327                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
328
329                                         mout->control_pressed = 0;
330                                         mout->executing = false;
331                                                                                 
332                                         #ifdef USE_MPI
333                                                 }
334                                         #endif
335                                 }else {         
336                                         mout->mothurOut("Invalid."); 
337                                         mout->mothurOutEndLine();
338                                 }
339                                 
340                         }
341                         mout->gobble(inputBatchFile);
342                 }
343                 
344                 inputBatchFile.close();
345                 return 1;
346         }
347         catch(exception& e) {
348                 mout->errorOut(e, "BatchEngine", "getInput");
349                 exit(1);
350         }
351 }
352 /***********************************************************************/
353 string BatchEngine::getNextCommand(ifstream& inputBatchFile) {
354         try {
355                         
356                 string nextcommand = "";
357                 
358                 if (inputBatchFile.eof()) { nextcommand = "quit()"; }
359                 else { nextcommand = mout->getline(inputBatchFile); }
360                 
361                 return nextcommand;
362         }
363         catch(exception& e) {
364                 mout->errorOut(e, "BatchEngine", "getNextCommand");
365                 exit(1);
366         }
367 }
368
369 /***********************************************************************/
370 /***********************************************************************/
371 //This function opens the batchfile to be used by BatchEngine::getInput.
372 ScriptEngine::ScriptEngine(string path, string commandString){
373         try {
374                 
375                 //remove quotes
376                 listOfCommands = commandString.substr(1, (commandString.length()-1));
377                 
378                 string temppath = path.substr(0, (path.find_last_of("othur")-5));
379
380                 //this will happen if you set the path variable to contain mothur's exe location
381                 if (temppath == "") { path = mout->findProgramPath("mothur"); }
382                 
383                 mout->argv = path;
384                                 
385         }
386         catch(exception& e) {
387                 mout->errorOut(e, "ScriptEngine", "ScriptEngine");
388                 exit(1);
389         }
390 }
391
392 /***********************************************************************/
393
394 ScriptEngine::~ScriptEngine(){  }
395
396 /***********************************************************************/
397 //This Function allows the user to run a batchfile containing several commands on mothur
398 bool ScriptEngine::getInput(){
399         try {
400                         
401                 string input = "";
402                 string commandName = "";
403                 string options = "";
404                 
405                 
406                 //CommandFactory cFactory;
407                 int quitCommandCalled = 0;
408         
409                 while(quitCommandCalled != 1){
410                         
411                         #ifdef USE_MPI
412                                 int pid, processors;
413                                 MPI_Status status;
414                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
415                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
416                                 
417                                 if (pid == 0) {
418                                 
419                         #endif
420                         
421                         input = getNextCommand(listOfCommands); 
422                         
423                         if (input == "") { input = "quit()"; }
424                     
425             if (mout->changedSeqNames) { mout->mothurOut("[WARNING]: your sequence names contained ':'.  I changed them to '_' to avoid problems in your downstream analysis.\n"); }
426                         
427                         if (mout->gui) {
428                                 if ((input.find("quit") != string::npos) || (input.find("set.logfile") != string::npos)) {}
429                                 else if ((input.find("get.current") != string::npos) && (!mout->hasCurrentFiles())) {}
430                                 else { mout->mothurOutEndLine(); mout->mothurOut("mothur > " + input); mout->mothurOutEndLine(); }
431                         }else{
432                                 mout->mothurOutEndLine(); mout->mothurOut("mothur > " + input); mout->mothurOutEndLine();
433                         }
434                         
435                         #ifdef USE_MPI
436                                 //send commandName
437                                 for(int i = 1; i < processors; i++) { 
438                                                 int length = input.length();
439                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
440                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
441         
442                                         }
443                                 }else {
444                                         int length;
445                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
446                                         //recieve container
447                                         char* tempBuf = new char[length];
448                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
449                                         
450                                         input = tempBuf;
451                                         if (input.length() > length) { input = input.substr(0, length);  }
452                                         delete tempBuf; 
453                                 }
454
455                         
456                         #endif
457                         
458                         
459                         if (mout->control_pressed) { input = "quit()"; }
460                                 
461                         //allow user to omit the () on the quit command
462                         if (input == "quit") { input = "quit()"; }
463
464                         CommandOptionParser parser(input);
465                         commandName = parser.getCommandString();
466                         options = parser.getOptionString();
467                                                                                 
468                         if (commandName != "") {
469                                         mout->executing = true;
470                                         #ifdef USE_MPI
471                                                 int pid, numProcesses;
472                                                 
473                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
474                                                 MPI_Comm_size(MPI_COMM_WORLD, &numProcesses); 
475                                         
476 //cout << pid << " is here " << commandName  << endl;
477                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
478                                                         //cout << pid << " is in execute" << endl;      
479                                         #endif
480                                         //executes valid command
481                     mout->changedSeqNames = false;
482                                         mout->runParse = true;
483                                         mout->clearGroups();
484                                         mout->clearAllGroups();
485                                         mout->Treenames.clear();
486                                         mout->saveNextLabel = "";
487                     mout->commandInputsConvertError = false;
488                     mout->printedSharedHeaders = false;
489                     mout->currentSharedBinLabels.clear();
490                     mout->sharedBinLabelsInFile.clear();
491                     mout->printedListHeaders = false;
492                     mout->listBinLabelsInFile.clear();
493
494                                         Command* command = cFactory->getCommand(commandName, options);
495                                         if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
496                                         else { quitCommandCalled = command->execute(); }
497                                         
498                                         //if we aborted command
499                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
500                                                         
501                                         mout->control_pressed = 0;
502                                         mout->executing = false;
503                                                                         
504                                         #ifdef USE_MPI
505                                         //cout << pid << " is done in execute" << endl;
506                                                 }
507                                         #endif
508                                 }else {         
509                                         mout->mothurOut("Invalid."); 
510                                         mout->mothurOutEndLine();
511                                 }
512
513                         
514                 }
515                 
516                 return 1;
517         }
518         catch(exception& e) {
519                 mout->errorOut(e, "ScriptEngine", "getInput");
520                 exit(1);
521         }
522 }
523 /***********************************************************************/
524 string ScriptEngine::getNextCommand(string& commandString) {
525         try {
526                 
527                 string nextcommand = "";
528                 int count = 0;
529                 bool ignoreSemiColons = false;
530                 
531                 //go through string until you reach ; or end
532                 while (count < commandString.length()) { 
533                         
534                          //you want to ignore any ; until you reach the next '
535                         if ((commandString[count] == '\'') && (!ignoreSemiColons)) {  ignoreSemiColons = true;  } 
536                         else if ((commandString[count] == '\'') && (ignoreSemiColons)) {  ignoreSemiColons = false;  } 
537                                 
538                         if ((commandString[count] == ';') && (!ignoreSemiColons)) {  break;   }
539                         else {          nextcommand += commandString[count];    }
540                         
541                         count++;
542                 }
543                 
544                 //if you are not at the end
545                 if (count != commandString.length())  {   commandString = commandString.substr(count+1, commandString.length());  }
546                 else { commandString = ""; }
547                                 
548                 
549                 //get rid of spaces in between commands if any
550                 if (commandString.length() > 0) {
551                         while (commandString[0] == ' ') {  
552                                 commandString = commandString.substr(1,commandString.length());
553                                 if (commandString.length() == 0) {  break;  }
554                         }
555                 }
556                 
557                 return nextcommand;
558         }
559         catch(exception& e) {
560                 mout->errorOut(e, "ScriptEngine", "getNextCommand");
561                 exit(1);
562         }
563 }
564 /***********************************************************************/