1 /************************************************************
2 * HMMER - Biological sequence analysis with profile HMMs
3 * Copyright (C) 1992-1999 Washington University School of Medicine
6 * This source code is distributed under the terms of the
7 * GNU General Public License. See the files COPYING and LICENSE
9 ************************************************************/
14 * SRE, Wed Sep 23 09:30:53 1998
16 * PVM slave for hmmsearch.
17 * RCS $Id: hmmsearch-pvm.c,v 1.1.1.1 2005/03/22 08:34:12 cmzmasek Exp $
26 #include "structs.h" /* data structures, macros, #define's */
27 #include "config.h" /* compile-time configuration constants */
28 #include "funcs.h" /* function declarations */
29 #include "globals.h" /* alphabet global variables */
30 #include "squid.h" /* general sequence analysis library */
32 static void leave_pvm(void);
37 struct plan7_s *hmm; /* HMM to search with */
38 struct p7trace_s *tr; /* trace structure for a Viterbi alignment */
39 int master_tid; /* PVM TID of our master */
40 int alphatype; /* alphabet type */
41 int code; /* status code for whether we're ok */
42 int my_idx; /* my slave index: 0..nslaves-1, master assigns */
43 int L; /* length of sequence */
44 char *dsq; /* digitized sequence 1..L */
45 float sc; /* log odds score for seq + HMM */
46 double pvalue; /* P-value of sc */
47 double evalue; /* bounded E-value of sc (we don't know nseq yet) */
48 int do_forward; /* TRUE to score using Forward() */
49 int do_null2; /* TRUE to use null2 ad hoc correction */
50 float globT; /* T parameter: keep only hits > globT bits */
51 double globE; /* E parameter: keep hits < globE E-value */
52 int Z; /* nseq to base E value calculation on */
53 int nseq; /* actual nseq so far (master keeps updating this) */
54 int send_trace; /* TRUE if sc looks significant and we return tr */
56 /* Register leave_pvm() cleanup function so any exit() call
57 * first calls pvm_exit().
59 if (atexit(leave_pvm) != 0) { pvm_exit(); Die("slave couldn't register leave_pvm()"); }
61 /*****************************************************************
63 * Master broadcasts the problem to us:
64 * globT, globE, Z, do_forward, do_null2, alphabet type, HMM,
65 ******************************************************************/
67 master_tid = pvm_parent(); /* who's our master? */
70 /* wait for a HMMPVM_INIT message, and unpack it;
71 * get options, set alphabet type, get HMM.
73 pvm_recv(master_tid, HMMPVM_INIT);
74 pvm_upkfloat(&globT, 1, 1);
75 pvm_upkdouble(&globE, 1, 1);
77 pvm_upkint(&do_forward, 1, 1);
78 pvm_upkint(&do_null2, 1, 1);
79 pvm_upkint(&alphatype, 1, 1);
80 SetAlphabet(alphatype);
83 P7Logoddsify(hmm, TRUE);
85 /* tell the master we're OK and ready to go (or not)
88 if (hmm == NULL) code = HMMPVM_BAD_INIT;
89 pvm_initsend(PvmDataDefault);
90 pvm_pkint(&code, 1, 1);
91 PVMPackString(RELEASE);
92 pvm_send(master_tid, HMMPVM_RESULTS);
94 /*****************************************************************
96 * Receive a digitized sequence to search against.
97 *****************************************************************/
101 SQD_DPRINTF1(("Slave about to do a blocking receive, waiting for input.\n"));
102 pvm_recv(master_tid, HMMPVM_WORK);
103 pvm_upkint(&nseq, 1, 1);
104 if (nseq == -1) break; /* shutdown signal */
105 if (my_idx == -1) my_idx = nseq;
106 pvm_upkint(&L, 1, 1);
107 SQD_DPRINTF1(("Slave received nseq=%d L=%d my_idx=%d\n", nseq, L, my_idx));
108 dsq = MallocOrDie(sizeof(char) * (L + 2));
109 pvm_upkbyte(dsq, L+2, 1);
110 SQD_DPRINTF1(("Slave unpacked a seq of %d bytes; beginning processing\n", L+2));
112 /* Score sequence, do alignment (Viterbi), recover trace
114 if (P7ViterbiSize(L, hmm->M) <= RAMLIMIT)
116 SQD_DPRINTF1(("Slave doing Viterbi after estimating %d MB\n", (P7ViterbiSize(L, hmm->M))));
117 sc = P7Viterbi(dsq, L, hmm, &tr);
121 SQD_DPRINTF1(("Slave going small after estimating %d MB\n", (P7ViterbiSize(L, hmm->M))));
122 sc = P7SmallViterbi(dsq, L, hmm, &tr);
125 if (do_forward) sc = P7Forward(dsq, L, hmm, NULL);
126 if (do_null2) sc -= TraceScoreCorrection(hmm, tr, dsq);
128 pvalue = PValue(hmm, sc);
129 evalue = Z ? (double) Z * pvalue : (double) nseq * pvalue;
130 send_trace = (sc >= globT && evalue <= globE) ? 1 : 0;
134 SQD_DPRINTF1(("Slave has a result (sc = %.1f); sending back to master\n", sc));
135 pvm_initsend(PvmDataDefault);
136 pvm_pkint (&my_idx, 1, 1);
137 pvm_pkfloat (&sc, 1, 1);
138 pvm_pkdouble(&pvalue, 1, 1);
139 pvm_pkint(&send_trace, 1, 1); /* flag for whether a trace structure is coming */
140 if (send_trace) PVMPackTrace(tr);
141 pvm_send(master_tid, HMMPVM_RESULTS);
149 /***********************************************
151 ***********************************************/
153 SQD_DPRINTF1(("Slave is done; performing a normal exit.\n"));
155 exit(0); /* pvm_exit() gets called by atexit() registration. */
158 /* Function: leave_pvm()
160 * Purpose: Cleanup function, to deal with crashes. We register
161 * this function using atexit() so it gets called before
166 SQD_DPRINTF1(("slave leaving PVM.\n"));
171 #else /* if HMMER_PVM not defined: include a dummy */
176 printf("hmmsearch-pvm is disabled. PVM support was not compiled into HMMER.\n");