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