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