hmmer-3.3/easel/esl_sq.c
/* Function:  esl_sq_ReverseComplement()
 * Synopsis:  Reverse complement a sequence.
 * Incept:    SRE, Thu May 15 20:52:13 2008 [Casa de Gatos]
 *
 * Purpose:   Reverse complement the sequence <sq>, in place.
 *            
 *            If <sq> is in text mode, upper/lower case is preserved,
 *            and the DNA alphabet is used (<Aa> is complemented to
 *            <Tt>, not <Uu>). If a non-nucleic character is seen, it
 *            is reverse complemented to an N, and the return status
 *            is <eslEINVAL> (but the whole sequence is still reverse
 *            complemented).
 *            
 *            If <sq> is in digital mode, the appropriate alphabet
 *            (DNA vs. RNA) is used. If the alphabet has no defined
 *            complement (such as amino acids), an <eslEINCOMPAT>
 *            error is thrown, and the sequence isn't changed at all.
 *            
 *            Gap, nonresidues, and missing data characters, if any,
 *            are preserved (in text mode, <._-> are treated as gaps,
 *            <*> are nonresidues, and <~> as missing
 *            data). Degenerate nucleic acid IUPAC characters are
 *            complemented appropriately.
 *
 *            The <start/end> coords in <sq> are swapped. (Note that
 *            in the unusual case of sequences of length 1,
 *            <start=end> and we can't unambiguously tell if a seq is
 *            in the reverse complement direction or not; this is a
 *            minor flaw in Easel's current coordinate handling.)
 *
 * Returns:   <eslOK> on success.
 *            
 *            Returns <eslEINVAL> if the <sq> is in text mode, and we
 *            see a character that doesn't belong to the IUPAC DNA/RNA
 *            alphabet; in this case, the <sq> is still reverse
 *            complemented using the DNA alphabet, with <N> for any
 *            non-nucleic residues.
 *
 * Throws:    <eslEINCOMPAT> if the <sq> is in digital mode, but the
 *            digital alphabet has no defined complement.
 */
esl_sq_ReverseComplement()
Synopsis:  Reverse complement a sequence.

Reverse complement the sequence , in place.

If  is in text mode, upper/lower case is preserved,
and the DNA alphabet is used ( is complemented to
, not ). If a non-nucleic character is seen, it
is reverse complemented to an N, and the return status
is  (but the whole sequence is still reverse
complemented).

If  is in digital mode, the appropriate alphabet
(DNA vs. RNA) is used. If the alphabet has no defined
complement (such as amino acids), an 
error is thrown, and the sequence isn't changed at all.

Gap, nonresidues, and missing data characters, if any,
are preserved (in text mode, <._-> are treated as gaps,
<*> are nonresidues, and <~> as missing
data). Degenerate nucleic acid IUPAC characters are
complemented appropriately.

