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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: id1_fetch.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:30:30  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.50
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: id1_fetch.cpp,v 1000.2 2004/06/01 18:30:30 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:  Denis Vakatov, Aleksey Grichenko, Aaron Ucko
  35.  *
  36.  * File Description:
  37.  *   New IDFETCH network client (get data from "ID1")
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbiapp.hpp>
  41. #include <corelib/ncbienv.hpp>
  42. #include <corelib/ncbiargs.hpp>
  43. #include <corelib/ncbireg.hpp>
  44. #include <connect/ncbi_core_cxx.hpp>
  45. #include <serial/enumvalues.hpp>
  46. #include <serial/objostrasnb.hpp>
  47. #include <serial/iterator.hpp>
  48. #include <objects/entrez2/Entrez2_boolean_element.hpp>
  49. #include <objects/entrez2/Entrez2_boolean_exp.hpp>
  50. #include <objects/entrez2/Entrez2_boolean_reply.hpp>
  51. #include <objects/entrez2/Entrez2_db_id.hpp>
  52. #include <objects/entrez2/Entrez2_docsum.hpp>
  53. #include <objects/entrez2/Entrez2_docsum_data.hpp>
  54. #include <objects/entrez2/Entrez2_docsum_list.hpp>
  55. #include <objects/entrez2/Entrez2_eval_boolean.hpp>
  56. #include <objects/entrez2/Entrez2_id_list.hpp>
  57. #include <objects/entrez2/entrez2_client.hpp>
  58. #include <objects/general/Date.hpp>
  59. #include <objects/general/Date_std.hpp>
  60. #include <objects/general/Dbtag.hpp>
  61. #include <objects/general/Object_id.hpp>
  62. #include <objects/id1/ID1Seq_hist.hpp>
  63. #include <objects/id1/ID1server_maxcomplex.hpp>
  64. #include <objects/id1/id1_client.hpp>
  65. #include <objmgr/graph_ci.hpp>
  66. #include <objmgr/object_manager.hpp>
  67. #include <objmgr/scope.hpp>
  68. #include <objmgr/seq_vector.hpp>
  69. #include <objtools/data_loaders/genbank/gbloader.hpp>
  70. #include <objects/seq/Bioseq.hpp>
  71. #include <objects/seq/Seq_descr.hpp>
  72. #include <objects/seq/Seq_hist_rec.hpp>
  73. #include <objects/seq/Seqdesc.hpp>
  74. #include <objects/seqloc/Seq_id.hpp>
  75. #include <objects/seqloc/Textseq_id.hpp>
  76. #include <objects/seqres/Byte_graph.hpp>
  77. #include <objects/seqres/Seq_graph.hpp>
  78. #include <objects/seqset/Seq_entry.hpp>
  79. #include <objects/seqset/Bioseq_set.hpp>
  80. #if 1
  81. #include <objtools/flat/flat_ncbi_formatter.hpp>
  82. #else
  83. #include <objmgr/util/genbank.hpp>
  84. #endif
  85. #include <objmgr/util/sequence.hpp>
  86. #include <memory>
  87. #include <algorithm>
  88. BEGIN_NCBI_SCOPE
  89. USING_SCOPE(NCBI_NS_NCBI::objects); // MSVC requires qualification (!)
  90. /////////////////////////////////
  91. //  CId1FetchApp::
  92. //
  93. class CId1FetchApp : public CNcbiApplication
  94. {
  95.     virtual void Init(void);
  96.     virtual int  Run (void);
  97.     virtual void Exit(void);
  98. private:
  99.     bool LookUpGI(int gi);
  100.     int  LookUpFastaSeqID(const string& s);
  101.     int  LookUpFlatSeqID(const string& s);
  102.     void WriteFastaIDs     (const list< CRef< CSeq_id > >& ids);
  103.     void WriteHistoryTable (const CID1server_back& id1_reply);
  104.     void WriteQualityScores(CBioseq_Handle& handle);
  105.     CNcbiOstream*        m_OutputFile;
  106.     CID1Client           m_ID1Client;
  107.     CEntrez2Client       m_E2Client;
  108.     CRef<CObjectManager> m_ObjMgr;
  109.     CRef<CScope>         m_Scope;
  110. };
  111. void CId1FetchApp::Init(void)
  112. {
  113.     // Prepare command line descriptions
  114.     //
  115.     // Create
  116.     auto_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
  117.     // GI
  118.     arg_desc->AddOptionalKey
  119.         ("gi", "SeqEntryID",
  120.          "GI id of the Seq-Entry to fetch",
  121.          CArgDescriptions::eInteger);
  122.     arg_desc->SetConstraint
  123.         ("gi", new CArgAllow_Integers(0, 99999999));
  124.     // Output format
  125.     arg_desc->AddDefaultKey
  126.         ("fmt", "OutputFormat",
  127.          "Format to dump the resulting data in",
  128.          CArgDescriptions::eString, "asn");
  129.     arg_desc->SetConstraint
  130.         ("fmt", &(*new CArgAllow_Strings,
  131.                   "asn", "asnb", "xml", "genbank", "genpept", "fasta",
  132.                   "quality", "docsum"));
  133.     // Output datafile
  134.     arg_desc->AddDefaultKey
  135.         ("out", "ResultFile",
  136.          "File to dump the resulting data to",
  137.          CArgDescriptions::eOutputFile, "-", CArgDescriptions::fBinary);
  138.     // Log file
  139.     arg_desc->AddOptionalKey
  140.         ("log", "LogFile",
  141.          "File to post errors and messages to",
  142.          CArgDescriptions::eOutputFile,
  143.          0);
  144.     // Database to use
  145.     arg_desc->AddOptionalKey
  146.         ("db", "Database", // was "-d" in `idfetch'
  147.          "Database to use",
  148.          CArgDescriptions::eString);
  149.     
  150.     // Entity number
  151.     arg_desc->AddOptionalKey
  152.         ("ent", "EntityNumber", // was "-e" in `idfetch'
  153.          "(Sub)entity number (retrieval number) to dump",
  154.          CArgDescriptions::eInteger);
  155.     arg_desc->SetConstraint
  156.         ("ent", new CArgAllow_Integers(0, 99999999));
  157.     // Type of lookup
  158.     arg_desc->AddDefaultKey
  159.         ("lt", "LookupType", // combination of "-i" (!) and "-n" in `idfetch'
  160.          "Type of lookup",
  161.          CArgDescriptions::eString, "entry");
  162.     arg_desc->SetConstraint
  163.         ("lt", &(*new CArgAllow_Strings,
  164.                  "entry", "state", "ids", "history", "revisions", "none"));
  165.     
  166.     // File with list of stuff to dump
  167.     arg_desc->AddOptionalKey
  168.         ("in", "RequestFile", // was "-G" (!) in `idfetch'
  169.          "File with list of GIs, (versioned) accessions, FASTA SeqIDs to dump",
  170.          CArgDescriptions::eInputFile, CArgDescriptions::fPreOpen);
  171.          
  172.     // Maximum complexity
  173.     arg_desc->AddDefaultKey
  174.         ("maxplex", "MaxComplexity", // was "-c" in `idfetch'
  175.          "Maximum complexity to return",
  176.          CArgDescriptions::eString, "entry");
  177.     arg_desc->SetConstraint
  178.         ("maxplex", &(*new CArgAllow_Strings,
  179.                       "entry", "bioseq", "bioseq-set", "nuc-prot",
  180.                       "pub-set"));
  181.     
  182.     // Flattened SeqID
  183.     arg_desc->AddOptionalKey
  184.         ("flat", "FlatID", // was "-f" in `idfetch'
  185.          "Flattened SeqID; format can ben"
  186.          "t'type([name][,[accession][,[release][,version]]])'"
  187.          " [e.g., '5(HUMHBB)'],n"
  188.          "ttype=accession[.version], or type:number",
  189.          CArgDescriptions::eString);
  190.     
  191.     // FASTA-style SeqID
  192.     arg_desc->AddOptionalKey
  193.         ("fasta", "FastaID", // was "-s" in `idfetch'
  194.          "FASTA-style SeqID, in the form "type|data"; choices aren"
  195.          "tlcl|int lcl|str bbs|int bbm|int gim|int gb|acc|loc emb|acc|locn"
  196.          "tpir|acc|name sp|acc|name pat|country|patent|seq ref|acc|name|reln"
  197.          "tgnl|db|id gi|int dbj|acc|loc prf|acc|name pdb|entry|chainn"
  198.          "ttpg|acc|name tpe|acc|name tpd|acc|name",
  199.          CArgDescriptions::eString);
  200.     // Generate GI list by Entrez query
  201.     arg_desc->AddOptionalKey
  202.         ("query", "EntrezQueryString", // was "-q" in `idfetch'
  203.          "Generate GI list by Entrez query given on command line",
  204.          CArgDescriptions::eString);
  205.     arg_desc->AddOptionalKey
  206.         ("qf", "EntrezQueryFile", // was "-Q" in `idfetch'
  207.          "Generate GI list by Entrez query in given file",
  208.          CArgDescriptions::eInputFile, CArgDescriptions::fPreOpen);
  209.     // Program description
  210.     string prog_description =
  211.         "Fetch SeqEntry from ID server by its GI ID, possibly obtained fromn"
  212.         "its SeqID or an Entrez query";
  213.     arg_desc->SetUsageContext(GetArguments().GetProgramBasename(),
  214.                               prog_description, false);
  215.     arg_desc->AddDefaultKey
  216.         ("repeat", "repeat",
  217.          "Repeat fetch number of times",
  218.          CArgDescriptions::eInteger, "1");
  219.     // Pass argument descriptions to the application
  220.     //
  221.     SetupArgDescriptions(arg_desc.release());
  222. }
  223. // Workaround for "replace_if"
  224. inline bool s_IsControl(char c)
  225. {
  226.     return iscntrl(c) ? true : false;
  227. }
  228. int CId1FetchApp::Run(void)
  229. {
  230.     // Process command line args
  231.     const CArgs& args = GetArgs();
  232.     // Setup and tune logging facilities
  233.     if ( args["log"] ) {
  234.         SetDiagStream( &args["log"].AsOutputFile() );
  235.     }
  236. #ifdef _DEBUG
  237.     // SetDiagTrace(eDT_Enable);
  238.     SetDiagPostLevel(eDiag_Info);
  239.     SetDiagPostFlag(eDPF_All);
  240. #endif
  241.     // Make sure the combination of arguments is valid
  242.     {{
  243.         int id_count = 0;
  244.         const string& fmt = args["fmt"].AsString();
  245.         if (args["gi"])     id_count++;
  246.         if (args["in"])     id_count++;
  247.         if (args["flat"])   id_count++;
  248.         if (args["fasta"])  id_count++;
  249.         if (args["query"])  id_count++;
  250.         if (args["qf"])     id_count++;
  251.         if (id_count != 1) {
  252.             NCBI_THROW(CArgException,eNoArg,
  253.                 "You must supply exactly one argument"
  254.                 " indicating what to look up.");
  255.         }
  256.         if ((args["query"]  ||  args["qf"]  ||  fmt == "docsum")
  257.             &&  !args["db"]) {
  258.             ERR_POST("No Entrez database supplied.  Try -db Nucleotide or "
  259.                      "-db Protein.");
  260.             return -1;
  261.         }
  262.         if ((fmt == "genbank"  ||  fmt == "genpept"  ||  fmt == "quality")
  263.             &&  args["lt"].AsString() != "entry") {
  264.             ERR_POST("The output format '" << fmt
  265.                      << "' is only available for Seq-Entries.");
  266.             return -1;
  267.         }
  268.     }}
  269.     // Setup application registry, error log, and MT-lock for CONNECT library
  270.     CONNECT_Init(&GetConfig());
  271.     m_E2Client.SetDefaultRequest().SetTool("id1_fetch");
  272.     // Open output file
  273.     m_OutputFile = &args["out"].AsOutputFile();
  274.     // Set up object manager
  275.     m_ObjMgr = new CObjectManager;
  276.     m_Scope = new CScope(*m_ObjMgr);
  277.     m_ObjMgr->RegisterDataLoader( *new CGBDataLoader("GENBANK"));
  278.     m_Scope->AddDataLoader("GENBANK");
  279.     int repeat = args["repeat"].AsInteger();
  280.     for ( int pass = 0; pass < repeat; ++pass ) {
  281.     if (args["gi"]) {
  282.         if ( !LookUpGI(args["gi"].AsInteger()) )
  283.             return -1;
  284.     }
  285.     if (args["fasta"]) {
  286.         int gi = LookUpFastaSeqID(args["fasta"].AsString());
  287.         if (gi <= 0  ||  !LookUpGI(gi)) {
  288.             return -1;
  289.         }
  290.     }
  291.     if (args["flat"]) {
  292.         int gi = LookUpFlatSeqID(args["flat"].AsString());
  293.         if (gi <= 0  ||  !LookUpGI(gi)) {
  294.             return -1;
  295.         }
  296.     }
  297.     if (args["in"]) {
  298.         CNcbiIstream& is = args["in"].AsInputFile();
  299.         while (is  &&  !is.eof()) {
  300.             string id;
  301.             int    gi;
  302.             is >> id;
  303.             if (id.empty()) {
  304.                 break;
  305.             }
  306.             if (id.find('|') != NPOS) {
  307.                 gi = LookUpFastaSeqID(id);
  308.             } else if (id.find_first_of(":=(") != NPOS) {
  309.                 gi = LookUpFlatSeqID(id);
  310.             } else {
  311.                 gi = NStr::StringToInt(id);
  312.             }
  313.             if (gi <= 0  ||  !LookUpGI(gi)) {
  314.                 return -1;
  315.             }
  316.         }
  317.     }
  318.     if (args["query"]  ||  args["qf"]) {
  319.         // Form query
  320.         CRef<CEntrez2_boolean_element> e2_element
  321.             (new CEntrez2_boolean_element);
  322.         if (args["query"]) {
  323.             e2_element->SetStr(args["query"].AsString());
  324.         } else {
  325.             CNcbiIstream& is = args["qf"].AsInputFile();
  326.             CNcbiOstrstream oss;
  327.             oss << is.rdbuf();
  328.             string& str = e2_element->SetStr();
  329.             str.assign(oss.str(), oss.pcount());
  330.             oss.freeze(false);
  331.             replace_if(str.begin(), str.end(), s_IsControl, ' ');
  332.         }
  333.         // Make the actual query
  334.         CRef<CEntrez2_boolean_reply> reply;
  335.         {{
  336.             CEntrez2_eval_boolean eb;
  337.             eb.SetReturn_UIDs(true);
  338.             CEntrez2_boolean_exp& query = eb.SetQuery();
  339.             query.SetExp().push_back(e2_element);
  340.             query.SetDb() = CEntrez2_db_id(args["db"].AsString());
  341.             reply = m_E2Client.AskEval_boolean(eb);
  342.         }}
  343.         if ( !reply->GetCount() ) {
  344.             ERR_POST("Entrez query returned no results.");
  345.             return -1;
  346.         }
  347.         // Query succeeded; proceed to next stage of lookup
  348.         for (CEntrez2_id_list::TConstUidIterator it
  349.                  = reply->GetUids().GetConstUidIterator();
  350.              !it.AtEnd();  ++it) {
  351.             if ( !LookUpGI(*it) ) {
  352.                 return -1;
  353.             }
  354.         }
  355.     }
  356.     }
  357.     return 0;
  358. }
  359. bool CId1FetchApp::LookUpGI(int gi)
  360. {    
  361.     const CArgs&             args       = GetArgs();
  362.     const string&            fmt        = args["fmt"].AsString();
  363.     const string&            lt         = args["lt"].AsString();
  364.     CConstRef<CSerialObject> reply_object;
  365.     bool                     use_objmgr = false;
  366.     if (lt == "none") {
  367.         *m_OutputFile << gi << NcbiEndl;
  368.         return true;  // Done
  369.     } else if (fmt == "docsum") {
  370.         // Handling this here costs some efficiency when the GI came
  371.         // from an Entrez query in the first place, but wins on generality.
  372.         CEntrez2_id_list uids;
  373.         uids.SetDb() = CEntrez2_db_id(args["db"].AsString());
  374.         uids.SetNum(1);
  375.         uids.SetUids().resize(uids.sm_UidSize);
  376.         {{
  377.             CEntrez2_id_list::TUidIterator it = uids.GetUidIterator();
  378.             *it = gi;
  379.         }}
  380.         CRef<CEntrez2_docsum_list> docs = m_E2Client.AskGet_docsum(uids);
  381.         if ( !docs->GetCount() ) {
  382.             ERR_POST("Entrez query returned no results.");
  383.             return false;
  384.         }
  385.         string caption, title;
  386.         for (CTypeConstIterator<CEntrez2_docsum_data> it = ConstBegin(*docs);
  387.              it;  ++it) {
  388.             // Should this be case-insensitive?
  389.             if (it->GetField_name() == "Caption") {
  390.                 caption = it->GetField_value();
  391.             } else if (it->GetField_name() == "Title") {
  392.                 title = it->GetField_value();
  393.             }
  394.         }
  395.         *m_OutputFile << '>';
  396.         if ( !caption.empty() ) {
  397.             *m_OutputFile << caption;
  398.         }
  399.         *m_OutputFile << ' ';
  400.         if ( !title.empty() ) {
  401.             *m_OutputFile << title;
  402.         }
  403.     } else if (lt == "entry") {
  404.         use_objmgr = true;
  405.     } else if (lt == "state") {
  406.         CRef<CID1server_back> id1_reply(new CID1server_back);
  407.         int state = m_ID1Client.AskGetgistate(gi, id1_reply);
  408.         if (fmt == "fasta") {
  409.             *m_OutputFile << "gi = " << gi << ", states: ";
  410.             switch (state & 0xff) {
  411.             case  0: *m_OutputFile << "NONEXISTENT"; break; // was "NOT EXIST"
  412.             case 10: *m_OutputFile << "DELETED";     break;
  413.             case 20: *m_OutputFile << "REPLACED";    break;
  414.             case 40: *m_OutputFile << "LIVE";        break;
  415.             default: *m_OutputFile << "UNKNOWN";     break;
  416.             }
  417.             if (state & 0x100) {
  418.                 *m_OutputFile << "|SUPPRESSED";
  419.             }
  420.             if (state & 0x200) {
  421.                 *m_OutputFile << "|WITHDRAWN";
  422.             }
  423.             if (state & 0x400) {
  424.                 *m_OutputFile << "|CONFIDENTIAL";
  425.             }
  426.         } else {
  427.             reply_object = id1_reply;
  428.         }
  429.     } else if (lt == "ids") {
  430. #if 1
  431.         CRef<CID1server_back> id1_reply(new CID1server_back);
  432.         CID1server_back::TIds ids
  433.             = m_ID1Client.AskGetseqidsfromgi(gi, id1_reply);
  434.         if (fmt == "fasta") {
  435.             WriteFastaIDs(ids);
  436.         } else {
  437.             reply_object = id1_reply;
  438.         }
  439. #else
  440.         use_objmgr = true;
  441. #endif
  442.     } else if (lt == "history"  ||  lt == "revisions") {
  443.         CRef<CID1server_back> id1_reply(new CID1server_back);
  444.         // ignore result -- it's simpler to use id1_reply
  445.         if (lt == "history") {
  446.             m_ID1Client.AskGetgihist(gi, id1_reply);
  447.         } else {
  448.             m_ID1Client.AskGetgirev(gi, id1_reply);
  449.         }
  450.         if (fmt == "fasta") {
  451.             WriteHistoryTable(*id1_reply);
  452.         } else {
  453.             reply_object = id1_reply;
  454.         }
  455.     }
  456.     CBioseq_Handle handle;
  457.     if (use_objmgr) {
  458.         // What about db, ent, and maxplex?
  459.         CSeq_id id;
  460.         id.SetGi(gi);
  461.         handle = m_Scope->GetBioseqHandle(id);
  462.         if ( !handle ) {
  463.             ERR_POST(Fatal << "Bioseq not found: " << id.DumpAsFasta());
  464.         }
  465.         reply_object.Reset(&handle.GetTopLevelSeqEntry());
  466.     }
  467.     // Dump server response in the specified format
  468.     ESerialDataFormat format = eSerial_None;
  469.     if        (fmt == "asn") {
  470.         format = eSerial_AsnText;
  471.     } else if (fmt == "asnb") {
  472.         format = eSerial_AsnBinary;
  473.     } else if (fmt == "xml") {
  474.         format = eSerial_Xml;
  475.     } else if (fmt == "fasta"  &&  lt == "ids") {
  476.         if (use_objmgr) {
  477.             WriteFastaIDs(handle.GetBioseq().GetId());
  478.         }
  479.     } else if (fmt == "fasta"  &&  lt == "entry") {
  480.         CFastaOstream out(*m_OutputFile);
  481.         out.SetFlag(CFastaOstream::eAssembleParts);
  482.         out.Write(handle);
  483.     } else if (fmt == "quality") {
  484.         WriteQualityScores(handle);
  485.     } else if (fmt == "genbank"  ||  fmt == "genpept") {
  486.         bool gp = fmt == "genpept";
  487.         const CSeq_entry& entry = handle.GetTopLevelSeqEntry();
  488. #if 1
  489.         CFlatNCBIFormatter formatter(*new CFlatTextOStream(*m_OutputFile),
  490.                                      *m_Scope, IFlatFormatter::eMode_Entrez);
  491.         formatter.Format(entry, formatter,
  492.                          gp ? IFlatFormatter::fSkipNucleotides
  493.                          : IFlatFormatter::fSkipProteins);
  494. #else
  495.         CGenbankWriter(*m_OutputFile, *m_Scope,
  496.                        gp ? CGenbankWriter::eFormat_Genpept
  497.                        : CGenbankWriter::eFormat_Genbank)
  498.             .Write(entry);
  499. #endif
  500.     }
  501.     if (reply_object.NotEmpty()  &&  format != eSerial_None) {
  502.         auto_ptr<CObjectOStream> asn_output
  503.            (CObjectOStream::Open(format, *m_OutputFile));
  504.         // *asn_output << *reply_object;
  505.         asn_output->Write(reply_object, reply_object->GetThisTypeInfo());
  506.     }
  507.     if (fmt != "asnb") {
  508.         *m_OutputFile << NcbiEndl;
  509.     }
  510.     return true;  // Done
  511. }
  512. // Cleanup
  513. void CId1FetchApp::Exit(void)
  514. {
  515.     SOCK_ShutdownAPI();
  516.     SetDiagStream(0);
  517. }
  518. int CId1FetchApp::LookUpFastaSeqID(const string& s)
  519. {
  520.     CSeq_id id(s);
  521.     return m_ID1Client.AskGetgi(id);
  522. }
  523. int CId1FetchApp::LookUpFlatSeqID(const string& s)
  524. {
  525.     CSeq_id::E_Choice type = static_cast<CSeq_id::E_Choice>(atoi(s.c_str()));
  526.     SIZE_TYPE pos = s.find_first_of(":=(");
  527.     if (pos == NPOS) {
  528.         THROW0_TRACE(runtime_error("Malformatted flat ID " + s));
  529.     }
  530.     string data = s.substr(pos + 1);
  531.     switch (s[pos]) {
  532.     case ':':
  533.     case '=':
  534.     {
  535.         CSeq_id id(type, data, kEmptyStr);
  536.         return m_ID1Client.AskGetgi(id);
  537.     }
  538.     case '(':
  539.     {
  540.         data.erase(data.end() - 1);
  541.         // remove last character, which should be ')'
  542.         vector<string> pieces;
  543.         NStr::Tokenize(data, ",", pieces);
  544.         pieces.resize(4, kEmptyStr);
  545.         // name acc rel ver -> acc name ver rel
  546.         CSeq_id id(type, pieces[1], pieces[0], pieces[3], pieces[2]);
  547.         return m_ID1Client.AskGetgi(id);
  548.     }
  549.     default: // can't happen, but shut the compiler up
  550.         return -1;
  551.     }
  552. }
  553. void CId1FetchApp::WriteFastaIDs(const list< CRef< CSeq_id > >& ids)
  554. {
  555.     ITERATE (list< CRef< CSeq_id > >, it, ids) {
  556.         if (it != ids.begin()) {
  557.             *m_OutputFile << '|';
  558.         }
  559.         (*it)->WriteAsFasta(*m_OutputFile);
  560.     }
  561. }
  562. // for formatting text
  563. class CTextColumn
  564. {
  565. public:
  566.     CTextColumn() : m_Width(0) { }
  567.     CTextColumn& Add(string s) {
  568.         m_Strings.push_back(s);
  569.         if (s.size() > m_Width)
  570.             m_Width = s.size();
  571.         return *this;
  572.     }
  573.     string Get(unsigned int index) const {
  574.         const string& s = m_Strings[index];
  575.         return s + string(m_Width - s.size(), ' ');
  576.     }
  577.     SIZE_TYPE Width()  const { return m_Width; }
  578.     size_t    Height() const { return m_Strings.size(); }
  579.  
  580. private:
  581.     SIZE_TYPE      m_Width;
  582.     vector<string> m_Strings;
  583. };
  584. void CId1FetchApp::WriteHistoryTable(const CID1server_back& id1_reply)
  585. {
  586.     CTextColumn gis, dates, dbs, numbers;
  587.     gis.Add("GI").Add("--");
  588.     dates.Add("Loaded").Add("------");
  589.     dbs.Add("DB").Add("--");
  590.     numbers.Add("Retrieval No.").Add("-------------");
  591.     for (CTypeConstIterator<CSeq_hist_rec> it = ConstBegin(id1_reply);
  592.          it;  ++it) {
  593.         int    gi = 0;
  594.         string dbname, number;
  595.         if ( it->GetDate().IsStr() ) {
  596.             dates.Add(it->GetDate().GetStr());
  597.         } else {
  598.             CNcbiOstrstream oss;
  599.             const CDate_std& date = it->GetDate().GetStd();
  600.             oss << setfill('0') << setw(2) << date.GetMonth() << '/'
  601.                 << setw(2) << date.GetDay() << '/' << date.GetYear();
  602.             dates.Add(CNcbiOstrstreamToString(oss));
  603.         }
  604.         ITERATE (CSeq_hist_rec::TIds, it2, it->GetIds()) {
  605.             if ( (*it2)->IsGi() ) {
  606.                 gi = (*it2)->GetGi();
  607.             } else if ( (*it2)->IsGeneral() ) {
  608.                 dbname = (*it2)->GetGeneral().GetDb();
  609.                 const CObject_id& tag = (*it2)->GetGeneral().GetTag();
  610.                 if ( tag.IsStr() ) {
  611.                     number = tag.GetStr();
  612.                 } else {
  613.                     number = NStr::IntToString(tag.GetId());
  614.                 }
  615.             }
  616.         }
  617.         gis.Add(NStr::IntToString(gi));
  618.         dbs.Add(dbname);
  619.         numbers.Add(number);
  620.     }
  621.     for (unsigned int n = 0;  n < gis.Height();  n++) {
  622.         *m_OutputFile << gis.Get(n) << "  " << dates.Get(n) << "  "
  623.                       << dbs.Get(n) << "  " << numbers.Get(n) << NcbiEndl;
  624.     }
  625. }
  626. void CId1FetchApp::WriteQualityScores(CBioseq_Handle& handle)
  627. {   
  628.     /* Test case:
  629.      * /net/ncbi/ncbi/ftp/genbank/quality_scores/gbvrt.qscore.gz
  630.      *  GI 13508865: gotseqentry.set.annot.data.graph
  631.      *  >AL590146.2 Phrap Quality (Length:121086, Min: 31, Max: 99)
  632.      *   99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99
  633.      *   ...
  634.      */
  635.     string id = FindBestChoice(handle.GetBioseqCore()->GetId(), CSeq_id::Score)
  636.         ->GetSeqIdString(true);
  637.     
  638.     for (CGraph_CI it(handle, 0, 0);  it;  ++it) {
  639.         string title = it->GetTitle();
  640.         if (title.find("uality") == NPOS) {
  641.             continue;
  642.         }
  643.         const CByte_graph& data = it->GetGraph().GetByte();
  644.         *m_OutputFile << '>' << id << ' ' << title
  645.                       << " (Length: " << it->GetNumval()
  646.                       << ", Min: " << data.GetMin()
  647.                       << ", Max: " << data.GetMax() << ')' << NcbiEndl;
  648.         for (SIZE_TYPE n = 0;  n < data.GetValues().size();  ++n) {
  649.             *m_OutputFile << setw(3) << static_cast<int>(data.GetValues()[n]);
  650.             if (n % 20 == 19) {
  651.                 *m_OutputFile << NcbiEndl;
  652.             }
  653.         }
  654.     }
  655. }
  656. END_NCBI_SCOPE
  657. /////////////////////////////////////////////////////////////////////////////
  658. //  MAIN
  659. //
  660. USING_NCBI_SCOPE;
  661. int main(int argc, const char* argv[]) 
  662. {
  663.     return CId1FetchApp().AppMain(argc, argv);
  664. }
  665. /*
  666. * ===========================================================================
  667. *
  668. * ---------------------------------------------------------------------------
  669. * $Log: id1_fetch.cpp,v $
  670. * Revision 1000.2  2004/06/01 18:30:30  gouriano
  671. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.50
  672. *
  673. * Revision 1.50  2004/05/21 21:41:40  gorelenk
  674. * Added PCH ncbi_pch.hpp
  675. *
  676. * Revision 1.49  2004/04/26 20:46:11  ucko
  677. * Fix typo that accidentally introduced an implicit temporary CSeq_id.
  678. *
  679. * Revision 1.48  2004/04/26 16:53:17  ucko
  680. * Don't try to pass temporary CSeq_id objects, even by const reference,
  681. * as CSeq_id has no public copy constructor.
  682. *
  683. * Revision 1.47  2004/01/05 17:59:32  vasilche
  684. * Moved genbank loader and its readers sources to new location in objtools.
  685. * Genbank is now in library libncbi_xloader_genbank.
  686. * Id1 reader is now in library libncbi_xreader_id1.
  687. * OBJMGR_LIBS macro updated correspondingly.
  688. *
  689. * Old headers temporarily will contain redirection to new location
  690. * for compatibility:
  691. * objmgr/gbloader.hpp > objtools/data_loaders/genbank/gbloader.hpp
  692. * objmgr/reader_id1.hpp > objtools/data_loaders/genbank/readers/id1/reader_id1.hpp
  693. *
  694. * Revision 1.46  2003/10/21 13:48:48  grichenk
  695. * Redesigned type aliases in serialization library.
  696. * Fixed the code (removed CRef-s, added explicit
  697. * initializers etc.)
  698. *
  699. * Revision 1.45  2003/06/02 16:06:16  dicuccio
  700. * Rearranged src/objects/ subtree.  This includes the following shifts:
  701. *     - src/objects/asn2asn --> arc/app/asn2asn
  702. *     - src/objects/testmedline --> src/objects/ncbimime/test
  703. *     - src/objects/objmgr --> src/objmgr
  704. *     - src/objects/util --> src/objmgr/util
  705. *     - src/objects/alnmgr --> src/objtools/alnmgr
  706. *     - src/objects/flat --> src/objtools/flat
  707. *     - src/objects/validator --> src/objtools/validator
  708. *     - src/objects/cddalignview --> src/objtools/cddalignview
  709. * In addition, libseq now includes six of the objects/seq... libs, and libmmdb
  710. * replaces the three libmmdb? libs.
  711. *
  712. * Revision 1.44  2003/05/13 17:14:17  ucko
  713. * Direct flat output to *m_OutputFile rather than hard-coding cout.
  714. *
  715. * Revision 1.43  2003/04/24 16:17:10  vasilche
  716. * Added '-repeat' option.
  717. * Updated includes.
  718. *
  719. * Revision 1.42  2003/04/09 16:00:15  ucko
  720. * Give all RPC clients unique basenames.
  721. *
  722. * Revision 1.41  2003/04/03 17:45:25  ucko
  723. * Switch to new (differently buggy ;-)) flat-file generator.
  724. * Drop s_SplitString, as NStr::Tokenize does the same thing.
  725. *
  726. * Revision 1.40  2003/03/10 18:48:48  kuznets
  727. * iterate->ITERATE
  728. *
  729. * Revision 1.39  2002/11/13 20:14:51  ucko
  730. * Rework to take advantage of new ID1 and Entrez2 client classes
  731. * generated by datatool
  732. *
  733. * Revision 1.38  2002/08/27 21:41:53  ucko
  734. * Use CFastaOstream rather than custom code.
  735. * Fix spelling of NONEXISTENT.
  736. *
  737. * Revision 1.37  2002/08/14 20:28:02  ucko
  738. * Fix behavior when given a list of IDs.
  739. *
  740. * Revision 1.36  2002/07/11 14:23:48  gouriano
  741. * exceptions replaced by CNcbiException-type ones
  742. *
  743. * Revision 1.35  2002/06/28 17:25:53  grichenk
  744. * +Error message if a GI was not found
  745. *
  746. * Revision 1.34  2002/06/12 16:51:55  lavr
  747. * Take advantage of CONNECT_Init()
  748. *
  749. * Revision 1.33  2002/06/07 16:11:40  ucko
  750. * GetTitle() is now in sequence::.
  751. *
  752. * Revision 1.32  2002/06/06 23:46:24  vakatov
  753. * Use GetTitle() from <objects/util/sequence.hpp>
  754. *
  755. * Revision 1.31  2002/05/06 16:13:46  ucko
  756. * Merge in Andrei Gourianov's changes to use the new OM (thanks!)
  757. * Remove some dead code.
  758. * Don't automatically turn on tracing, even when building with _DEBUG;
  759. * it is always possible to set DIAG_TRACE in the environment instead.
  760. * Move CVS log to end.
  761. *
  762. *
  763. * *** These four entries are from src/app/id1_fetch1/id1_fetch1.cpp ***
  764. * Revision 1.5  2002/05/06 03:31:52  vakatov
  765. * OM/OM1 renaming
  766. *
  767. * Revision 1.4  2002/05/03 21:28:21  ucko
  768. * Introduce T(Signed)SeqPos.
  769. *
  770. * Revision 1.3  2002/04/10 21:02:21  gouriano
  771. * moved construction of iterators out of "for" loop initialization:
  772. * Sun Workshop compiler does not call destructors of such objects
  773. * in case we use break to exit the loop
  774. *
  775. * Revision 1.2  2002/04/10 16:07:30  gouriano
  776. * corrected data output in different formats
  777. *
  778. * Revision 1.1  2002/04/04 16:31:36  gouriano
  779. * id1_fetch1 - modified version of id1_fetch, which uses objmgr1
  780. *
  781. * Revision 1.29  2002/03/11 21:52:05  lavr
  782. * Print complete debug and trace information when compiled with _DEBUG
  783. *
  784. * Revision 1.28  2002/01/16 22:14:00  ucko
  785. * Removed CRef<> argument from choice variant setter, updated sources to
  786. * use references instead of CRef<>s
  787. *
  788. * Revision 1.27  2001/12/07 21:15:16  ucko
  789. * Remove duplicate includes.
  790. *
  791. * Revision 1.26  2001/12/07 21:11:01  grichenk
  792. * Fixed includes to work with the updated datatool
  793. *
  794. * Revision 1.25  2001/12/07 21:03:47  ucko
  795. * Add #includes required by new datatool version.
  796. *
  797. * Revision 1.24  2001/11/16 16:06:45  ucko
  798. * Handle new Entrez docsum interface properly.
  799. *
  800. * Revision 1.23  2001/10/26 14:49:16  ucko
  801. * Restructured to avoid CRefs as arguments.
  802. *
  803. * Revision 1.22  2001/10/23 20:05:12  ucko
  804. * Request ASCII from CSeq_vector.
  805. *
  806. * Revision 1.21  2001/10/17 21:17:53  ucko
  807. * Seq_vector now properly starts from zero rather than one; adjust code
  808. * that uses it accordingly.
  809. *
  810. * Revision 1.20  2001/10/12 19:32:58  ucko
  811. * move BREAK to a central location; move CBioseq::GetTitle to object manager
  812. *
  813. * Revision 1.19  2001/10/12 15:34:01  ucko
  814. * Edit in-source version of CVS log to avoid end-of-comment marker.  (Oops.)
  815. *
  816. * Revision 1.18  2001/10/12 15:29:08  ucko
  817. * Drop {src,include}/objects/util/asciiseqdata.* in favor of CSeq_vector.
  818. * Rewrite GenBank output code to take fuller advantage of the object manager.
  819. *
  820. * Revision 1.17  2001/10/10 16:02:53  ucko
  821. * Clean up includes.
  822. *
  823. * Revision 1.16  2001/10/04 19:11:56  ucko
  824. * Centralize (rudimentary) code to get a sequence's title.
  825. *
  826. * Revision 1.15  2001/09/25 20:31:13  ucko
  827. * Work around bug in Workshop's handling of declarations in for-loop
  828. * initializers.
  829. *
  830. * Revision 1.14  2001/09/25 20:12:02  ucko
  831. * More cleanups from Denis.
  832. * Put utility code in the objects namespace.
  833. * Moved utility code to {src,include}/objects/util (to become libxobjutil).
  834. * Moved static members of CGenbankWriter to above their first use.
  835. *
  836. * Revision 1.13  2001/09/25 13:26:36  lavr
  837. * CConn_ServiceStream() - arguments adjusted
  838. *
  839. * Revision 1.12  2001/09/24 03:22:09  vakatov
  840. * Un-#include <cstdlib> and <cctype> which break IRIX/MIPSpro compilation and
  841. * apparently are not needed after all
  842. *
  843. * Revision 1.11  2001/09/21 22:38:59  ucko
  844. * Cope with new Entrez interface; fix MSVC build.
  845. *
  846. * Revision 1.10  2001/09/05 16:25:56  ucko
  847. * Adapted to latest revision of object manager interface.
  848. *
  849. * Revision 1.9  2001/09/05 14:44:37  ucko
  850. * Use NStr::IntToString instead of Stringify.
  851. *
  852. * Revision 1.8  2001/09/04 16:20:53  ucko
  853. * Dramatically fleshed out id1_fetch
  854. *
  855. * Revision 1.7  2001/07/19 19:40:20  lavr
  856. * Typo fixed
  857. *
  858. * Revision 1.6  2001/06/01 18:43:44  vakatov
  859. * Comment out excessive debug/trace printout
  860. *
  861. * Revision 1.5  2001/05/16 17:55:37  grichenk
  862. * Redesigned support for non-blocking stream read operations
  863. *
  864. * Revision 1.4  2001/05/11 20:41:16  grichenk
  865. * Added support for non-blocking stream reading
  866. *
  867. * Revision 1.3  2001/05/11 14:06:45  grichenk
  868. * The first working revision
  869. *
  870. * Revision 1.2  2001/04/13 14:09:34  grichenk
  871. * Next debug version, still not working
  872. *
  873. * Revision 1.1  2001/04/10 22:39:04  vakatov
  874. * Initial revision.
  875. * Compiles and links, but apparently is not working yet.
  876. *
  877. * ===========================================================================
  878. */