]> git.donarmstrong.com Git - mothur.git/blob - engine.cpp
added tree reader class to handle reading trees. Reworked the tree map to tree class...
[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->saveNextLabel = "";
187                                         mout->printedHeaders = false;
188                                         mout->commandInputsConvertError = false;
189                                         mout->currentBinLabels.clear();
190                                         mout->binLabelsInFile.clear();
191                                                         
192                                         Command* command = cFactory->getCommand(commandName, options);
193                                         if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
194                                         else { quitCommandCalled = command->execute(); }
195                                                         
196                                         //if we aborted command
197                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
198
199                                         mout->control_pressed = 0;
200                                         mout->executing = false;
201                                                                                 
202                                         #ifdef USE_MPI
203                                                 }
204                                         #endif
205                                 }else {         
206                                         mout->mothurOut("Invalid."); 
207                                         mout->mothurOutEndLine();
208                                 }
209                 }       
210                 return 1;
211         }
212         catch(exception& e) {
213                 mout->errorOut(e, "InteractEngine", "getInput");
214                 exit(1);
215         }
216 }
217 /***********************************************************************/
218 string Engine::getCommand()  {
219         try {
220         
221                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
222                         #ifdef USE_READLINE
223                                 char* nextCommand = NULL;
224                                 nextCommand = readline("mothur > ");
225                                 
226                                 if(nextCommand != NULL) {  add_history(nextCommand);  } 
227                                 else{ //^D causes null string and we want it to quit mothur
228                                         nextCommand = strdup("quit");
229                                         mout->mothurOut(nextCommand);
230                                 }       
231                                 
232                                 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
233                                 return nextCommand;
234                         #else
235                                 string nextCommand = "";
236                                 mout->mothurOut("mothur > ");
237                                 getline(cin, nextCommand);
238                                 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
239                                 
240                                 return nextCommand;
241                         #endif
242                 #else
243                                 string nextCommand = "";
244                                 
245                                 mout->mothurOut("mothur > ");
246                                 getline(cin, nextCommand);
247                                 mout->mothurOutJustToLog(toString(nextCommand));
248                                 
249                                 return nextCommand;
250                 #endif
251         
252                                                 
253         }
254         catch(exception& e) {
255                 mout->errorOut(e, "Engine", "getCommand");
256                 exit(1);
257         }
258 }
259 /***********************************************************************/
260 //This function opens the batchfile to be used by BatchEngine::getInput.
261 BatchEngine::BatchEngine(string path, string batchFileName){
262         try {
263         
264                 openedBatch = mout->openInputFile(batchFileName, inputBatchFile);
265                 
266                 string temppath = path.substr(0, (path.find_last_of("othur")-5));
267         
268                 //this will happen if you set the path variable to contain mothur's exe location
269                 if (temppath == "") { path = findMothursPath(); }
270                 
271                 mout->argv = path;
272                                 
273         }
274         catch(exception& e) {
275                 mout->errorOut(e, "BatchEngine", "BatchEngine");
276                 exit(1);
277         }
278 }
279
280 /***********************************************************************/
281
282 BatchEngine::~BatchEngine(){    }
283
284 /***********************************************************************/
285 //This Function allows the user to run a batchfile containing several commands on Dotur
286 bool BatchEngine::getInput(){
287         try {
288                 //check if this is a valid batchfile
289                 if (openedBatch == 1) {  
290                         mout->mothurOut("unable to open batchfile");  
291                         mout->mothurOutEndLine();
292                         return 1; 
293                 }
294         
295                 string input = "";
296                 string commandName = "";
297                 string options = "";
298                 
299                 //CommandFactory cFactory;
300                 int quitCommandCalled = 0;
301             int count = 0;
302                 while(quitCommandCalled != 1){
303                         
304                         #ifdef USE_MPI
305                                 int pid, processors;
306                                 MPI_Status status;
307                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
308                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
309                                 
310                                 if (pid == 0) {
311                                 
312                         #endif
313                         
314                         input = getNextCommand(inputBatchFile);
315                         count++;
316                         
317                         #ifdef USE_MPI
318                                 //send commandName
319                                 for(int i = 1; i < processors; i++) { 
320                                                 int length = input.length();
321                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
322                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
323         
324                                         }
325                                 }else {
326                                         int length;
327                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
328                                         //recieve container
329                                         char* tempBuf = new char[length];
330                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
331                                         
332                                         input = tempBuf;
333                                         if (input.length() > length) { input = input.substr(0, length);  }
334                                         delete tempBuf; 
335                                 }
336
337                         
338                         #endif
339
340                         
341                         
342                         if (input[0] != '#') {
343                                 
344                                 mout->mothurOutEndLine();
345                                 mout->mothurOut("mothur > " + input);
346                                 mout->mothurOutEndLine();
347                                                         
348                                 if (mout->control_pressed) { input = "quit()"; }
349                                 
350                                 //allow user to omit the () on the quit command
351                                 if (input == "quit") { input = "quit()"; }
352
353                                 CommandOptionParser parser(input);
354                                 commandName = parser.getCommandString();
355                                 options = parser.getOptionString();
356                                                                                 
357                                 if (commandName != "") {
358                                         mout->executing = true;
359                                         #ifdef USE_MPI
360                                                 int pid;
361                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
362                                                 
363 //cout << pid << " is here " << commandName << '\t' << count << endl;
364                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
365                                         #endif
366                                         //executes valid command
367                                         mout->runParse = true;
368                                         mout->clearGroups();
369                                         mout->clearAllGroups();
370                                         mout->Treenames.clear();
371                                         mout->saveNextLabel = "";
372                                         mout->printedHeaders = false;
373                                         mout->commandInputsConvertError = false;
374                                         mout->currentBinLabels.clear();
375                                         mout->binLabelsInFile.clear();
376
377                                                         
378                                         Command* command = cFactory->getCommand(commandName, options);
379                                         if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
380                                         else { quitCommandCalled = command->execute(); }
381                                                         
382                                         //if we aborted command
383                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
384
385                                         mout->control_pressed = 0;
386                                         mout->executing = false;
387                                                                                 
388                                         #ifdef USE_MPI
389                                                 }
390                                         #endif
391                                 }else {         
392                                         mout->mothurOut("Invalid."); 
393                                         mout->mothurOutEndLine();
394                                 }
395                                 
396                         }
397                         mout->gobble(inputBatchFile);
398                 }
399                 
400                 inputBatchFile.close();
401                 return 1;
402         }
403         catch(exception& e) {
404                 mout->errorOut(e, "BatchEngine", "getInput");
405                 exit(1);
406         }
407 }
408 /***********************************************************************/
409 string BatchEngine::getNextCommand(ifstream& inputBatchFile) {
410         try {
411                         
412                 string nextcommand = "";
413                 
414                 if (inputBatchFile.eof()) { nextcommand = "quit()"; }
415                 else { nextcommand = mout->getline(inputBatchFile); }
416                 
417                 return nextcommand;
418         }
419         catch(exception& e) {
420                 mout->errorOut(e, "BatchEngine", "getNextCommand");
421                 exit(1);
422         }
423 }
424
425 /***********************************************************************/
426 /***********************************************************************/
427 //This function opens the batchfile to be used by BatchEngine::getInput.
428 ScriptEngine::ScriptEngine(string path, string commandString){
429         try {
430                 
431                 //remove quotes
432                 listOfCommands = commandString.substr(1, (commandString.length()-1));
433                 
434                 string temppath = path.substr(0, (path.find_last_of("othur")-5));
435
436                 //this will happen if you set the path variable to contain mothur's exe location
437                 if (temppath == "") { path = findMothursPath(); }
438                 
439                 mout->argv = path;
440                                 
441         }
442         catch(exception& e) {
443                 mout->errorOut(e, "ScriptEngine", "ScriptEngine");
444                 exit(1);
445         }
446 }
447
448 /***********************************************************************/
449
450 ScriptEngine::~ScriptEngine(){  }
451
452 /***********************************************************************/
453 //This Function allows the user to run a batchfile containing several commands on mothur
454 bool ScriptEngine::getInput(){
455         try {
456                         
457                 string input = "";
458                 string commandName = "";
459                 string options = "";
460                 
461                 
462                 //CommandFactory cFactory;
463                 int quitCommandCalled = 0;
464         
465                 while(quitCommandCalled != 1){
466                         
467                         #ifdef USE_MPI
468                                 int pid, processors;
469                                 MPI_Status status;
470                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
471                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
472                                 
473                                 if (pid == 0) {
474                                 
475                         #endif
476                         
477                         input = getNextCommand(listOfCommands); 
478                         
479                         if (input == "") { input = "quit()"; }
480                         
481                         if (mout->gui) {
482                                 if ((input.find("quit") != string::npos) || (input.find("set.logfile") != string::npos)) {}
483                                 else if ((input.find("get.current") != string::npos) && (!mout->hasCurrentFiles())) {}
484                                 else { mout->mothurOutEndLine(); mout->mothurOut("mothur > " + input); mout->mothurOutEndLine(); }
485                         }else{
486                                 mout->mothurOutEndLine(); mout->mothurOut("mothur > " + input); mout->mothurOutEndLine();
487                         }
488                         
489                         #ifdef USE_MPI
490                                 //send commandName
491                                 for(int i = 1; i < processors; i++) { 
492                                                 int length = input.length();
493                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
494                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
495         
496                                         }
497                                 }else {
498                                         int length;
499                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
500                                         //recieve container
501                                         char* tempBuf = new char[length];
502                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
503                                         
504                                         input = tempBuf;
505                                         if (input.length() > length) { input = input.substr(0, length);  }
506                                         delete tempBuf; 
507                                 }
508
509                         
510                         #endif
511                         
512                         
513                         if (mout->control_pressed) { input = "quit()"; }
514                                 
515                         //allow user to omit the () on the quit command
516                         if (input == "quit") { input = "quit()"; }
517
518                         CommandOptionParser parser(input);
519                         commandName = parser.getCommandString();
520                         options = parser.getOptionString();
521                                                                                 
522                         if (commandName != "") {
523                                         mout->executing = true;
524                                         #ifdef USE_MPI
525                                                 int pid, numProcesses;
526                                                 
527                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
528                                                 MPI_Comm_size(MPI_COMM_WORLD, &numProcesses); 
529                                         
530 //cout << pid << " is here " << commandName  << endl;
531                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
532                                                         //cout << pid << " is in execute" << endl;      
533                                         #endif
534                                         //executes valid command
535                                         mout->runParse = true;
536                                         mout->clearGroups();
537                                         mout->clearAllGroups();
538                                         mout->Treenames.clear();
539                                         mout->saveNextLabel = "";
540                                         mout->printedHeaders = false;
541                                         mout->commandInputsConvertError = false;
542                                         mout->currentBinLabels.clear();
543                                         mout->binLabelsInFile.clear();
544
545                                         Command* command = cFactory->getCommand(commandName, options);
546                                         if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
547                                         else { quitCommandCalled = command->execute(); }
548                                         
549                                         //if we aborted command
550                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
551                                                         
552                                         mout->control_pressed = 0;
553                                         mout->executing = false;
554                                                                         
555                                         #ifdef USE_MPI
556                                         //cout << pid << " is done in execute" << endl;
557                                                 }
558                                         #endif
559                                 }else {         
560                                         mout->mothurOut("Invalid."); 
561                                         mout->mothurOutEndLine();
562                                 }
563
564                         
565                 }
566                 
567                 return 1;
568         }
569         catch(exception& e) {
570                 mout->errorOut(e, "ScriptEngine", "getInput");
571                 exit(1);
572         }
573 }
574 /***********************************************************************/
575 string ScriptEngine::getNextCommand(string& commandString) {
576         try {
577                 
578                 string nextcommand = "";
579                 int count = 0;
580                 bool ignoreSemiColons = false;
581                 
582                 //go through string until you reach ; or end
583                 while (count < commandString.length()) { 
584                         
585                          //you want to ignore any ; until you reach the next '
586                         if ((commandString[count] == '\'') && (!ignoreSemiColons)) {  ignoreSemiColons = true;  } 
587                         else if ((commandString[count] == '\'') && (ignoreSemiColons)) {  ignoreSemiColons = false;  } 
588                                 
589                         if ((commandString[count] == ';') && (!ignoreSemiColons)) {  break;   }
590                         else {          nextcommand += commandString[count];    }
591                         
592                         count++;
593                 }
594                 
595                 //if you are not at the end
596                 if (count != commandString.length())  {   commandString = commandString.substr(count+1, commandString.length());  }
597                 else { commandString = ""; }
598                                 
599                 
600                 //get rid of spaces in between commands if any
601                 if (commandString.length() > 0) {
602                         while (commandString[0] == ' ') {  
603                                 commandString = commandString.substr(1,commandString.length());
604                                 if (commandString.length() == 0) {  break;  }
605                         }
606                 }
607                 
608                 return nextcommand;
609         }
610         catch(exception& e) {
611                 mout->errorOut(e, "ScriptEngine", "getNextCommand");
612                 exit(1);
613         }
614 }
615 /***********************************************************************/