/* * MrBayes 3 * * (c) 2002-2013 * * John P. Huelsenbeck * Dept. Integrative Biology * University of California, Berkeley * Berkeley, CA 94720-3140 * johnh@berkeley.edu * * Fredrik Ronquist * Swedish Museum of Natural History * Box 50007 * SE-10405 Stockholm, SWEDEN * fredrik.ronquist@nrm.se * * With important contributions by * * Paul van der Mark (paulvdm@sc.fsu.edu) * Maxim Teslenko (maxkth@gmail.com) * Chi Zhang (zhangchicool@gmail.com) * * and by many users (run 'acknowledgments' to see more info) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details (www.gnu.org). * */ #include "bayes.h" #include "command.h" #include "model.h" #include "sumpt.h" #include "utils.h" /* We only do proper command line parsing if we're on a system where the unistd.h header is available */ #ifdef HAVE_UNISTD_H #define UNIX_COMMAND_LINE_PARSING 1 #include /* getopt() */ #endif #ifdef HAVE_LIBREADLINE # if defined(HAVE_READLINE_READLINE_H) # include # elif defined(HAVE_READLINE_H) # include # endif /* !defined(HAVE_READLINE_H) */ #endif /* HAVE_LIBREADLINE */ #ifdef HAVE_READLINE_HISTORY # if defined(HAVE_READLINE_HISTORY_H) # include # elif defined(HAVE_HISTORY_H) # include # endif /* defined(HAVE_READLINE_HISTORY_H) */ #endif /* HAVE_READLINE_HISTORY */ #ifdef HAVE_LIBREADLINE static char **readline_completion(const char *, int, int); #endif /* local prototypes */ int CommandLine (int argc, char **argv); void GetTimeSeed (void); int InitializeMrBayes (void); void PrintHeader (void); int ReinitializeMrBayes (void); /* global variables, declared in this file */ BitsLong bitsLongWithAllBitsSet; /* BitsLong with all bits set, for bit ops */ ModelParams defaultModel; /* Default model; vals set in InitializeMrBayes */ int defTaxa; /* flag for whether number of taxa is known */ int defChars; /* flag for whether number of chars is known */ int defMatrix; /* flag for whether matrix is successfull read */ int defPartition; /* flag for whether character partition is read */ int defPairs; /* flag for whether pairs are read */ Doublet doublet[16]; /* holds information on states for doublets */ int fileNameChanged; /* has file name been changed ? */ RandLong globalSeed; /* seed that is initialized at start up */ char **modelIndicatorParams; /* model indicator params */ char ***modelElementNames; /* names for component models */ int nBitsInALong; /* number of bits in a BitsLong */ int nPThreads; /* number of pthreads to use */ int numUserTrees; /* number of defined user trees */ int readComment; /* should we read comment (looking for &) ? */ int readWord; /* should we read word next ? */ RandLong runIDSeed; /* seed used only for determining run ID [stamp] */ RandLong swapSeed; /* seed used only for determining which to swap */ int userLevel; /* user level */ PolyTree *userTree[MAX_NUM_USERTREES];/* array of user trees */ char workingDir[100]; /* working directory */ #if defined (MPI_ENABLED) int proc_id; /* process ID (0, 1, ..., num_procs-1) */ int num_procs; /* number of active processors */ MrBFlt myStateInfo[7]; /* likelihood/prior/heat/ran/moveInfo vals of me */ MrBFlt partnerStateInfo[7]; /* likelihood/prior/heat/ran/moveInfo vals of partner */ #endif int main (int argc, char *argv[]) { int i; # if defined (MPI_ENABLED) int ierror; # endif # if defined (WIN_VERSION) HANDLE scbh; BOOL ok; DWORD lastError; COORD largestWindow; CONSOLE_SCREEN_BUFFER_INFO csbi; int currBottom; char poltmp[256]; scbh = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(scbh, &csbi); currBottom = csbi.srWindow.Bottom; largestWindow = GetLargestConsoleWindowSize(scbh); /* Allow for screen buffer 3000 lines long and 140 characters wide */ csbi.dwSize.Y = 3000; csbi.dwSize.X = 140; SetConsoleScreenBufferSize(scbh, csbi.dwSize); /* Allow for maximum possible screen height */ csbi.srWindow.Left = 0; /* no change relative to current value */ csbi.srWindow.Top = 0; /* no change relative to current value */ csbi.srWindow.Right = 0; /* no change relative to current value */ csbi.srWindow.Bottom = largestWindow.Y - currBottom -10; /**/ ok = SetConsoleWindowInfo(scbh, FALSE, &csbi.srWindow); if (ok == FALSE) { lastError = GetLastError(); GetConsoleScreenBufferInfo(scbh, &csbi); sprintf(poltmp, "\nlastError = %d", lastError); // printf (poltmp); } # endif /* calculate the size of a long - used by bit manipulation functions */ nBitsInALong = sizeof(BitsLong) * 8; for (i=0; i' (i is for interactive)\n", spacer); MrBayesPrint ("%s or use 'set mode=interactive'\n\n", spacer); return (NO_ERROR); } /* normally, we simply wait at the prompt for a user action */ # if defined (MPI_ENABLED) if (proc_id == 0) { /* do not use readline because OpenMPI does not handle it */ MrBayesPrint ("MrBayes > "); fflush (stdin); if (fgets (cmdStr, CMD_STRING_LENGTH - 2, stdin) == NULL) { if (feof(stdin)) MrBayesPrint ("%s End of File encountered on stdin; quitting\n", spacer); else MrBayesPrint ("%s Could not read command from stdin; quitting\n", spacer); strcpy (cmdStr,"quit;\n"); } } ierror = MPI_Bcast (&cmdStr, CMD_STRING_LENGTH, MPI_CHAR, 0, MPI_COMM_WORLD); if (ierror != MPI_SUCCESS) { MrBayesPrint ("%s Problem broadcasting command string\n", spacer); } # else # ifdef HAVE_LIBREADLINE cmdStrP = readline("MrBayes > "); if (cmdStrP!=NULL) { strncpy (cmdStr,cmdStrP,CMD_STRING_LENGTH - 2); if (*cmdStrP) add_history (cmdStrP); free (cmdStrP); } else /* fall through to if (feof(stdin))..*/ # else MrBayesPrint ("MrBayes > "); fflush (stdin); if (fgets (cmdStr, CMD_STRING_LENGTH - 2, stdin) == NULL) # endif { if (feof(stdin)) MrBayesPrint ("%s End of File encountered on stdin; quitting\n", spacer); else MrBayesPrint ("%s Could not read command from stdin; quitting\n", spacer); strcpy (cmdStr,"quit;\n"); } # endif } i = 0; while (cmdStr[i] != '\0' && cmdStr[i] != '\n') i++; cmdStr[i++] = ';'; cmdStr[i] = '\0'; MrBayesPrint ("\n"); if (cmdStr[0] != ';') { /* check that all characters in the string are valid */ if (CheckStringValidity (cmdStr) == ERROR) { MrBayesPrint (" Unknown character in command string\n\n"); } else { expecting = Expecting(COMMAND); message = ParseCommand (cmdStr); if (message == NO_ERROR_QUIT) return (NO_ERROR); if (message == ERROR && quitOnError == YES) { MrBayesPrint ("%s Will exit with signal 1 (error) because quitonerror is set to yes\n", spacer); MrBayesPrint ("%s If you want control to be returned to the command line on error,\n", spacer); MrBayesPrint ("%s use 'mb -i ' (i is for interactive) or use 'set quitonerror=no'\n\n", spacer); return (ERROR); } # if defined (MPI_ENABLED) ierror = MPI_Barrier (MPI_COMM_WORLD); if (ierror != MPI_SUCCESS) { MrBayesPrint ("%s Problem at command barrier\n", spacer); } # endif MrBayesPrint ("\n"); } } } } #ifdef HAVE_LIBREADLINE extern char *command_generator(const char *text, int state); char **readline_completion (const char *text, int start, int stop) { char **matches = (char **) NULL; # ifdef COMPLETIONMATCHES if (start == 0) matches = rl_completion_matches (text, command_generator); # endif return (matches); } #endif void GetTimeSeed (void) { time_t curTime; # if defined (MPI_ENABLED) int ierror; if (proc_id == 0) { curTime = time(NULL); globalSeed = (RandLong)curTime; if (globalSeed < 0) globalSeed = -globalSeed; } ierror = MPI_Bcast(&globalSeed, 1, MPI_LONG, 0, MPI_COMM_WORLD); if (ierror != MPI_SUCCESS) { MrBayesPrint ("%s Problem broadcasting seed\n", spacer); } if (proc_id == 0) { /* Note: swapSeed will often be same as globalSeed */ curTime = time(NULL); swapSeed = (RandLong)curTime; if (swapSeed < 0) swapSeed = -swapSeed; } ierror = MPI_Bcast(&swapSeed, 1, MPI_LONG, 0, MPI_COMM_WORLD); if (ierror != MPI_SUCCESS) { MrBayesPrint ("%s Problem broadcasting swap seed\n", spacer); } if (proc_id == 0) { /* Note: runIDSeed will often be same as globalSeed */ curTime = time(NULL); runIDSeed = (RandLong)curTime; if (runIDSeed < 0) runIDSeed = -runIDSeed; } ierror = MPI_Bcast(&runIDSeed, 1, MPI_LONG, 0, MPI_COMM_WORLD); if (ierror != MPI_SUCCESS) { MrBayesPrint ("%s Problem broadcasting run ID seed\n", spacer); } # else curTime = time(NULL); globalSeed = (RandLong)curTime; if (globalSeed < 0) globalSeed = -globalSeed; /* Note: swapSeed will often be the same as globalSeed */ curTime = time(NULL); swapSeed = (RandLong)curTime; if (swapSeed < 0) swapSeed = -swapSeed; /* Note: runIDSeed will often be the same as globalSeed */ curTime = time(NULL); runIDSeed = (RandLong)curTime; if (runIDSeed < 0) runIDSeed = -runIDSeed; # endif } int InitializeMrBayes (void) { /* this function initializes the program; only call it at the start of execution */ int i, j, growthFxn[6]; nBitsInALong = sizeof(BitsLong) * 8; /* global variable: number of bits in a BitsLong */ userLevel = STANDARD_USER; /* default user level */ readWord = NO; /* should we read a word next ? */ readComment = NO; /* should we read comments? (used by tree cmd) */ fileNameChanged = NO; /* file name changed ? (used by a few commands) */ echoMB = YES; /* flag used by Manual to control printing */ # if defined (MPI_ENABLED) sprintf (manFileName, "commref_mb%sp.txt", VERSION_NUMBER); /* name of command reference file */ # else sprintf (manFileName, "commref_mb%s.txt", VERSION_NUMBER); /* name of command reference file */ # endif for (i=0; i\" for information\n"); MrBayesPrint (" on the commands that are available.\n\n"); MrBayesPrint (" Type \"about\" for authorship and general\n"); MrBayesPrint (" information about the program.\n\n\n"); } int ReinitializeMrBayes (void) { /* this function resets everything dependent on a matrix */ int i; /* reinitialize indentation */ strcpy (spacer, ""); /* holds blanks for indentation */ /* reset all taxa flags */ ResetTaxaFlags(); /* reset all characters flags */ ResetCharacterFlags(); /* chain parameters */ chainParams.numGen = 1000000; /* number of MCMC cycles */ chainParams.sampleFreq = 500; /* frequency to sample chain */ chainParams.printFreq = 1000; /* frequency to print chain */ chainParams.swapFreq = 1; /* frequency of attempting swap of states */ chainParams.numSwaps = 1; /* number of swaps to try each time */ chainParams.isSS = NO; chainParams.startFromPriorSS = NO; chainParams.numStepsSS = 50; chainParams.burninSS = -1; chainParams.alphaSS = 0.4; chainParams.backupCheckSS = 0; chainParams.mcmcDiagn = YES; /* write MCMC diagnostics to file ? */ chainParams.diagnFreq = 5000; /* diagnostics frequency */ chainParams.minPartFreq = 0.10; /* min partition frequency for diagnostics */ chainParams.allChains = NO; /* calculate diagnostics for all chains ? */ chainParams.allComps = NO; /* do not calc diagn for all run comparisons */ chainParams.relativeBurnin = YES; /* use relative burnin? */ chainParams.burninFraction = 0.25; /* default burnin fraction */ chainParams.stopRule = NO; /* should stopping rule be used? */ chainParams.stopVal = 0.05; /* convergence diagnostic value to reach */ chainParams.numRuns = 2; /* number of runs */ chainParams.numChains = 4; /* number of chains */ chainParams.chainTemp = 0.1; /* chain temperature */ chainParams.redirect = NO; /* should printf be to stdout */ strcpy(chainParams.chainFileName, "temp"); /* chain file name for output */ chainParams.chainBurnIn = 0; /* chain burn in length */ chainParams.numStartPerts = 0; /* number of perturbations to starting tree */ strcpy(chainParams.startTree, "Current"); /* starting tree for chain (random/current) */ strcpy(chainParams.startParams, "Current"); /* starting params for chain (reset/current) */ chainParams.saveBrlens = YES; /* should branch lengths be saved */ chainParams.weightScheme[0] = 0.0; /* percent chars to decrease in weight */ chainParams.weightScheme[1] = 0.0; /* percent chars to increase in weight */ chainParams.weightScheme[2] = 1.0; /* weight increment */ chainParams.calcPbf = NO; /* should we calculate the pseudo-BF? */ chainParams.pbfInitBurnin = 100000; /* initial burnin for pseudo BF */ chainParams.pbfSampleFreq = 10; /* sample frequency for pseudo BF */ chainParams.pbfSampleTime = 2000; /* how many cycles to calcualate site prob. */ chainParams.pbfSampleBurnin = 2000; /* burnin period for each site for pseudo BF */ chainParams.userDefinedTemps = NO; /* should we use the users temperatures? */ for (i=0; i