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