The  coords in  are swapped. (Note that
in the unusual case of sequences of length 1,
 and we can't unambiguously tell if a seq is
in the reverse complement direction or not; this is a
minor flaw in Easel's current coordinate handling.)

 on success.

Returns  if the  is in text mode, and we
see a character that doesn't belong to the IUPAC DNA/RNA
alphabet; in this case, the  is still reverse
complemented using the DNA alphabet, with  for any
non-nucleic residues.

 if the  is in digital mode, but the
digital alphabet has no defined complement.
esl_sq_ReverseComplement () Synopsis : Reverse complement a sequence . Reverse complement the sequence in place . If is in text mode upper / lower case is preserved and the DNA alphabet is used ( is complemented to not ) . If a non - nucleic character is seen it is reverse complemented to an N and the return status is ( but the whole sequence is still reverse complemented ) . If is in digital mode the appropriate alphabet ( DNA vs . RNA ) is used . If the alphabet has no defined complement ( such as amino acids ) an error is thrown and the sequence isn ' t changed at all . Gap nonresidues and missing data characters if any are preserved ( in text mode < . _ - > are treated as gaps < * > are nonresidues and <~ > as missing data ) . Degenerate nucleic acid IUPAC characters are complemented appropriately . The coords in are swapped . ( Note that in the unusual case of sequences of length 1 and we can ' t unambiguously tell if a seq is in the reverse complement direction or not ; this is a minor flaw in Easel ' s current coordinate handling . ) on success . Returns if the is in text mode and we see a character that doesn ' t belong to the IUPAC DNA / RNA alphabet ; in this case the is still reverse complemented using the DNA alphabet with for any non - nucleic residues . if the is in digital mode but the digital alphabet has no defined complement .
int
esl_sq_ReverseComplement(ESL_SQ *sq)
{
  int64_t i;
  int     x;               
  int     status = eslOK;
  if (sq->seq != NULL)
    {
      for (i = 0; i < sq->n; i++)
	switch (sq->seq[i]) {
	case 'A': sq->seq[i] = 'T'; break;
	case 'C': sq->seq[i] = 'G'; break;
	case 'G': sq->seq[i] = 'C'; break;
	case 'T': sq->seq[i] = 'A'; break;
	case 'U': sq->seq[i] = 'A'; break;
	case 'R': sq->seq[i] = 'Y'; break;
	case 'Y': sq->seq[i] = 'R'; break;
	case 'M': sq->seq[i] = 'K'; break;
	case 'K': sq->seq[i] = 'M'; break;
	case 'S': sq->seq[i] = 'S'; break;
	case 'W': sq->seq[i] = 'W'; break;
	case 'H': sq->seq[i] = 'D'; break;
	case 'B': sq->seq[i] = 'V'; break;
	case 'V': sq->seq[i] = 'B'; break;
	case 'D': sq->seq[i] = 'H'; break;
	case 'N': sq->seq[i] = 'N'; break;
	case 'X': sq->seq[i] = 'X'; break;
	case 'a': sq->seq[i] = 't'; break;
	case 'c': sq->seq[i] = 'g'; break;
	case 'g': sq->seq[i] = 'c'; break;
	case 't': sq->seq[i] = 'a'; break;
	case 'u': sq->seq[i] = 'a'; break;
	case 'r': sq->seq[i] = 'y'; break;
	case 'y': sq->seq[i] = 'r'; break;
	case 'm': sq->seq[i] = 'k'; break;
	case 'k': sq->seq[i] = 'm'; break;
	case 's': sq->seq[i] = 's'; break;
	case 'w': sq->seq[i] = 'w'; break;
	case 'h': sq->seq[i] = 'd'; break;
	case 'b': sq->seq[i] = 'v'; break;
	case 'v': sq->seq[i] = 'b'; break;
	case 'd': sq->seq[i] = 'h'; break;
	case 'n': sq->seq[i] = 'n'; break;
	case 'x': sq->seq[i] = 'x'; break;
	case '.': sq->seq[i] = '.'; break;
	case '_': sq->seq[i] = '_'; break;
	case '-': sq->seq[i] = '-'; break;
	case '~': sq->seq[i] = '~'; break;
	case '*': sq->seq[i] = '*'; break;
	default:  sq->seq[i] = 'N'; status = eslEINVAL; break;
	}
      for (i = 0; i < sq->n / 2; i++)
	ESL_SWAP(sq->seq[i], sq->seq[sq->n-i-1], char);
    }
  else
    {
      if ((status = esl_abc_revcomp(sq->abc, sq->dsq, sq->n)) != eslOK) goto ERROR;
    }
  ESL_SWAP(sq->start, sq->end, int64_t);
  if (sq->ss != NULL) { free(sq->ss); sq->ss = NULL; }
  if (sq->nxr > 0) {
    for (x = 0; x < sq->nxr; x++) 
      if (sq->xr[x] != NULL) { free(sq->xr_tag[x]); free(sq->xr[x]); sq->xr_tag[x] = NULL; sq->xr[x] = NULL; }  
    free(sq->xr_tag); sq->xr_tag = NULL;
    free(sq->xr);     sq->xr     = NULL;
  }   
  return status;
 ERROR:
  return status;
}
int esl_sq_ReverseComplement ( ESL_SQ * sq ) { int64_t i ; int x ; int status = eslOK ; if ( sq -> seq != NULL ) { for ( i = 0 ; i < sq -> n ; i ++ ) switch ( sq -> seq [ i ] ) { case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; case ' ' : sq -> seq [ i ] = ' ' ; break ; default : sq -> seq [ i ] = ' ' ; status = eslEINVAL ; break ; } for ( i = 0 ; i < sq -> n / 2 ; i ++ ) ESL_SWAP ( sq -> seq [ i ] , sq -> seq [ sq -> n - i - 1 ] , char ) ; } else { if ( ( status = esl_abc_revcomp ( sq -> abc , sq -> dsq , sq -> n ) ) != eslOK ) goto ERROR ; } ESL_SWAP ( sq -> start , sq -> end , int64_t ) ; if ( sq -> ss != NULL ) { free ( sq -> ss ) ; sq -> ss = NULL ; } if ( sq -> nxr > 0 ) { for ( x = 0 ; x < sq -> nxr ; x ++ ) if ( sq -> xr [ x ] != NULL ) { free ( sq -> xr_tag [ x ] ) ; free ( sq -> xr [ x ] ) ; sq -> xr_tag [ x ] = NULL ; sq -> xr [ x ] = NULL ; } free ( sq -> xr_tag ) ; sq -> xr_tag = NULL ; free ( sq -> xr ) ; sq -> xr = NULL ; } return status ; ERROR : return status ; }
Function:  esl_sq_ReverseComplement()
 Synopsis:  Reverse complement a sequence.
Function : esl_sq_ReverseComplement () Synopsis : Reverse complement a sequence .
/* index for optional extra residue markups */ /* first, complement the sequence */ /* then, reverse it in place */ /* revcomp invalidates any secondary structure annotation */ /* revcomp invalidates any extra residue markup */