static int utest_XPairId(ESL_ALPHABET *abc, char **as, ESL_DSQ **ax, int N) { double pid, pid2; int nid, nid2; int nres, nres2; int dL, L; int i,j; /* Self comparison gives identity = 1. */ dL = esl_abc_dsqlen(ax[0]); L = strlen(as[0]); if (dL != L) abort(); if (esl_dst_XPairId(abc, ax[0], ax[0], &pid, &nid, &nres) != eslOK) abort(); if (pid != 1.0 || nid != L || nres > dL) abort(); /* So does 0,1 comparison */ if (esl_dst_XPairId(abc, ax[0], ax[1], &pid, &nid, &nres) != eslOK) abort(); if (pid != 1.0 || nid != L || nres > L) abort(); /* 0,2 comparison gives 0.0, 0 */ if (esl_dst_XPairId(abc, ax[0], ax[2], &pid, &nid, &nres) != eslOK) abort(); if (pid != 0.0 || nid != 0 || nres > L) abort(); /* remaining comparisons shouldn't fail, and should be identical to text mode */ for (i = 3; i < N; i++) for (j = i; j < N; j++) { if (esl_dst_XPairId(abc, ax[i], ax[j], &pid, &nid, &nres) != eslOK) abort(); if (esl_dst_CPairId(as[i], as[j], &pid2, &nid2, &nres2) != eslOK) abort(); if (pid < 0. || pid > 1. || nid < 0 || nid > L || nres > L) abort(); if (pid != pid2 || nid != nid2 || nres != nres2) abort(); } /* API should accept NULL for return values */ if (esl_dst_XPairId(abc, ax[0], ax[0], NULL, NULL, NULL) != eslOK) abort(); return eslOK; }
/* Function: esl_msashuffle_XQRNA() * Synopsis: Gap-preserving column shuffle of a digital pairwise alignment. * Incept: SRE, Tue Jan 22 09:09:52 2008 [Market Street Cafe, Leesburg] * * Purpose: Shuffle a digital pairwise alignment <x>,<y> while * preserving the position of gaps, where both sequences are * in digital alphabet <abc>, using the random number * generator <r>. Return the shuffled alignment in <xs>, * <ys>. Caller provides allocated space for <xs> and <ys> * for at least the same length of <x>,<y>. * * Works by doing three separate * shuffles, of (1) columns with residues in both * <x> and <y>, (2) columns with residue in <x> and gap in <y>, * and (3) columns with gap in <x> and residue in <y>. * * <xs>,<x> and <ys>,<y> may be identical: that is, to shuffle * an alignment "in place", destroying the original * alignment, just call <esl_msashuffle_XQRNA(r, abc, x,y,x,y)>. * * Returns: <eslOK> on success, and the shuffled alignment is * returned in <xs>, <ys>. * * Throws: <eslEMEM> on allocation failure. */ int esl_msashuffle_XQRNA(ESL_RANDOMNESS *r, ESL_ALPHABET *abc, ESL_DSQ *x, ESL_DSQ *y, ESL_DSQ *xs, ESL_DSQ *ys) { int L; int *xycol = NULL; int *xcol = NULL; int *ycol = NULL; int nxy, nx, ny; int i; int pos, c; char xsym, ysym; int status; L = esl_abc_dsqlen(x); if (esl_abc_dsqlen(y) != L) ESL_XEXCEPTION(eslEINVAL, "sequences of different lengths in qrna shuffle"); if (xs != x) esl_abc_dsqcpy(x, L, xs); if (ys != y) esl_abc_dsqcpy(y, L, ys); /* First, construct three arrays containing lists of the column positions * of the three types of columns. (If a column contains gaps in both x and y, * we've already simply copied it to the shuffled sequence.) */ ESL_ALLOC(xycol, sizeof(int) * L); ESL_ALLOC(xcol, sizeof(int) * L); ESL_ALLOC(ycol, sizeof(int) * L); nxy = nx = ny = 0; for (i = 1; i <= L; i++) { if ( esl_abc_XIsGap(abc, x[i]) && esl_abc_XIsGap(abc, y[i])) { continue; } else if (! esl_abc_XIsGap(abc, x[i]) && ! esl_abc_XIsGap(abc, y[i])) { xycol[nxy] = i; nxy++; } else if ( esl_abc_XIsGap(abc, x[i])) { ycol[ny] = i; ny++; } else if ( esl_abc_XIsGap(abc, y[i])) { xcol[nx] = i; nx++; } } /* Second, shuffle the sequences indirectly, via shuffling these arrays. * Yow, careful with those indices, and with order of the statements... */ for (; nxy > 1; nxy--) { pos = esl_rnd_Roll(r, nxy); xsym = xs[xycol[pos]]; ysym = ys[xycol[pos]]; c = xycol[pos]; xs[xycol[pos]] = xs[xycol[nxy-1]]; ys[xycol[pos]] = ys[xycol[nxy-1]]; xycol[pos] = xycol[nxy-1]; xs[xycol[nxy-1]] = xsym; ys[xycol[nxy-1]] = ysym; xycol[pos] = xycol[nxy-1]; } for (; nx > 1; nx--) { pos = esl_rnd_Roll(r, nx); xsym = xs[xcol[pos]]; ysym = ys[xcol[pos]]; c = xcol[pos]; xs[xcol[pos]] = xs[xcol[nx-1]]; ys[xcol[pos]] = ys[xcol[nx-1]]; xcol[pos] = xcol[nx-1]; xs[xcol[nx-1]] = xsym; ys[xcol[nx-1]] = ysym; xcol[nx-1] = c; } for (; ny > 1; ny--) { pos = esl_rnd_Roll(r, ny); xsym = xs[ycol[pos]]; ysym = ys[ycol[pos]]; c = ycol[pos]; xs[ycol[pos]] = xs[ycol[ny-1]]; ys[ycol[pos]] = ys[ycol[ny-1]]; ycol[pos] = ycol[ny-1]; xs[ycol[ny-1]] = xsym; ys[ycol[ny-1]] = ysym; ycol[ny-1] = c; } free(xycol); free(xcol); free(ycol); return eslOK; ERROR: if (xycol != NULL) free(xycol); if (xcol != NULL) free(xcol); if (ycol != NULL) free(ycol); return status; }