/* dnaDust - A little web utility that reformats
* DNA sequence in some simple but useful ways. */
#include "common.h"
#include "htmshell.h"
#include "cheapcgi.h"
#include "dnautil.h"
char *skipAlNum(char *s)
/* Return first non-alphanumeric char */
{
for (;;)
{
if (!isalnum(*s)) return s;
s += 1;
}
}
char *skipToAlNum(char *s)
/* Return first alphanumeric char */
{
char c;
for (;;)
{
c = *s;
if (c == 0 || isalnum(c))
return s;
++s;
}
}
boolean allNt(char *s,int size)
/* Return TRUE if all chars are DNA type */
{
while (--size >= 0)
if (ntChars[(int)(*s++)] == 0) return FALSE;
return TRUE;
}
void dustDna(char *in,char *out)
/* Remove non-dna looking words from input as it
* is copied to output. */
{
char *wordEnd;
int wordLen;
while (*in != 0)
{
in = skipToAlNum(in);
wordEnd = skipAlNum(in);
wordLen = wordEnd - in;
if (allNt(in, wordLen))
{
memcpy(out, in, wordLen);
out += wordLen;
}
in = wordEnd;
}
*out++ = 0;
}
int noneOrNumber(char *s)
/* Return binary representation of ascii number, or 0 if
* it is not a number. */
{
return atoi(s);
}
void formatOutput(char *output, int spacer, int liner,
boolean showNumbers, char *caseChoice)
/* Write out output with line breaks and optional numbering. */
{
int countSpace = 0;
int countLine = 0;
int baseCount = 0;
char c;
if (differentWord(caseChoice, "upper") == 0)
touppers(output);
else if (differentWord(caseChoice, "lower") == 0)
tolowers(output);
printf("\n");
for (;;)
{
c = *output++;
if (c == 0)
break;
++baseCount;
putc(c, stdout);
if (spacer != 0 && ++countSpace == spacer)
{
putc(' ', stdout);
countSpace = 0;
}
if (liner != 0 && ++countLine == liner)
{
if (showNumbers)
printf(" %d", baseCount);
printf("
\n");
countLine = 0;
}
}
if (countLine != 0)
{
if (showNumbers)
printf(" %d", baseCount);
printf("
\n");
}
printf("\n");
}
void eraseLowerCase(char *s)
/* Get rid of all but upper case characters in string. */
{
char *in, *out;
char c;
in = out = s;
for (;;)
{
c = *in++;
if (c == 0)
break;
if (isupper(c))
*out++ = c;
}
*out++ = 0;
}
char *customTranslate(char *dna, boolean searchAug)
/* Translate DNA into protein, possibly searching for
* start codon before beginning translation. */
{
int dnaLength;
int protLength;
char *protein;
char aa;
int i;
tolowers(dna);
toRna(dna);
if (searchAug)
{
dna = strstr(dna, "aug");
if (dna == NULL)
errAbort("No start codon in input.");
}
dnaLength = strlen(dna);
protLength = dnaLength/3;
protein = (char *)needMem(protLength+1);
for (i=0; iG and C<->T */
{
DNA b;
while ((b = *dna) != 0)
*dna++ = ntCompTable[(int)b];
}
void doMiddle()
/* Write out middle part of web page. */
{
char *input, *dustedDna;
long len;
char *linesEvery, *spacesEvery;
boolean showNumbers;
char *caseChoice;
boolean asProtein;
boolean searchAug;
boolean ignoreLower;
char *strand;
input = cgiString("TextArea");
linesEvery = cgiString("linesEvery");
spacesEvery = cgiString("spacesEvery");
showNumbers = cgiBoolean("showNumbers");
caseChoice = cgiString("caseChoice");
asProtein = cgiBoolean("asProtein");
searchAug = cgiBoolean("searchAug");
ignoreLower = cgiBoolean("ignoreLower");
strand = cgiString("strand");
len = strlen(input);
if ((dustedDna = malloc(len+1)) == NULL)
errAbort("Out of memory");
dustDna(input, dustedDna);
if (ignoreLower)
{
eraseLowerCase(dustedDna);
if (strlen(dustedDna) == 0)
{
errAbort("Nothing left after removing introns. Perhaps you should go back and uncheck the 'lower case is intron' button");
}
}
if (!differentWord("reverse complement", strand))
reverseComplement(dustedDna, strlen(dustedDna));
else if (!differentWord("reverse", strand))
reverseBytes(dustedDna, strlen(dustedDna));
else if (!differentWord("complement", strand))
complementDna(dustedDna);
if (asProtein)
{
char *prot = customTranslate(dustedDna, searchAug);
formatOutput(prot,
noneOrNumber(spacesEvery), noneOrNumber(linesEvery),
showNumbers, caseChoice);
}
else
{
formatOutput(dustedDna,
noneOrNumber(spacesEvery), noneOrNumber(linesEvery),
showNumbers, caseChoice);
}
}
int main(int argc, char *argv[])
/* Main entry point. Wrap html shell around doMiddle. */
{
dnaUtilOpen();
htmShell("DNA Duster Output", doMiddle, "POST");
return 0;
}