Mac binaries
[jabaws.git] / website / archive / binaries / mac / src / clustalw / src / general / Stats.cpp
diff --git a/website/archive/binaries/mac/src/clustalw/src/general/Stats.cpp b/website/archive/binaries/mac/src/clustalw/src/general/Stats.cpp
new file mode 100644 (file)
index 0000000..0dfb6de
--- /dev/null
@@ -0,0 +1,375 @@
+/**
+ *
+ * Copyright (c) 2007 Des Higgins, Julie Thompson and Toby Gibson.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <cstdlib>
+#include <iostream>
+#include <algorithm>
+#include <string>
+#include <stdio.h>
+#include "../alignment/Alignment.h"
+#ifdef HAVE_MHASH_H
+#include "mhash.h"
+#endif
+
+#include "Stats.h"
+
+
+using namespace std;
+
+namespace clustalw
+{
+
+
+Stats::Stats()
+{
+    enabled = false;
+}
+
+
+Stats::~Stats()
+{
+}
+
+
+
+
+/* adopted from Sean Eddy'ssquid:aligneval.c */
+/* Function: PairwiseIdentity()
+ * 
+ * Purpose:  Calculate the pairwise fractional identity between
+ *           two aligned sequences s1 and s2. This is simply
+ *           (idents / MIN(len1, len2)).
+ *
+ *           Note how many ways there are to calculate pairwise identity,
+ *           because of the variety of choices for the denominator:
+ *           idents/(idents+mismat) has the disadvantage that artifactual
+ *             gappy alignments would have high "identities".
+ *           idents/(AVG|MAX)(len1,len2) both have the disadvantage that 
+ *             alignments of fragments to longer sequences would have
+ *             artifactually low "identities".
+ *           
+ *           Case sensitive; also, watch out in nucleic acid alignments; 
+ *           U/T RNA/DNA alignments will be counted as mismatches!
+ */
+/* float
+PairwiseIdentity(char @s1, char @s2)
+{
+  int     idents;              /@ total identical positions  @/
+  int     len1, len2;          /@ lengths of seqs            @/
+  int     x;                   /@ position in aligned seqs   @/
+
+  idents = len1 = len2 = 0;
+  for (x = 0; s1[x] != '\0' && s2[x] != '\0'; x++) 
+  {
+      if (!isgap(s1[x])) {
+          len1++;
+          if (s1[x] == s2[x]) idents++; 
+      }
+      if (!isgap(s2[x])) len2++;
+  }
+  if (len2 < len1) len1 = len2;
+  return (len1 == 0 ? 0.0 : (float) idents / (float) len1);
+}
+*/
+
+
+/* s1/s2 are unit-offset as usual
+ *
+ */
+float
+Stats::pairwiseIdentity(Alignment *alnObj, int s1, int s2)
+{
+    int idents;     /* total identical positions */
+    int len1, len2; /* real lengths of seqs      */
+    int x;          /* position in aligned seqs  */
+    
+    const vector<int>* seq1 = alnObj->getSequence(s1);
+    const vector<int>* seq2 = alnObj->getSequence(s2);
+    
+    idents = len1 = len2 = 0;
+    // cerr << "comparing " << alnObj->getName(s1).c_str() << ":" << alnObj->getName(s2).c_str() << " " << s1 << ":" << s2  << "\n";
+    
+    // sequence length should be identical, but be paranoid
+    for (x = 1; x<=alnObj->getSeqLength(s1) && x<=alnObj->getSeqLength(s2); x++)
+    {
+        if (! alnObj->isGap(s1, x)) {
+            len1++;
+            //cerr << " pos " << x << ": " << (*seq1)[x] << ":" << (*seq2)[x] << "\n";
+            if ((*seq1)[x] == (*seq2)[x])
+                idents++; 
+        }
+        //DEBUG
+        //else {
+        //cerr << " gap at pos " << x << " (" << s1 << ")\n";
+        //}
+        if (! alnObj->isGap(s2, x))
+            len2++;
+        //DEBUG
+        //else
+        //    cerr << " gap at pos " << x << " (" << s2 << ")\n";
+    }
+    if (len2 < len1)
+        len1 = len2;
+    return (len1 == 0 ? 0.0 : (float) idents / (float) len1);
+}
+  
+
+
+#ifdef HAVE_MHASH_H
+
+string
+Stats::ConcatInputHash(Alignment *alnObj)
+{
+    vector<string> rawSeqArray;
+    string ret;
+    char *hash;
+
+    // collect all sequences and sort 
+    const clustalw::SeqArray* seqArray = alnObj->getSeqArray();
+    for(int s = 1; s <= alnObj->getNumSeqs(); s++)
+    {
+        string seq;
+        for(int r = 1; r <= alnObj->getSeqLength(s); r++)
+        {
+            int val = (*seqArray)[s][r];
+            seq.append(1, clustalw::userParameters->getAminoAcidCode(val));
+        }
+        rawSeqArray.push_back(seq);
+    }
+    std::sort(rawSeqArray.begin(), rawSeqArray.end());
+
+    // concatenate sorted seqs
+    string concatSeq;
+    std::vector<string>::iterator iter;
+    for(iter=rawSeqArray.begin(); iter != rawSeqArray.end(); ++iter)
+        concatSeq.append(*iter);
+
+    // build hash and return
+    hash = Md5Hash(concatSeq.c_str());
+    if (hash==NULL)
+    {
+        ret="HASHING_FAILURE";
+    } else {
+        for (int i=0; i<strlen(hash); i++)
+        ret.append(1, hash[i]);
+        free(hash);
+    }
+    return ret;
+}
+
+
+string
+Stats::Md5ForSeq(Alignment *alnObj, int s)
+{
+    string seq;
+    const clustalw::SeqArray* seqArray = alnObj->getSeqArray();
+    char *hash;
+    string ret;
+    
+    for(int l = 1; l <= alnObj->getSeqLength(s); l++)
+    {
+        int val = (*seqArray)[s][l];
+        // continue if gap
+        if((val < 0) || (val > userParameters->getMaxAA()))
+            continue;
+        seq.append(1, clustalw::userParameters->getAminoAcidCode(val));
+    }
+    std::transform(seq.begin(), seq.end(), seq.begin(), ::toupper);
+
+    hash = Md5Hash(seq.c_str());
+    if (hash==NULL)
+    {
+        ret = "HASHING_FAILURE";
+    } else {
+        ret = hash;
+    }
+    return ret;
+}
+
+/* create md5 hash from input string
+ * returns NULL on failure
+ * user must free returned string
+ */
+char *
+Stats::Md5Hash(const char *thread)
+{
+    MHASH td;
+    char *tmpcstr;
+    int i;
+    unsigned char *hash;
+    char *rethash;
+    
+    td = mhash_init(MHASH_MD5);
+    if (td == MHASH_FAILED)
+        return NULL;
+
+    if (thread==NULL)
+        return NULL;
+
+    mhash(td, thread, strlen(thread));
+    //mhash_deinit(td, hash);
+    hash = (unsigned char*) mhash_end(td);
+    
+    rethash = (char*) calloc(mhash_get_block_size(MHASH_MD5)*2+1, sizeof(char));
+    for (i = 0; i < mhash_get_block_size(MHASH_MD5); i++) {
+        sprintf(&rethash[i*2], "%.2x", hash[i]);
+    }
+
+    return rethash;
+}
+
+#endif
+// HAVE_MHASH_H
+
+
+
+
+void
+Stats::logCmdLine(int argc, char **argv)
+{
+    FILE *fp = fopen(logfilename.c_str(), "a");
+    if (fp == NULL)
+    {
+        cerr << "couldn't open file " << logfilename << " for logging of stats\n";
+        return;
+    }
+
+    if (argc > 1)
+    {
+        for (int i=1; i<argc; i++)
+        {
+            // remove non-interesting stuff
+            if (strstr(argv[i], "-infile=")==NULL &&
+                strstr(argv[i], "-outfile=")==NULL &&
+                strstr(argv[i], "-stats=")==NULL &&
+                strstr(argv[i], "-align")==NULL)
+            {
+                fprintf(fp, "cmdline non-default arg: %s\n", argv[i]);
+            }
+        }
+    }
+}
+
+
+/* log some statistics for input sequences, i.e. alnObj should hold
+ * the unaligned sequences
+ *
+ */
+void
+Stats::logInputSeqStats(Alignment *alnObj)
+{
+    int i;
+    std::vector<double> lengths;
+    time_t t = time(NULL);
+    tm s = *localtime(&t);
+    int shortest;
+    string hash;
+    
+    FILE *fp = fopen(logfilename.c_str(), "a");
+    if (fp == NULL)
+    {
+        cerr << "couldn't open file " << logfilename << " for logging of stats\n";
+        return;
+    }
+
+    fprintf(fp, "logging job: %s on %s", userParameters->getSeqName().c_str(), asctime(&s));
+    fprintf(fp, "clustal version: %s\n", userParameters->getRevisionLevel().c_str());
+
+    fprintf(fp, "seq type: ");
+    if (userParameters->getDNAFlag())
+        fprintf(fp, "DNA");
+    else
+        fprintf(fp, "protein");
+    fprintf(fp, "\n");
+    
+    fprintf(fp, "numseqs: %d\n", alnObj->getNumSeqs());
+
+    // create a vector of seq lengths for later
+    // and get shortest seq at the same time
+    shortest=alnObj->getLengthLongestSequence();
+    for (i = 1; i <= alnObj->getNumSeqs(); i++) {
+        int l = alnObj->getSeqLength(i);
+        lengths.push_back(l);
+        if (l<shortest)
+            shortest=l;
+    }
+    
+    fprintf(fp, "seqlen longest: %d\n", alnObj->getLengthLongestSequence());
+    fprintf(fp, "seqlen shortest: %d\n", shortest);
+
+    fprintf(fp, "seqlen avg: %.2f\n", utilityObject->average(lengths));
+    fprintf(fp, "seqlen std-dev: %.2f\n", utilityObject->stdDev(lengths));
+    fprintf(fp, "seqlen median: %.2f\n", utilityObject->median(lengths));
+
+    
+#ifdef HAVE_MHASH_H
+    //hash = concatInputHash(alnObj);
+    //fprintf(fp, "seq hash: %s\n", hash.c_str());
+    
+    for (int s = 1; s <= alnObj->getNumSeqs(); s++) {
+        string md5 = Md5ForSeq(alnObj, s);
+        fprintf(fp, "md5 for seq %d: %s\n", s, md5.c_str());
+
+    }
+#else
+    fprintf(fp, "md5: disabled\n");    
+#endif
+
+    fclose(fp);
+}
+
+
+
+/* log some statistics for aligned sequences, i.e. alnObj should hold
+ * the already aligned sequences
+ *
+ */
+void
+Stats::logAlignedSeqStats(Alignment *alnObj)
+{
+    FILE *fp = fopen(logfilename.c_str(), "a");
+    if (fp == NULL)
+    {
+        cerr << "couldn't open file " << logfilename << " for logging of stats\n";
+        return;
+    }
+    
+    // alignment length is the length of any sequence
+    fprintf(fp, "aln len: %d\n", alnObj->getSeqLength(1));
+
+
+    std::vector<double> pwIdents;
+    double lowestPwId = 1.0;
+    double hightestPwId = 0.0;
+
+    // create vector of pairwise identities
+    for(int s1 = 1; s1 <= alnObj->getNumSeqs(); s1++)
+    {        
+        for(int s2 = s1+1; s2 <= alnObj->getNumSeqs(); s2++)
+        {
+            double thisPwId = pairwiseIdentity(alnObj, s1, s2);
+            pwIdents.push_back(thisPwId);
+            if (thisPwId>hightestPwId)
+                hightestPwId=thisPwId;
+            if (thisPwId<lowestPwId)
+                lowestPwId=thisPwId;
+            //fprintf(fp, "ident %s:%s %d:%d=%f\n", alnObj->getName(s1).c_str(), alnObj->getName(s2).c_str(), s1, s2, PairwiseIdentity(alnObj, s1, s2));
+        }
+    }
+    fprintf(fp, "aln pw-id highest: %.2f\n", hightestPwId);
+    fprintf(fp, "aln pw-id lowest: %.2f\n", lowestPwId);
+    fprintf(fp, "aln pw-id avg: %.2f\n",  utilityObject->average(pwIdents));
+    fprintf(fp, "aln pw-id std-dev: %.2f\n",  utilityObject->stdDev(pwIdents));
+    fprintf(fp, "aln pw-id median: %.2f\n",  utilityObject->median(pwIdents));
+
+    fclose(fp);
+}
+
+}
+