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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: user_feature_dload.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:42:52  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: user_feature_dload.cpp,v 1000.2 2004/06/01 19:42:52 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.  * Authors:  Josh Cherry
  35.  *
  36.  * File Description:  Data loader for user features in tabular form
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <objtools/data_loaders/table/user_feature_dload.hpp>
  41. #include <sqlite/sqlite.hpp>
  42. #include <objects/general/User_object.hpp>
  43. #include <objects/general/User_field.hpp>
  44. #include <objects/general/Object_id.hpp>
  45. #include <objects/seqfeat/Seq_feat.hpp>
  46. #include <objects/seqloc/Seq_loc.hpp>
  47. #include <objects/seqloc/Seq_id.hpp>
  48. #include <objects/seqloc/Seq_interval.hpp>
  49. #include <objects/seqset/Seq_entry.hpp>
  50. #include <objects/seqset/Bioseq_set.hpp>
  51. #include <objmgr/scope.hpp>
  52. #include <objmgr/impl/data_source.hpp>
  53. #include <objmgr/impl/synonyms.hpp>
  54. #include <objmgr/impl/handle_range_map.hpp>
  55. #include <serial/serial.hpp>
  56. #include <serial/objostr.hpp>
  57. BEGIN_NCBI_SCOPE
  58. USING_SCOPE(objects);
  59. bool CUsrFeatDataLoader::SIdHandleByContent::operator()
  60.     (const CSeq_id_Handle& h1, const CSeq_id_Handle& h2) const
  61. {
  62.     CConstRef<CSeq_id> id1 = h1.GetSeqId();
  63.     CConstRef<CSeq_id> id2 = h2.GetSeqId();
  64.     return (*id1 < *id2);
  65. }
  66. CUsrFeatDataLoader::CUsrFeatDataLoader(const string& input_file,
  67.                                        const string& temp_file,
  68.                                        bool delete_file,
  69.                                        EOffset offset,
  70.                                        const string& type,
  71.                                        const CSeq_id* given_id)
  72.     : CDataLoader(input_file), m_Offset(offset), m_Type(type)
  73. {
  74.     //
  75.     // create our SQLite DB
  76.     //
  77.     m_Table.Reset(new CSQLiteTable(input_file, temp_file, delete_file));
  78.     //
  79.     // now, store some precalculated info about our table
  80.     //
  81.     {{
  82.         // extract the column names
  83.         list<string> cols;
  84.         m_Table->GetColumnTitles(cols);
  85.         m_Cols.reserve(cols.size());
  86.         std::copy(cols.begin(), cols.end(), back_inserter(m_Cols));
  87.     }}
  88.     // determine our column mapping
  89.     int i = 0;
  90.     m_ColAssign.resize(m_Cols.size(), eUnknown);
  91.     fill(m_ColIdx, m_ColIdx + eMaxKnownCol, -1);
  92.     ITERATE(vector<string>, iter, m_Cols) {
  93.         string str(*iter);
  94.         NStr::ToLower(str);
  95.         if (str == "contig"  ||
  96.             str == "contig_accession"  ||
  97.             str == "accession" ||
  98.             str == "id") {
  99.             m_ColAssign[i] = eAccession;
  100.             m_ColIdx[eAccession] = i;
  101.         } else if (str == "from") {
  102.             m_ColAssign[i] = eFrom;
  103.             m_ColIdx[eFrom] = i;
  104.         } else if (str == "to") {
  105.             m_ColAssign[i] = eTo;
  106.             m_ColIdx[eTo] = i;
  107.         } else if (str == "type") {
  108.             m_ColAssign[i] = eType;
  109.             m_ColIdx[eType] = i;
  110.         } else if (str == "strand"  ||
  111.                    str == "orientation") {
  112.             m_ColAssign[i] = eStrand;
  113.             m_ColIdx[eStrand] = i;
  114.         }
  115.         ++i;
  116.     }
  117.     if (given_id) {
  118.         m_SeqId.Reset(given_id);
  119.     }
  120.     if (!m_SeqId && m_ColIdx[eAccession] == -1) {
  121.         LOG_POST(Info << "CUsrFeatDataLoader: no id column in file, "
  122.                  "and no id given as parameter");
  123.         throw runtime_error("no id column in file, "
  124.                             "and no id given as parameter");
  125.     }
  126.     CSQLite& sqlite = m_Table->SetDB();
  127.     if (!m_SeqId) {
  128.         string acc_col = "col" + NStr::IntToString(m_ColIdx[eAccession]);
  129.         // create an index on accession
  130.         try {
  131.             sqlite.Execute("create index IDX_accession "
  132.                            "on TableData (" + acc_col + ")");
  133.         }
  134.         catch (...) {
  135.             // index already exists - ignored
  136.         }
  137.         // extract a list of the accessions we have
  138.         CRef<CSQLiteQuery> q
  139.             (sqlite.Compile("select distinct " + acc_col +
  140.                             " from TableData order by " + acc_col));
  141.         int count;
  142.         const char** data = NULL;
  143.         const char** cols = NULL;
  144.         while (q->NextRow(count, data, cols)) {
  145.             CRef<CSeq_id> id(new CSeq_id(data[0]));
  146.             if (id->Which() == CSeq_id::e_not_set) {
  147.                 LOG_POST(Error << "failed to index id = " << data[0]);
  148.                 continue;
  149.             }
  150.             CSeq_id_Handle handle = CSeq_id_Handle::GetHandle(*id);
  151.             m_Ids.insert(TIdMap::value_type(handle, data[0]));
  152.             _TRACE("  id = " << data[0]);
  153.         }
  154.         LOG_POST(Info << "CUsrFeatDataLoader: " 
  155.                  << m_Ids.size() << " distinct ids");
  156.     } else {
  157.         LOG_POST(Info << "CUsrFeatDataLoader: using single "
  158.                  "specified id");
  159.     }
  160. }
  161. // Request from a datasource using handles and ranges instead of seq-loc
  162. // The TSEs loaded in this call will be added to the tse_set.
  163. void CUsrFeatDataLoader::GetRecords(const CSeq_id_Handle& idh,
  164.                                     EChoice choice)
  165. {
  166.     //
  167.     // find out if we've already loaded annotations for this seq-id
  168.     //
  169.     TEntries::iterator iter = m_Entries.find(idh);
  170.     if (iter != m_Entries.end()) {
  171.         return;
  172.     }
  173.     CRef<CSeq_annot> annot = GetAnnot(idh);
  174.     if (!annot) {
  175.         return;
  176.     }
  177.     CRef<CSeq_entry> entry;
  178.     // we then add the object to the data loader
  179.     // we need to create a dummy TSE for it first
  180.     entry.Reset(new CSeq_entry());
  181.     entry->SetSet().SetSeq_set();
  182.     entry->SetSet().SetAnnot().push_back(annot);
  183.     GetDataSource()->AddTSE(*entry);
  184.     
  185.     _TRACE("CUsrFeatDataLoader(): loaded "
  186.            << annot->GetData().GetFtable().size()
  187.            << " features for " << idh.AsString());
  188.     
  189.     // we always save an entry here.  If the entry is empty,
  190.     // we have no information about this sequence, but we at
  191.     // least don't need to repeat an expensive search
  192.     m_Entries[idh] = entry;
  193. }
  194. CRef<CSeq_annot> CUsrFeatDataLoader::GetAnnot(const CSeq_id_Handle& idh)
  195. {
  196.     CRef<CSeq_annot> annot;
  197.     CSQLiteTable::TIterator row_iter;
  198.     if (!m_SeqId) {
  199.         //
  200.         // find out if this ID is in our list of ids
  201.         //
  202.         pair<TIdMap::iterator, TIdMap::iterator> id_iter
  203.             = m_Ids.equal_range(idh);
  204.         if (id_iter.first == id_iter.second) {
  205.             return annot;  // null CRef
  206.         }
  207.         // select just the rows with that match the id
  208.         string acc_col = "col" + NStr::IntToString(m_ColIdx[eAccession]);
  209.         string sql("select * from TableData where " + acc_col +
  210.                    " in (");
  211.         string tmp;
  212.         for ( ;  id_iter.first != id_iter.second;  ++id_iter.first) {
  213.             TIdMap::iterator iter = id_iter.first;
  214.             
  215.             if ( !tmp.empty() ) {
  216.                 tmp += ", ";
  217.             }
  218.             tmp += "'" + iter->second + "'";
  219.         }
  220.         sql += tmp + ")";
  221.         row_iter = m_Table->Begin(sql);
  222.         
  223.     } else {
  224.         // check that this is the right id
  225.         if (!idh.GetSeqId()->Match(*m_SeqId)) {
  226.             return annot;  // null CRef
  227.         }
  228.         // select 'em all
  229.         row_iter = m_Table->Begin("select * from TableData");
  230.     }
  231.     annot.Reset(new CSeq_annot());
  232.     vector<string> data;
  233.     for ( ;  *row_iter;  ++(*row_iter)) {
  234.         list<string> temp;
  235.         (*row_iter).GetRow(temp);
  236.         data.resize(temp.size());
  237.         std::copy(temp.begin(), temp.end(), data.begin());
  238.         // create a new feature
  239.         CRef<CSeq_feat> feat(new CSeq_feat());
  240.         CSeq_loc& loc = feat->SetLocation();
  241.         loc.SetInt().SetId().Assign(*idh.GetSeqId());
  242.         CUser_object& user = feat->SetData().SetUser();
  243.         // fill in our columns
  244.         TSeqPos from;
  245.         TSeqPos to;
  246.         string strand_str;
  247.         for (unsigned int i = 0;  i < data.size();  ++i) {
  248.             switch (m_ColAssign[i]) {
  249.             case eAccession:
  250.                 // already handled as ID...
  251.                 break;
  252.             case eStrand:
  253.                 strand_str = NStr::ToLower(data[i]);
  254.                 if (strand_str == "+" || strand_str == "plus" ||
  255.                     strand_str == "positive" || strand_str == "forward") {
  256.                     loc.SetInt().SetStrand(eNa_strand_plus);
  257.                 } else if (strand_str == "-" || strand_str == "minus" ||
  258.                            strand_str == "negative" || 
  259.                            strand_str == "reverse") {
  260.                     loc.SetInt().SetStrand(eNa_strand_minus);
  261.                 } else if (strand_str == "b" || strand_str == "+/-" ||
  262.                            strand_str == "both") {
  263.                     loc.SetInt().SetStrand(eNa_strand_both);
  264.                 } else {
  265.                     throw runtime_error(string("Invalid strand designation: ")
  266.                                         + data[i]);
  267.                 }
  268.                 break;
  269.             case eFrom:
  270.                 from = NStr::StringToInt(data[i]);
  271.                 break;
  272.             case eTo:
  273.                 to = NStr::StringToInt(data[i]);
  274.                 break;
  275.             case eType:
  276.                 user.SetType().SetStr(data[i]);
  277.                 break;
  278.             case eUnknown:
  279.             default:
  280.                 // add a user field, unless column title
  281.                 // starts with '.'
  282.                 if (!NStr::StartsWith(m_Cols[i], ".")) {
  283.                     user.AddField(m_Cols[i], data[i]);
  284.                 }
  285.                 break;
  286.             }
  287.         }
  288.         loc.SetInt().SetFrom(from - m_Offset);
  289.         loc.SetInt().SetTo  (to - m_Offset);
  290.         if (!m_Type.empty() || m_ColIdx[eType] == -1) {
  291.             user.SetType().SetStr(m_Type);
  292.         }
  293.         annot->SetData().SetFtable().push_back(feat);
  294.     }
  295.     return annot;
  296. }
  297. END_NCBI_SCOPE
  298. /*
  299.  * ===========================================================================
  300.  * $Log: user_feature_dload.cpp,v $
  301.  * Revision 1000.2  2004/06/01 19:42:52  gouriano
  302.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3
  303.  *
  304.  * Revision 1.3  2004/05/21 21:42:53  gorelenk
  305.  * Added PCH ncbi_pch.hpp
  306.  *
  307.  * Revision 1.2  2003/11/28 13:41:10  dicuccio
  308.  * Fixed to match new API in CDataLoader
  309.  *
  310.  * Revision 1.1  2003/11/14 19:09:18  jcherry
  311.  * Initial version
  312.  *
  313.  * ===========================================================================
  314.  */