format_guess.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:9k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: format_guess.cpp,v $
  4.  * PRODUCTION Revision 1000.5  2004/06/01 19:40:07  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: format_guess.cpp,v 1000.5 2004/06/01 19:40:07 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author: Anatoliy Kuznetsov
  35.  *
  36.  * File Description:  Implemented methods to identify file formats.
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <util/format_guess.hpp>
  41. #include <corelib/ncbifile.hpp>
  42. BEGIN_NCBI_SCOPE
  43. static bool isDNA_Alphabet(char ch)
  44. {
  45.     return ::strchr("ATGCN", ch) != 0;
  46. }
  47. // Check if letter belongs to amino acid alphabet
  48. static bool isProtein_Alphabet(char ch)
  49. {
  50.     return ::strchr("ACDEFGHIKLMNPQRSTVWYBZ", ch) != 0;
  51. }
  52. // Check if character belongs to the CR/LF group of symbols
  53. static inline bool isLineEnd(char ch)
  54. {
  55.     return ch == 0x0D || ch == 0x0A || ch == 'n';
  56. }
  57. CFormatGuess::ESequenceType 
  58. CFormatGuess::SequenceType(const char* str, unsigned length)
  59. {
  60.     if (length == 0)
  61.         length = (unsigned)::strlen(str);
  62.     unsigned ATGC_content = 0;
  63.     unsigned amino_acid_content = 0;
  64.     for (unsigned i = 0; i < length; ++i) {
  65.         unsigned char ch = str[i];
  66.         char upch = toupper(ch);
  67.         if (isDNA_Alphabet(upch)) {
  68.             ++ATGC_content;
  69.         }
  70.         if (isProtein_Alphabet(upch)) {
  71.             ++amino_acid_content;
  72.         }
  73.     }
  74.     double dna_content = (double)ATGC_content / (double)length;
  75.     double prot_content = (double)amino_acid_content / (double)length;
  76.     if (dna_content > 0.7) {
  77.         return eNucleotide;
  78.     }
  79.     if (prot_content > 0.7) {
  80.         return eProtein;
  81.     }
  82.     return eUndefined;
  83. }
  84. CFormatGuess::EFormat CFormatGuess::Format(const string& path)
  85. {
  86.     CNcbiIfstream input(path.c_str(), IOS_BASE::in | IOS_BASE::binary);
  87.     if (!input.is_open()) {
  88.         return eUnknown;
  89.     }
  90.     return Format(input);
  91. }
  92. CFormatGuess::EFormat CFormatGuess::Format(CNcbiIstream& input)
  93. {
  94.     EFormat format = eUnknown;
  95.     CT_POS_TYPE orig_pos = input.tellg();
  96.     unsigned char buf[1024];
  97.     input.read((char*)buf, sizeof(buf));
  98.     size_t count = input.gcount();
  99. input.clear();  // in case we reached eof
  100. input.seekg(orig_pos);
  101.     if (!count) {
  102.         return eUnknown;
  103.     }
  104.     // Buffer analysis (completely ad-hoc heuristics).
  105.     // Check for XML signature...
  106.     {{
  107.         if (count > 5) {
  108.             const char* xml_sig = "<?XML";
  109.             bool xml_flag = true;
  110.             for (unsigned i = 0; i < 5; ++i) {
  111.                 unsigned char ch = buf[i];
  112.                 char upch = toupper(ch);
  113.                 if (upch != xml_sig[i]) {
  114.                     xml_flag = false;
  115.                     break;
  116.                 }
  117.             }
  118.             if (xml_flag) {
  119.                 
  120.                 return eXml;
  121.             }
  122.         }
  123.     }}
  124.     // check for binary ASN.1 - the presence of any non-printing characters
  125.     // can confirm this
  126.     unsigned int i = 0;
  127.     {{
  128.         for (i = 0;  i < count;  ++i) {
  129.             if ( !isgraph(buf[i])  &&  !isspace(buf[i]) ) {
  130.                 return eBinaryASN;
  131.             }
  132.         }
  133.     }}
  134.     
  135.     unsigned ATGC_content = 0;
  136.     unsigned amino_acid_content = 0;
  137.     unsigned seq_length = (unsigned)count;
  138.     unsigned alpha_content = 0;
  139.     if (buf[0] == '>') { // FASTA ?
  140.         for (i = 0; (!isLineEnd(buf[i])) && i < count; ++i) {
  141.             // skip the first line (presumed this is free-text information)
  142.             unsigned char ch = buf[i];
  143.             if (isalnum(ch) || isspace(ch)) {
  144.                 ++alpha_content;
  145.             }
  146.         }
  147.         seq_length = (unsigned)count - i;
  148.         if (seq_length == 0) {
  149.             return eUnknown;   // No way to tell what format is this...
  150.         }
  151.     }
  152.     for (i = 0; i < count; ++i) {
  153.         unsigned char ch = buf[i];
  154.         char upch = toupper(ch);
  155.         if (isalnum(ch) || isspace(ch)) {
  156.             ++alpha_content;
  157.         }
  158.         if (isDNA_Alphabet(upch)) {
  159.             ++ATGC_content;
  160.         }
  161.         if (isProtein_Alphabet(upch)) {
  162.             ++amino_acid_content;
  163.         }
  164.         if (isLineEnd(ch)) {
  165.             ++alpha_content;
  166.             --seq_length;
  167.         }
  168.     }
  169.     double dna_content = (double)ATGC_content / (double)seq_length;
  170.     double prot_content = (double)amino_acid_content / (double)seq_length;
  171.     double a_content = (double)alpha_content / (double)count;
  172.     if (buf[0] == '>') {
  173.         if (dna_content > 0.7 && a_content > 0.91) {
  174.             return eFasta;  // DNA fasta file
  175.         }
  176.         if (prot_content > 0.7 && a_content > 0.91) {
  177.             return eFasta;  // Protein fasta file
  178.         }
  179.     }
  180.     if (a_content > 0.80) {  // Text ASN ?
  181.         // extract first line
  182.         char line[1024] = {0,};
  183.         char* ptr = line;
  184.         for (i = 0; i < count; ++i) {
  185.             if (isLineEnd(buf[i])) {
  186.                 break;
  187.             }
  188.             *ptr = buf[i];
  189.             ++ptr;
  190.         }
  191.         // roll it back to last non-space character...
  192.         while (ptr > line) {
  193.             --ptr;
  194.             if (!isspace(*ptr)) break;
  195.         }
  196.         if (*ptr == '{') {  // "{" symbol says it's most likely ASN text
  197.             return eTextASN;
  198.         }
  199.     }
  200.     // Signature check
  201.     if (buf[1] == 0x80) {
  202.         if (buf[0] == 0x30 || buf[0] == 0x31) {
  203.             //return eBinaryASN;
  204.         }
  205.         if (buf[0] >= 0xA0) {
  206.             //return eBinaryASN;
  207.         }
  208.     }
  209.     return format;
  210. }
  211. END_NCBI_SCOPE
  212. /*
  213.  * ===========================================================================
  214.  * $Log: format_guess.cpp,v $
  215.  * Revision 1000.5  2004/06/01 19:40:07  gouriano
  216.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17
  217.  *
  218.  * Revision 1.17  2004/05/17 21:06:02  gorelenk
  219.  * Added include of PCH ncbi_pch.hpp
  220.  *
  221.  * Revision 1.16  2004/04/01 12:17:20  kuznets
  222.  * Added 'N' to the legal DNA alphabet. (isDNA_Alphabet)
  223.  *
  224.  * Revision 1.15  2004/03/24 20:35:34  ucko
  225.  * Use the correct type (CT_POS_TYPE rather than int) for tellg's return value.
  226.  *
  227.  * Revision 1.14  2004/03/23 23:04:23  jcherry
  228.  * clear() stream after reading; seekg() in just one place
  229.  *
  230.  * Revision 1.13  2004/03/23 22:29:50  jcherry
  231.  * Added Format(CNcbiIstream& input)
  232.  *
  233.  * Revision 1.12  2004/03/02 20:06:59  johnson
  234.  * bug fix: missing loop initializers
  235.  *
  236.  * Revision 1.11  2004/03/01 15:49:54  dicuccio
  237.  * Added explicit check for binary ASN
  238.  *
  239.  * Revision 1.10  2003/12/02 20:16:09  kuznets
  240.  * Improved ASN binary recognition by checking ASN specific signatures
  241.  *
  242.  * Revision 1.9  2003/11/26 14:34:16  kuznets
  243.  * Fine tuned ascii content coefficient to better recognize binary asns
  244.  *
  245.  * Revision 1.8  2003/11/07 17:16:23  ivanov
  246.  * Fixed  warnings on 64-bit Workshop compiler
  247.  *
  248.  * Revision 1.7  2003/07/10 19:58:25  ivanov
  249.  * Get rid of compilation warning: removed double variable declaration
  250.  *
  251.  * Revision 1.6  2003/07/08 20:30:50  kuznets
  252.  * Fixed bug with different "n" coding in DOS-Windows and Unix.
  253.  *
  254.  * Revision 1.5  2003/07/07 19:54:06  kuznets
  255.  * Improved format recognition of short fasta files
  256.  *
  257.  * Revision 1.4  2003/06/20 20:58:04  kuznets
  258.  * Cleaned up amino-acid alphabet recognition.
  259.  *
  260.  * Revision 1.3  2003/05/13 15:18:02  kuznets
  261.  * added sequence type guessing function
  262.  *
  263.  * Revision 1.2  2003/05/09 14:08:28  ucko
  264.  * ios_base:: -> IOS_BASE:: for gcc 2.9x compatibility
  265.  *
  266.  * Revision 1.1  2003/05/08 19:46:34  kuznets
  267.  * Initial revision
  268.  *
  269.  * ===========================================================================
  270.  */