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