int main(void) { struct p7trace_s *tr; /* traceback of an alignment */ int master_tid; /* PVM TID of our master */ char *hmmfile; /* file to read HMM(s) from */ HMMFILE *hmmfp; /* opened hmmfile for reading */ struct plan7_s *hmm; char *seq; char *dsq; int len; int nhmm; /* number of HMM to work on */ float sc; int my_idx = -1; /* my index, 0..nslaves-1 */ float globT; /* T parameter: keep only hits > globT bits */ double globE; /* E parameter: keep hits < globE E-value */ double pvalue; /* Z*pvalue = Evalue */ int Z; /* nseq to base E value calculation on */ int send_trace; /* TRUE if score is significant */ int do_xnu; /* TRUE to do XNU filter on seq */ int do_forward; /* TRUE to use Forward() scores not Viterbi */ int do_null2; /* TRUE to correct scores w/ ad hoc null2 */ int alphatype; /* alphabet type, hmmAMINO or hmmNUCLEIC */ int code; /* return code after initialization */ /* Register leave_pvm() cleanup function so any exit() call * first calls pvm_exit(). */ if (atexit(leave_pvm) != 0) { pvm_exit(); Die("slave couldn't register leave_pvm()"); } /***************************************************************** * initialization. * Master broadcasts to us: * 1) len of HMM file name (int) * 2) name of HMM file (string) * 3) length of sequence string (int) * 4) sequence (string) * 5) globT threshold * 6) globE threshold * 7) Z * 8) do_xnu flag * 9) do_forward flag * 10) do_null2 flag * 11) alphabet type * We receive the broadcast and open the files. ******************************************************************/ master_tid = pvm_parent(); /* who's our master? */ pvm_recv(master_tid, HMMPVM_INIT); pvm_upkint(&len, 1, 1); hmmfile = MallocOrDie(sizeof(char *) * (len+1)); pvm_upkstr(hmmfile); pvm_upkint(&len, 1, 1); seq = MallocOrDie(sizeof(char *) * (len+1)); pvm_upkstr(seq); pvm_upkfloat(&globT, 1, 1); pvm_upkdouble(&globE, 1, 1); pvm_upkint(&Z, 1, 1); pvm_upkint(&do_xnu, 1, 1); pvm_upkint(&do_forward, 1, 1); pvm_upkint(&do_null2, 1, 1); pvm_upkint(&alphatype, 1, 1); SetAlphabet(alphatype); /* Open HMM file (maybe in HMMERDB) */ code = HMMPVM_OK; if ((hmmfp = HMMFileOpen(hmmfile, "HMMERDB")) == NULL) code = HMMPVM_NO_HMMFILE; else if (hmmfp->gsi == NULL) code = HMMPVM_NO_INDEX; /* report our status. */ pvm_initsend(PvmDataDefault); pvm_pkint(&code, 1, 1); pvm_send(master_tid, HMMPVM_RESULTS); dsq = DigitizeSequence(seq, len); if (do_xnu) XNU(dsq, len); /***************************************************************** * Main loop. * Receive an integer 0..nhmm-1 for which HMM to search against. * If we receive a -1, we shut down. *****************************************************************/ for (;;) { pvm_recv(master_tid, HMMPVM_WORK); pvm_upkint(&nhmm, 1, 1); if (my_idx < 0) my_idx = nhmm; /* first time thru, remember what index we are. */ if (nhmm == -1) break; /* shutdown signal */ /* move to our assigned HMM in the HMM file, and read it */ HMMFilePositionByIndex(hmmfp, nhmm); if (! HMMFileRead(hmmfp, &hmm)) Die("unexpected end of HMM file"); if (hmm == NULL) Die("unexpected failure to parse HMM file"); P7Logoddsify(hmm, TRUE); /* Score sequence, do alignment (Viterbi), recover trace */ if (P7ViterbiSize(len, hmm->M) <= RAMLIMIT) { SQD_DPRINTF1(("P7Viterbi(): Estimated size %d Mb\n", P7ViterbiSize(len, hmm->M))); sc = P7Viterbi(dsq, len, hmm, &tr); } else { SQD_DPRINTF1(("P7SmallViterbi() called; %d Mb > %d\n", P7ViterbiSize(len, hmm->M), RAMLIMIT)); sc = P7SmallViterbi(dsq, len, hmm, &tr); } if (do_forward) sc = P7Forward(dsq, len, hmm, NULL); if (do_null2) sc -= TraceScoreCorrection(hmm, tr, dsq); pvalue = PValue(hmm, sc); send_trace = (sc > globT && pvalue * (float) Z < globE) ? 1 : 0; /* return output */ pvm_initsend(PvmDataDefault); pvm_pkint(&my_idx, 1, 1); /* tell master who we are */ pvm_pkstr(hmm->name); /* double check that we did the right thing */ pvm_pkfloat(&sc, 1, 1); pvm_pkdouble(&pvalue, 1, 1); pvm_pkint(&send_trace, 1, 1); /* flag for whether a trace structure is coming */ if (send_trace) PVMPackTrace(tr); pvm_send(master_tid, HMMPVM_RESULTS); /* cleanup */ FreePlan7(hmm); P7FreeTrace(tr); } /*********************************************** * Cleanup, return. ***********************************************/ HMMFileClose(hmmfp); free(seq); free(dsq); free(hmmfile); return 0; }
/* Function: CP9_HMMFileOpen() * * Purpose: Open an HMM file for reading. The file may be either * an index for a library of HMMs, or an HMM. * * Args: hmmfile - name of file * env - NULL, or environment variable for HMM database. * * Return: Valid HMMFILE *, or NULL on failure. */ CP9HMMFILE * CP9_HMMFileOpen(char *hmmfile, char *env) { CP9HMMFILE *hmmfp; unsigned int magic; char buf[512]; char *ssifile; char *dir; /* dir name in which HMM file was found */ int status; hmmfp = (CP9HMMFILE *) MallocOrDie (sizeof(CP9HMMFILE)); hmmfp->f = NULL; hmmfp->parser = NULL; hmmfp->is_binary = FALSE; hmmfp->byteswap = FALSE; hmmfp->is_seekable= TRUE; /* always; right now, an HMM must always be in a file. */ /* Open the file. Look in current directory. * If that doesn't work, check environment var for * a second possible directory (usually the location * of a system-wide HMM library). * Using dir name if necessary, construct correct SSI file name. */ hmmfp->f = NULL; hmmfp->ssi = NULL; if ((hmmfp->f = fopen(hmmfile, "r")) != NULL) { ssifile = MallocOrDie(sizeof(char) * (strlen(hmmfile) + 5)); sprintf(ssifile, "%s.ssi", hmmfile); if ((hmmfp->mode = SSIRecommendMode(hmmfile)) == -1) Die("SSIRecommendMode() failed"); } else if ((hmmfp->f = EnvFileOpen(hmmfile, env, &dir)) != NULL) { char *full; full = FileConcat(dir, hmmfile); ssifile = MallocOrDie(sizeof(char) * (strlen(full) + strlen(hmmfile) + 5)); sprintf(ssifile, "%s.ssi", full); if ((hmmfp->mode = SSIRecommendMode(full)) == -1) Die("SSIRecommendMode() failed"); free(full); free(dir); } else return NULL; /* Open the SSI index file. If it doesn't exist, or it's corrupt, or * some error happens, hmmfp->ssi stays NULL. */ SQD_DPRINTF1(("Opening ssifile %s...\n", ssifile)); SSIOpen(ssifile, &(hmmfp->ssi)); free(ssifile); /* Initialize the disk offset stuff. */ status = SSIGetFilePosition(hmmfp->f, hmmfp->mode, &(hmmfp->offset)); if (status != 0) Die("SSIGetFilePosition() failed"); /* Check for binary or byteswapped binary format * by peeking at first 4 bytes. */ if (! fread((char *) &magic, sizeof(unsigned int), 1, hmmfp->f)) { CP9_HMMFileClose(hmmfp); return NULL; } rewind(hmmfp->f); if (magic == vCP9magic) { hmmfp->parser = CP9_read_bin_hmm; hmmfp->is_binary = TRUE; return hmmfp; } else if (magic == vCP9swap) { SQD_DPRINTF1(("Opened an Infernal CP9 HMM binary file [byteswapped]\n")); hmmfp->parser = CP9_read_bin_hmm; hmmfp->is_binary = TRUE; hmmfp->byteswap = TRUE; return hmmfp; } /* else we fall thru; it may be an ASCII file. */ /* If magic looks binary but we don't recognize it, choke and die. */ if (magic & 0x80000000) { Warn("\ %s appears to be a binary but not a CM plan 9 format that we recognize\n\ It may be from HMMER,\n\ or may be a different kind of binary altogether.\n", hmmfile); CP9_HMMFileClose(hmmfp); return NULL; }
/* Function: leave_pvm() * * Purpose: Cleanup function, to deal with crashes. We register * this function using atexit() so it gets called before * the slave dies. */ static void leave_pvm(void) { SQD_DPRINTF1(("slave leaving PVM.\n")); pvm_exit(); }
/* Function: main_loop_pvm() * Date: SRE, Wed Aug 19 13:59:54 1998 [St. Louis] * * Purpose: Given an HMM and parameters for synthesizing random * sequences; return a histogram of scores. * (PVM version) * * Args: hmm - an HMM to calibrate. * seed - random number seed * nsample - number of seqs to synthesize * lumpsize- # of seqs per slave exchange; controls granularity * lenmean - mean length of random sequence * lensd - std dev of random seq length * fixedlen- if nonzero, override lenmean, always this len * hist - RETURN: the score histogram * ret_max - RETURN: highest score seen in simulation * extrawatch - RETURN: total CPU time spend in slaves. * ret_nslaves- RETURN: number of PVM slaves run. * * Returns: (void) * hist is alloc'ed here, and must be free'd by caller. */ static void main_loop_pvm(struct plan7_s *hmm, int seed, int nsample, int lumpsize, float lenmean, float lensd, int fixedlen, struct histogram_s **ret_hist, float *ret_max, Stopwatch_t *extrawatch, int *ret_nslaves) { struct histogram_s *hist; int master_tid; int *slave_tid; int nslaves; int nsent; /* # of seqs we've asked for so far */ int ndone; /* # of seqs we've got results for so far */ int packet; /* # of seqs to have a slave do */ float max; int slaveidx; /* id of a slave */ float *sc; /* scores returned by a slave */ Stopwatch_t slavewatch; int i; StopwatchZero(extrawatch); hist = AllocHistogram(-200, 200, 100); max = -FLT_MAX; /* Initialize PVM */ if ((master_tid = pvm_mytid()) < 0) Die("pvmd not responding -- do you have PVM running?"); #if DEBUGLEVEL >= 1 pvm_catchout(stderr); /* catch output for debugging */ #endif PVMSpawnSlaves("hmmcalibrate-pvm", &slave_tid, &nslaves); /* Initialize the slaves */ pvm_initsend(PvmDataDefault); pvm_pkfloat(&lenmean, 1, 1); pvm_pkfloat(&lensd, 1, 1); pvm_pkint( &fixedlen, 1, 1); pvm_pkint( &Alphabet_type, 1, 1); pvm_pkint( &seed, 1, 1); if (! PVMPackHMM(hmm)) Die("Failed to pack the HMM"); pvm_mcast(slave_tid, nslaves, HMMPVM_INIT); SQD_DPRINTF1(("Initialized %d slaves\n", nslaves)); /* Confirm slaves' OK status. */ PVMConfirmSlaves(slave_tid, nslaves); SQD_DPRINTF1(("Slaves confirm that they're ok...\n")); /* Load the slaves */ nsent = ndone = 0; for (slaveidx = 0; slaveidx < nslaves; slaveidx++) { packet = (nsample - nsent > lumpsize ? lumpsize : nsample - nsent); pvm_initsend(PvmDataDefault); pvm_pkint(&packet, 1, 1); pvm_pkint(&slaveidx, 1, 1); pvm_send(slave_tid[slaveidx], HMMPVM_WORK); nsent += packet; } SQD_DPRINTF1(("Loaded %d slaves\n", nslaves)); /* Receive/send loop */ sc = MallocOrDie(sizeof(float) * lumpsize); while (nsent < nsample) { /* integrity check of slaves */ PVMCheckSlaves(slave_tid, nslaves); /* receive results */ SQD_DPRINTF2(("Waiting for results...\n")); pvm_recv(-1, HMMPVM_RESULTS); pvm_upkint(&slaveidx, 1, 1); pvm_upkint(&packet, 1, 1); pvm_upkfloat(sc, packet, 1); SQD_DPRINTF2(("Got results.\n")); ndone += packet; /* store results */ for (i = 0; i < packet; i++) { AddToHistogram(hist, sc[i]); if (sc[i] > max) max = sc[i]; } /* send new work */ packet = (nsample - nsent > lumpsize ? lumpsize : nsample - nsent); pvm_initsend(PvmDataDefault); pvm_pkint(&packet, 1, 1); pvm_pkint(&slaveidx, 1, 1); pvm_send(slave_tid[slaveidx], HMMPVM_WORK); SQD_DPRINTF2(("Told slave %d to do %d more seqs.\n", slaveidx, packet)); nsent += packet; } /* Wait for the last output to come in. */ while (ndone < nsample) { /* integrity check of slaves */ PVMCheckSlaves(slave_tid, nslaves); /* receive results */ SQD_DPRINTF1(("Waiting for final results...\n")); pvm_recv(-1, HMMPVM_RESULTS); pvm_upkint(&slaveidx, 1, 1); pvm_upkint(&packet, 1, 1); pvm_upkfloat(sc, packet, 1); SQD_DPRINTF2(("Got some final results.\n")); ndone += packet; /* store results */ for (i = 0; i < packet; i++) { AddToHistogram(hist, sc[i]); if (sc[i] > max) max = sc[i]; } } /* Shut down the slaves: send -1,-1,-1. */ pvm_initsend(PvmDataDefault); packet = -1; pvm_pkint(&packet, 1, 1); pvm_pkint(&packet, 1, 1); pvm_pkint(&packet, 1, 1); pvm_mcast(slave_tid, nslaves, HMMPVM_WORK); /* Collect stopwatch results; quit the VM; return. */ for (i = 0; i < nslaves; i++) { pvm_recv(-1, HMMPVM_RESULTS); pvm_upkint(&slaveidx, 1, 1); StopwatchPVMUnpack(&slavewatch); SQD_DPRINTF1(("Slave %d finished; says it used %.2f cpu, %.2f sys\n", slaveidx, slavewatch.user, slavewatch.sys)); StopwatchInclude(extrawatch, &slavewatch); } free(slave_tid); free(sc); pvm_exit(); *ret_hist = hist; *ret_max = max; *ret_nslaves = nslaves; return; }