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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: seqtitle.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:25:27  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.37
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: seqtitle.cpp,v 1000.3 2004/06/01 19:25:27 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:  Aaron Ucko
  35. *
  36. * File Description:
  37. *   Obtains or constructs a sequence's title.  (Corresponds to
  38. *   CreateDefLine in the C toolkit.)
  39. */
  40. #include <ncbi_pch.hpp>
  41. #include <serial/iterator.hpp>
  42. #include <objects/biblio/Id_pat.hpp>
  43. #include <objects/general/Dbtag.hpp>
  44. #include <objects/general/Object_id.hpp>
  45. #include <objects/seq/Bioseq.hpp>
  46. #include <objects/seq/Delta_ext.hpp>
  47. #include <objects/seq/Delta_seq.hpp>
  48. #include <objects/seq/MolInfo.hpp>
  49. #include <objects/seq/Seg_ext.hpp>
  50. #include <objects/seq/Seq_descr.hpp>
  51. #include <objects/seq/Seq_ext.hpp>
  52. #include <objects/seq/Seq_inst.hpp>
  53. #include <objects/seq/Seq_literal.hpp>
  54. #include <objects/seqblock/EMBL_block.hpp>
  55. #include <objects/seqblock/GB_block.hpp>
  56. #include <objects/seqblock/PDB_block.hpp>
  57. #include <objects/seqfeat/BioSource.hpp>
  58. #include <objects/seqfeat/Gene_ref.hpp>
  59. #include <objects/seqfeat/OrgMod.hpp>
  60. #include <objects/seqfeat/OrgName.hpp>
  61. #include <objects/seqfeat/Org_ref.hpp>
  62. #include <objects/seqfeat/Prot_ref.hpp>
  63. #include <objects/seqfeat/Seq_feat.hpp>
  64. #include <objects/seqfeat/SubSource.hpp>
  65. #include <objects/seqloc/PDB_seq_id.hpp>
  66. #include <objects/seqloc/PDB_seq_id.hpp>
  67. #include <objects/seqloc/Patent_seq_id.hpp>
  68. #include <objects/seqloc/Seq_id.hpp>
  69. #include <objects/seqloc/Seq_loc.hpp>
  70. #include <objects/seqloc/Seq_loc_mix.hpp>
  71. #include <objects/seqloc/Textseq_id.hpp>
  72. #include <objects/seqset/Seq_entry.hpp>
  73. #include <objmgr/scope.hpp>
  74. #include <objmgr/seqdesc_ci.hpp>
  75. #include <objmgr/feat_ci.hpp>
  76. #include <objmgr/util/feature.hpp>
  77. #include <objmgr/util/sequence.hpp>
  78. BEGIN_NCBI_SCOPE
  79. BEGIN_SCOPE(objects)
  80. BEGIN_SCOPE(sequence)
  81. static string s_TitleFromBioSource (const CBioSource&    source,
  82.                                     const string&        suffix = kEmptyStr);
  83. static string s_TitleFromChromosome(const CBioSource&    source,
  84.                                     const CMolInfo&      mol_info);
  85. static string s_TitleFromProtein   (const CBioseq_Handle& handle,
  86.                                           CScope&        scope,
  87.                                           string&        organism);
  88. static string s_TitleFromSegment   (const CBioseq_Handle& handle,
  89.                                           CScope&        scope);
  90.                                           
  91. string GetTitle(const CBioseq_Handle& hnd, TGetTitleFlags flags)
  92. {
  93.     string                    prefix, title, suffix;
  94.     string                    organism;
  95.     CBioseq_Handle::TBioseqCore core        = hnd.GetBioseqCore();
  96.     CConstRef<CTextseq_id>    tsid(NULL);
  97.     CConstRef<CPDB_seq_id>    pdb_id(NULL);
  98.     CConstRef<CPatent_seq_id> pat_id(NULL);
  99.     CConstRef<CDbtag>         general_id(NULL);
  100.     CConstRef<CBioSource>     source(NULL);
  101.     CConstRef<CMolInfo>       mol_info(NULL);
  102.     bool                      third_party = false;
  103.     bool                      is_nc       = false;
  104.     bool                      is_nm       = false;
  105.     bool                      is_nr       = false;
  106.     bool                      wgs_master  = false;
  107.     CMolInfo::TTech           tech        = CMolInfo::eTech_unknown;
  108.     bool                      htg_tech    = false;
  109.     bool                      use_biosrc  = false;
  110.     ITERATE (CBioseq::TId, id, core->GetId()) {
  111.         if ( !tsid ) {
  112.             tsid = (*id)->GetTextseq_Id();
  113.         }
  114.         switch ((*id)->Which()) {
  115.         case CSeq_id::e_Other:
  116.         case CSeq_id::e_Genbank:
  117.         case CSeq_id::e_Embl:
  118.         case CSeq_id::e_Ddbj:
  119.         {
  120.             const CTextseq_id& t = *(*id)->GetTextseq_Id();
  121.             if (t.IsSetAccession()) {
  122.                 const string& acc = t.GetAccession();
  123.                 CSeq_id::EAccessionInfo type = CSeq_id::IdentifyAccession(acc);
  124.                 if ((type & CSeq_id::eAcc_division_mask) == CSeq_id::eAcc_wgs
  125.                     &&  NStr::EndsWith(acc, "000000")) {
  126.                     wgs_master = true;
  127.                 } else if (type == CSeq_id::eAcc_refseq_chromosome) {
  128.                     is_nc = true;
  129.                 } else if (type == CSeq_id::eAcc_refseq_mrna) {
  130.                     is_nm = true;
  131.                 } else if (type == CSeq_id::eAcc_refseq_ncrna) {
  132.                     is_nr = true;
  133.                 }
  134.             }
  135.             break;
  136.         }
  137.         case CSeq_id::e_General:
  138.             general_id = &(*id)->GetGeneral();
  139.             break;
  140.         case CSeq_id::e_Tpg:
  141.         case CSeq_id::e_Tpe:
  142.         case CSeq_id::e_Tpd:
  143.             third_party = true;
  144.             break;
  145.         case CSeq_id::e_Pdb:
  146.             pdb_id = &(*id)->GetPdb();
  147.             break;
  148.         case CSeq_id::e_Patent:
  149.             pat_id = &(*id)->GetPatent();
  150.             break;
  151.         default:
  152.             break;
  153.         }
  154.     }
  155.     
  156.     {
  157.         CSeqdesc_CI it(hnd, CSeqdesc::e_Source);
  158.         if (it) {
  159.             source = &it->GetSource();
  160.         }
  161.     }
  162.     {
  163.         CSeqdesc_CI it(hnd, CSeqdesc::e_Molinfo);
  164.         if (it) {
  165.             mol_info = &it->GetMolinfo();
  166.             tech = mol_info->GetTech();
  167.         }
  168.     }
  169.     switch (tech) {
  170.     case CMolInfo::eTech_htgs_0:
  171.     case CMolInfo::eTech_htgs_1:
  172.     case CMolInfo::eTech_htgs_2:
  173.         // manufacture all titles for unfinished HTG sequences
  174.         flags |= fGetTitle_Reconstruct;
  175.         // fall through
  176.     case CMolInfo::eTech_htgs_3:
  177.         htg_tech = true;
  178.         // fall through
  179.     case CMolInfo::eTech_est:
  180.     case CMolInfo::eTech_sts:
  181.     case CMolInfo::eTech_survey:
  182.     case CMolInfo::eTech_wgs:
  183.         use_biosrc = true;
  184.     default:
  185.         break;
  186.     }
  187.     if (!(flags & fGetTitle_Reconstruct)) {
  188.         // Ignore parents' titles for non-PDB proteins.
  189.         if (core->GetInst().GetMol() == CSeq_inst::eMol_aa
  190.             &&  pdb_id.IsNull()) {
  191.             // Sun Workshop compiler does not call destructors of objects
  192.             // created in for-loop initializers in case we use break to exit the loop
  193.             // (08-apr-2002)
  194.             CTypeConstIterator<CSeqdesc> it = ConstBegin(*core);
  195.             for (; it;  ++it) {
  196.                 if (it->IsTitle()) {
  197.                     title = it->GetTitle();
  198.                     BREAK(it);
  199.                 }
  200.             }
  201.         } else {
  202.             {
  203.                 CSeqdesc_CI it(hnd, CSeqdesc::e_Title);
  204.                 if (it) {
  205.                     title = it->GetTitle();
  206.                 }
  207.             }
  208.         }
  209.     }
  210.     if (title.empty()  &&  use_biosrc  &&  source.NotEmpty()) {
  211.         if (tech == CMolInfo::eTech_wgs  &&  !wgs_master
  212.             &&  general_id.NotEmpty()  &&  general_id->GetTag().IsStr()) {
  213.             title = s_TitleFromBioSource(*source,
  214.                                          general_id->GetTag().GetStr());
  215.         } else {
  216.             title = s_TitleFromBioSource(*source);
  217.         }
  218.         flags &= ~fGetTitle_Organism;
  219.     }
  220.     if (title.empty()  &&  is_nc  &&  source.NotEmpty()) {
  221.         switch (mol_info->GetBiomol()) {
  222.         case CMolInfo::eBiomol_genomic:
  223.         case CMolInfo::eBiomol_other_genetic:
  224.             title = s_TitleFromChromosome(*source, *mol_info);
  225.             if (!title.empty()) {
  226.                 flags &= ~fGetTitle_Organism;
  227.             }
  228.             break;
  229.         }
  230.     } else if (title.empty()  &&  is_nm  &&  source.NotEmpty()) {
  231.         unsigned int         genes = 0, cdregions = 0, prots = 0;
  232.         CConstRef<CSeq_feat> gene(0),   cdregion(0);
  233.         for (CFeat_CI it(hnd, 0, 0, CSeqFeatData::e_not_set);
  234.              it;  ++it) {
  235.             switch (it->GetData().Which()) {
  236.             case CSeqFeatData::e_Gene:
  237.                 ++genes;
  238.                 gene.Reset(&it->GetMappedFeature());
  239.                 break;
  240.             case CSeqFeatData::e_Cdregion:
  241.                 ++cdregions;
  242.                 cdregion.Reset(&it->GetMappedFeature());
  243.                 break;
  244.             case CSeqFeatData::e_Prot:
  245.                 ++prots;
  246.                 break;
  247.             default:
  248.                 break;
  249.             }
  250.         }
  251.         if (genes == 1  &&  cdregions == 1  // &&  prots >= 1
  252.             &&  source->GetOrg().IsSetTaxname()) {
  253.             title = source->GetOrg().GetTaxname() + ' ';
  254.             feature::GetLabel(*cdregion, &title, feature::eContent,
  255.                               &hnd.GetScope());
  256.             title += " (";
  257.             feature::GetLabel(*gene, &title, feature::eContent,
  258.                               &hnd.GetScope());
  259.             title += "), mRNA";
  260.         }
  261.     } else if (title.empty()  &&  is_nr  &&  source.NotEmpty()
  262.                &&  source->GetOrg().IsSetTaxname()) {
  263.         for (CTypeConstIterator<CSeq_feat> it(hnd.GetTopLevelSeqEntry());
  264.              it;  ++it) {
  265.             if (it->GetData().IsGene()) {
  266.                 title = source->GetOrg().GetTaxname() + ' ';
  267.                 feature::GetLabel(*it, &title, feature::eContent);
  268.                 title += ", ";
  269.                 switch (mol_info->GetBiomol()) {
  270.                 case CMolInfo::eBiomol_pre_RNA: title += "precursorRNA"; break;
  271.                 case CMolInfo::eBiomol_mRNA:    title += "mRNA";         break;
  272.                 case CMolInfo::eBiomol_rRNA:    title += "rRNA";         break;
  273.                 case CMolInfo::eBiomol_tRNA:    title += "tRNA";         break;
  274.                 case CMolInfo::eBiomol_snRNA:   title += "snRNA";        break;
  275.                 case CMolInfo::eBiomol_scRNA:   title += "scRNA";        break;
  276.                 case CMolInfo::eBiomol_cRNA:    title += "cRNA";         break;
  277.                 case CMolInfo::eBiomol_snoRNA:  title += "snoRNA";       break;
  278.                 default:                        title += "miscRNA";      break;
  279.                 }
  280.                 BREAK(it);
  281.             }
  282.         }
  283.     }
  284.     // originally further down, but moved up to match the C version
  285.     while (NStr::EndsWith(title, ".")  ||  NStr::EndsWith(title, " ")) {
  286.         title.erase(title.end() - 1);
  287.     }
  288.     if (title.empty()  &&  pdb_id.NotEmpty()) {
  289.         CSeqdesc_CI it(hnd, CSeqdesc::e_Pdb);
  290.         for (;  it;  ++it) {
  291.             if ( !it->GetPdb().GetCompound().empty() ) {
  292.                 if (isprint(pdb_id->GetChain())) {
  293.                     title = string("Chain ") + (char)pdb_id->GetChain() + ", ";
  294.                 }
  295.                 title += it->GetPdb().GetCompound().front();
  296.                 BREAK(it);
  297.             }
  298.         }
  299.     }
  300.     if (title.empty()  &&  pat_id.NotEmpty()) {
  301.         title = "Sequence " + NStr::IntToString(pat_id->GetSeqid())
  302.             + " from Patent " + pat_id->GetCit().GetCountry()
  303.             + ' ' + pat_id->GetCit().GetId().GetNumber();
  304.     }
  305.     if (title.empty()  &&  core->GetInst().GetMol() == CSeq_inst::eMol_aa) {
  306.         title = s_TitleFromProtein(hnd, hnd.GetScope(), organism);
  307.         if ( !title.empty() ) {
  308.             flags |= fGetTitle_Organism;
  309.         }
  310.     }
  311.     if (title.empty()  &&  !htg_tech
  312.         &&  core->GetInst().GetRepr() == CSeq_inst::eRepr_seg) {
  313.         title = s_TitleFromSegment(hnd, hnd.GetScope());
  314.     }
  315.     if (title.empty()  &&  !htg_tech  &&  source.NotEmpty()) {
  316.         title = s_TitleFromBioSource(*source);
  317.         if (title.empty()) {
  318.             title = "No definition line found";
  319.         }
  320.     }
  321.     if (third_party  &&  !title.empty()
  322.         &&  !NStr::StartsWith(title, "TPA: ", NStr::eNocase)) {
  323.         prefix += "TPA: ";
  324.     }
  325.     switch (tech) {
  326.     case CMolInfo::eTech_htgs_0:
  327.         if (title.find("LOW-PASS") == NPOS) {
  328.             suffix = ", LOW-PASS SEQUENCE SAMPLING";
  329.         }
  330.         break;
  331.     case CMolInfo::eTech_htgs_1:
  332.     case CMolInfo::eTech_htgs_2:
  333.     {
  334.         bool is_draft  = false;
  335.         bool cancelled = false;
  336.         const CGB_block::TKeywords* keywords = 0;
  337.         for (CSeqdesc_CI gb(hnd, CSeqdesc::e_Genbank);  gb;  ++gb) {
  338.             if (gb->GetGenbank().IsSetKeywords()) {
  339.                 keywords = &gb->GetGenbank().GetKeywords();
  340.             }
  341.             BREAK(gb);
  342.         }
  343.         if ( !keywords ) {
  344.             for (CSeqdesc_CI embl(hnd, CSeqdesc::e_Embl);  embl;  ++embl) {
  345.                 if (embl->GetEmbl().IsSetKeywords()) {
  346.                     keywords = &embl->GetEmbl().GetKeywords();
  347.                 }
  348.                 BREAK(embl);
  349.             }
  350.         }
  351.         if (keywords) {
  352.             ITERATE (CGB_block::TKeywords, it, *keywords) {
  353.                 if (NStr::Compare(*it, "HTGS_DRAFT", NStr::eNocase) == 0) {
  354.                     is_draft = true;
  355.                     break;
  356.                 } else if (NStr::Compare(*it, "HTGS_CANCELLED", NStr::eNocase)
  357.                            == 0) {
  358.                     cancelled = true;
  359.                     break;
  360.                 }
  361.             }
  362.         }
  363.         if (is_draft  &&  title.find("WORKING DRAFT") == NPOS) {
  364.             suffix = ", WORKING DRAFT SEQUENCE";
  365.         } else if (!is_draft  &&  !cancelled
  366.                    &&  title.find("SEQUENCING IN") == NPOS) {
  367.             suffix = ", *** SEQUENCING IN PROGRESS ***";
  368.         }
  369.         
  370.         string un;
  371.         if (tech == CMolInfo::eTech_htgs_1) {
  372.             un = "un";
  373.         }
  374.         if (core->GetInst().GetRepr() == CSeq_inst::eRepr_delta) {
  375.             // We need the full bioseq here...
  376.             const CBioseq& seq = hnd.GetBioseq();
  377.             unsigned int pieces = 1;
  378.             ITERATE (CDelta_ext::Tdata, it,
  379.                      seq.GetInst().GetExt().GetDelta().Get()) {
  380.                 switch ((*it)->Which()) {
  381.                 case CDelta_seq::e_Loc:
  382.                     if ( (*it)->GetLoc().IsNull() ) {
  383.                         pieces++;
  384.                     }
  385.                     break;
  386.                 case CDelta_seq::e_Literal:
  387.                     if ( !(*it)->GetLiteral().IsSetSeq_data() ) {
  388.                         pieces++;
  389.                     }
  390.                     break;
  391.                 default:
  392.                     break;
  393.                 }
  394.             }
  395.             if (pieces == 1) {
  396.                 // suffix += (", 1 " + un + "ordered piece");
  397.             } else {
  398.                 suffix += (", " + NStr::IntToString(pieces)
  399.                            + ' ' + un + "ordered pieces");
  400.             }
  401.         } else {
  402.             // suffix += ", in " + un + "ordered pieces";
  403.         }
  404.         break;
  405.     }
  406.     case CMolInfo::eTech_htgs_3:
  407.         if (title.find("complete sequence") == NPOS) {
  408.             suffix = ", complete sequence";
  409.         }
  410.         break;
  411.     case CMolInfo::eTech_est:
  412.         if (title.find("mRNA sequence") == NPOS) {
  413.             suffix = ", mRNA sequence";
  414.         }
  415.         break;
  416.     case CMolInfo::eTech_sts:
  417.         if (title.find("sequence tagged site") == NPOS) {
  418.             suffix = ", sequence tagged site";
  419.         }
  420.         break;
  421.     case CMolInfo::eTech_survey:
  422.         if (title.find("genomic survey sequence") == NPOS) {
  423.             suffix = ", genomic survey sequence";
  424.         }
  425.         break;
  426.     case CMolInfo::eTech_wgs:
  427.         if (wgs_master) {
  428.             if (title.find("whole genome shotgun sequencing project") == NPOS){
  429.                 suffix = ", whole genome shotgun sequencing project";
  430.             }            
  431.         } else {
  432.             if (title.find("whole genome shotgun sequence") == NPOS) {
  433.                 suffix = ", whole genome shotgun sequence";
  434.             }
  435.         }
  436.         break;
  437.     }
  438.     if (flags & fGetTitle_Organism) {
  439.         CConstRef<COrg_ref> org;
  440.         if (source) {
  441.             org = &source->GetOrg();
  442.         } else {
  443.             CSeqdesc_CI it(hnd, CSeqdesc::e_Org);
  444.             for (;  it;  ++it) {
  445.                 org = &it->GetOrg();
  446.                 BREAK(it);
  447.             }
  448.         }
  449.         if (organism.empty()  &&  org.NotEmpty()  &&  org->IsSetTaxname()) {
  450.             organism = org->GetTaxname();
  451.         }
  452.         if ( !organism.empty()  &&  title.find(organism) == NPOS) {
  453.             suffix += " [" + organism + ']';
  454.         }
  455.     }
  456.     return prefix + title + suffix;
  457. }
  458. static string s_DescribeClones(const string& clone)
  459. {
  460.     SIZE_TYPE count = 1;
  461.     for (SIZE_TYPE pos = clone.find(';');  pos != NPOS;
  462.          pos = clone.find(';', pos + 1)) {
  463.         ++count;
  464.     }
  465.     if (count > 3) {
  466.         return ", " + NStr::IntToString(count) + " clones,";
  467.     } else {
  468.         return " clone " + clone;
  469.     }
  470. }
  471. static string s_TitleFromBioSource(const CBioSource& source,
  472.                                    const string&     suffix)
  473. {
  474.     string          name, chromosome, clone, map_, strain, sfx;
  475.     const COrg_ref& org = source.GetOrg();
  476.     if (org.IsSetTaxname()) {
  477.         name = org.GetTaxname();
  478.     }
  479.     if (source.IsSetSubtype()) {
  480.         ITERATE (CBioSource::TSubtype, it, source.GetSubtype()) {
  481.             switch ((*it)->GetSubtype()) {
  482.             case CSubSource::eSubtype_chromosome:
  483.                 chromosome = " chromosome " + (*it)->GetName();
  484.                 break;
  485.             case CSubSource::eSubtype_clone:
  486.                 clone = s_DescribeClones((*it)->GetName());
  487.                 break;
  488.             case CSubSource::eSubtype_map:
  489.                 map_ = " map " + (*it)->GetName();
  490.                 break;
  491.             }
  492.         }
  493.     }
  494.     if (org.IsSetOrgname()  &&  org.GetOrgname().IsSetMod()) {
  495.         ITERATE (COrgName::TMod, it, org.GetOrgname().GetMod()) {
  496.             if ((*it)->GetSubtype() == COrgMod::eSubtype_strain
  497.                 &&  !NStr::EndsWith(name, 
  498.                 (*it)->GetSubname(), NStr::eNocase)) {
  499.                 strain = " strain " + (*it)->GetSubname();
  500.             }
  501.         }
  502.     }
  503.     if (suffix.size() > 0) {
  504.         sfx = ' ' + suffix;
  505.     }
  506.     string title = NStr::TruncateSpaces(name + chromosome + clone + map_
  507.                                         + strain + sfx);
  508.     if (islower(title[0])) {
  509.         title[0] = toupper(title[0]);
  510.     }
  511.     return title;
  512. }
  513. static string x_TitleFromChromosome(const CBioSource& source,
  514.                                     const CMolInfo&   mol_info)
  515. {
  516.     string name, chromosome, segment, plasmid_name, orgnl;
  517.     string seq_tag, gen_tag;
  518.     bool   is_plasmid = false, is_virus = false;
  519.     if (source.GetOrg().IsSetTaxname()) {
  520.         name = source.GetOrg().GetTaxname();
  521.     } else {
  522.         return kEmptyStr;
  523.     }
  524.     string lc_name = name;
  525.     NStr::ToLower(lc_name);
  526.     if (lc_name.find("virus") != NPOS) {
  527.         is_virus = true;
  528.     }
  529.     if (source.IsSetSubtype()) {
  530.         ITERATE (CBioSource::TSubtype, it, source.GetSubtype()) {
  531.             switch ((*it)->GetSubtype()) {
  532.             case CSubSource::eSubtype_chromosome:
  533.                 chromosome = (*it)->GetName();
  534.                 break;
  535.             case CSubSource::eSubtype_segment:
  536.                 segment = (*it)->GetName();
  537.                 break;
  538.             case CSubSource::eSubtype_plasmid_name:
  539.             {
  540.                 plasmid_name = (*it)->GetName();
  541.                 string lc_plasmid = plasmid_name;
  542.                 NStr::ToLower(lc_plasmid);
  543.                 if (lc_plasmid.find("plasmid") == NPOS
  544.                     &&  lc_plasmid.find("element") == NPOS) {
  545.                     plasmid_name = "plasmid " + plasmid_name;
  546.                 }
  547.                 break;
  548.             }
  549.             }
  550.         }
  551.     }
  552.     switch (source.GetGenome()) {
  553.         // unknown, genomic
  554.     case CBioSource::eGenome_chloroplast:  orgnl = "chloroplast";   break;
  555.     case CBioSource::eGenome_chromoplast:  orgnl = "chromoplast";   break;
  556.     case CBioSource::eGenome_kinetoplast:  orgnl = "kinetoplast";   break;
  557.     case CBioSource::eGenome_mitochondrion:
  558.         orgnl = plasmid_name.empty() ? "mitochondrion" : "mitochondrial";
  559.         break;
  560.     case CBioSource::eGenome_plastid:      orgnl = "plastid";       break;
  561.     case CBioSource::eGenome_macronuclear: orgnl = "macronuclear";  break;
  562.     case CBioSource::eGenome_extrachrom:   orgnl = "extrachromosomal"; break;
  563.     case CBioSource::eGenome_plasmid:
  564.         orgnl = "plasmid";
  565.         is_plasmid = true;
  566.         break;
  567.         // transposon, insertion-seq
  568.     case CBioSource::eGenome_cyanelle:     orgnl = "cyanelle";      break;
  569.     case CBioSource::eGenome_proviral:
  570.         if (!is_virus) {
  571.             orgnl = plasmid_name.empty() ? "provirus" : "proviral";
  572.         }
  573.         break;
  574.     case CBioSource::eGenome_virion:
  575.         if (!is_virus) {
  576.             orgnl = "virion";
  577.         }
  578.         break;
  579.     case CBioSource::eGenome_nucleomorph:  orgnl = "nucleomorph";   break;
  580.     case CBioSource::eGenome_apicoplast:   orgnl = "apicoplast";    break;
  581.     case CBioSource::eGenome_leucoplast:   orgnl = "leucoplast";    break;
  582.     case CBioSource::eGenome_proplastid:   orgnl = "protoplast";    break;
  583.         // endogenous-virus
  584.     }
  585.     switch (mol_info.GetCompleteness()) {
  586.     case CMolInfo::eCompleteness_partial:
  587.     case CMolInfo::eCompleteness_no_left:
  588.     case CMolInfo::eCompleteness_no_right:
  589.     case CMolInfo::eCompleteness_no_ends:
  590.         seq_tag = ", partial sequence";
  591.         gen_tag = ", genome";
  592.         break;
  593.     default:
  594.         seq_tag = ", complete sequence";
  595.         gen_tag = ", complete genome";
  596.         break;
  597.     }
  598.     if (lc_name.find("plasmid") != NPOS) {
  599.         return name + seq_tag;        
  600.     } else if (is_plasmid) {
  601.         if (plasmid_name.empty()) {
  602.             return name + " unnamed plasmid" + seq_tag;
  603.         } else {
  604.             return name + ' ' + plasmid_name + seq_tag;
  605.         }
  606.     } else if ( !plasmid_name.empty() ) {
  607.         if (orgnl.empty()) {
  608.             return name + ' ' + plasmid_name + seq_tag;
  609.         } else {
  610.             return name + ' ' + orgnl + ' ' + plasmid_name + seq_tag;
  611.         }
  612.     } else if ( !orgnl.empty() ) {
  613.         if ( chromosome.empty() ) {
  614.             return name + ' ' + orgnl + gen_tag;
  615.         } else {
  616.             return name + ' ' + orgnl + " chromosome " + chromosome + seq_tag;
  617.         }
  618.     } else if ( !segment.empty() ) {
  619.         if (segment.find("DNA") == NPOS  &&  segment.find("RNA") == NPOS
  620.             &&  segment.find("segment") == NPOS
  621.             &&  segment.find("Segment") == NPOS) {
  622.             return name + " segment " + segment + seq_tag;
  623.         } else {
  624.             return name + ' ' + segment + seq_tag;
  625.         }
  626.     } else if ( !chromosome.empty() ) {
  627.         return name + " chromosome " + chromosome + seq_tag;
  628.     } else {
  629.         return name + gen_tag;
  630.     }
  631. }
  632. static string s_TitleFromChromosome(const CBioSource& source,
  633.                                     const CMolInfo&   mol_info)
  634. {
  635.     string result = x_TitleFromChromosome(source, mol_info);
  636.     result = NStr::Replace(result, "Plasmid", "plasmid");
  637.     result = NStr::Replace(result, "Element", "element");
  638.     if (!result.empty()) {
  639.         result[0] = toupper(result[0]);
  640.     }
  641.     return result;
  642. }
  643. static CConstRef<CSeq_feat> s_FindLongestFeature(const CSeq_loc& location,
  644.                                                  CScope& scope,
  645.                                                  CSeqFeatData::E_Choice type,
  646.                                                  CFeat_CI::EFeat_Location lt
  647.                                                    = CFeat_CI::e_Location)
  648. {
  649.     CConstRef<CSeq_feat> result;
  650.     TSeqPos best_length = 0;
  651.     CFeat_CI it(scope, location, type, SAnnotSelector::eOverlap_Intervals,
  652.                 SAnnotSelector::eResolve_TSE, lt);
  653.     for (;  it;  ++it) {
  654.         if (it->GetLocation().IsWhole()) {
  655.             // kludge; length only works on a Seq-loc of type "whole"
  656.             // if its Seq-id points to an object manager, which may not
  657.             // be the case here.
  658.             result = &it->GetMappedFeature();
  659.             BREAK(it);
  660.         } else if (GetLength(it->GetLocation(), &scope) > best_length) {
  661.             best_length = GetLength(it->GetLocation(), &scope);
  662.             result = &it->GetMappedFeature();
  663.         }
  664.     }
  665.     return result;
  666. }
  667. static string s_TitleFromProtein(const CBioseq_Handle& handle, CScope& scope,
  668.                                  string& organism)
  669. {
  670.     CConstRef<CProt_ref> prot;
  671.     CConstRef<CSeq_loc>  cds_loc;
  672.     CConstRef<CGene_ref> gene;
  673.     CBioseq_Handle::TBioseqCore  core = handle.GetBioseqCore();
  674.     string               result;
  675.     CSeq_loc everywhere;
  676.     everywhere.SetWhole().Assign(*core->GetId().front());
  677.     {{
  678.         CConstRef<CSeq_feat> prot_feat
  679.             = s_FindLongestFeature(everywhere, scope, CSeqFeatData::e_Prot);
  680.         if (prot_feat) {
  681.             prot = &prot_feat->GetData().GetProt();
  682.         }
  683.     }}
  684.     {{
  685.         CConstRef<CSeq_feat> cds_feat
  686.             = s_FindLongestFeature(everywhere, scope, CSeqFeatData::e_Cdregion,
  687.                                    CFeat_CI::e_Product);
  688.         if (cds_feat) {
  689.             cds_loc = &cds_feat->GetLocation();
  690.         }
  691.     }}
  692.     if (cds_loc) {
  693.         CConstRef<CSeq_feat> gene_feat
  694.             = s_FindLongestFeature(*cds_loc, scope, CSeqFeatData::e_Gene);
  695.         if (gene_feat) {
  696.             gene = &gene_feat->GetData().GetGene();
  697.         }
  698.     }
  699.     if (prot.NotEmpty()  &&  prot->IsSetName()  &&  !prot->GetName().empty()) {
  700.         bool first = true;
  701.         ITERATE (CProt_ref::TName, it, prot->GetName()) {
  702.             if (!first) {
  703.                 result += "; ";
  704.             }
  705.             result += *it;
  706.             first = false;
  707.         }
  708.         if (NStr::CompareNocase(result, "hypothetical protein") == 0) {
  709.             // XXX - gene_feat might not always be exactly what we want
  710.             if (bool(gene) && gene->IsSetLocus_tag()) {
  711.                 result += ' ' + gene->GetLocus_tag();
  712.             }
  713.         }
  714.     } else if (prot.NotEmpty()  &&  prot->IsSetDesc()
  715.                &&  !prot->GetDesc().empty()) {
  716.         result = prot->GetDesc();
  717.     } else if (prot.NotEmpty()  &&  prot->IsSetActivity()
  718.                &&  !prot->GetActivity().empty()) {
  719.         result = prot->GetActivity().front();
  720.     } else if (gene) {
  721.         string gene_name;
  722.         if (gene->IsSetLocus()  &&  !gene->GetLocus().empty()) {
  723.             gene_name = gene->GetLocus();
  724.         } else if (gene->IsSetSyn()  &&  !gene->GetSyn().empty()) {
  725.             gene_name = *gene->GetSyn().begin();
  726.         } else if (gene->IsSetDesc()  &&  !gene->GetDesc().empty()) {
  727.             gene_name = gene->GetDesc();
  728.         }
  729.         if ( !gene_name.empty() ) {
  730.             result = gene_name + " gene product";
  731.         }
  732.     } else {
  733.         result = "unnamed protein product";
  734.     }
  735.     {{ // Find organism name 
  736.         CConstRef<COrg_ref> org;
  737.         if (core->CanGetDescr()) {
  738.             // Don't go up(!)
  739.             ITERATE(CSeq_descr::Tdata, it, core->GetDescr().Get()) {
  740.                 if ((*it)->IsSource()) {
  741.                     org = &(*it)->GetSource().GetOrg();
  742.                     break;
  743.                 }
  744.             }
  745.         }
  746.         if (org.Empty()  &&  cds_loc.NotEmpty()) {
  747.             for (CFeat_CI it(scope, *cds_loc, CSeqFeatData::e_Biosrc);
  748.                  it;  ++it) {
  749.                 org = &it->GetData().GetBiosrc().GetOrg();
  750.                 BREAK(it);
  751.             }
  752.         }
  753.         if (org.NotEmpty()  &&  org->IsSetTaxname()) {
  754.             organism = org->GetTaxname();
  755.         }
  756.     }}
  757.     return result;
  758. }
  759. static string s_TitleFromSegment(const CBioseq_Handle& handle, CScope& scope)
  760. {
  761.     string              organism, product, locus, strain, clone, isolate;
  762.     string              completeness = "complete";
  763.     bool                cds_found = false;
  764.     CBioseq_Handle::TBioseqCore core = handle.GetBioseqCore();
  765.     CSeq_loc everywhere;
  766.     everywhere.SetMix().Set() = core->GetInst().GetExt().GetSeg();
  767.     {
  768.         CSeqdesc_CI it(handle, CSeqdesc::e_Source);
  769.         const CBioSource& src = it->GetSource();
  770.         for (;  it;  ++it) {
  771.             const COrg_ref& org = src.GetOrg();
  772.             if (org.IsSetTaxname()) {
  773.                 organism = org.GetTaxname();
  774.                 if (org.IsSetOrgname()) {
  775.                     const COrgName& orgname = org.GetOrgname();
  776.                     if (orgname.IsSetMod()) {
  777.                         ITERATE (COrgName::TMod, mod, orgname.GetMod()) {
  778.                             COrgMod::TSubtype subtype = (*mod)->GetSubtype();
  779.                             const string&     subname = (*mod)->GetSubname();
  780.                             if (subtype == COrgMod::eSubtype_strain) {
  781.                                 if ( !NStr::EndsWith(organism, subname) ) {
  782.                                     strain = subname;
  783.                                 }
  784.                                 break;
  785.                             } else if (subtype == COrgMod::eSubtype_isolate) {
  786.                                 isolate = subname;
  787.                                 break;
  788.                             }
  789.                         }
  790.                     }
  791.                 }
  792.             }
  793.             if (src.IsSetSubtype()) {
  794.                 ITERATE (CBioSource::TSubtype, ssrc, src.GetSubtype()) {
  795.                     if ((*ssrc)->GetSubtype() == CSubSource::eSubtype_clone) {
  796.                         clone = s_DescribeClones((*ssrc)->GetName());
  797.                     }
  798.                 }
  799.             }
  800.             BREAK(it);
  801.         }
  802.     }
  803.     if (organism.empty()) {
  804.         organism = "Unknown";
  805.     }
  806.     CFeat_CI it(scope, everywhere, CSeqFeatData::e_Cdregion);
  807.     for (; it;  ++it) {
  808.         cds_found = true;
  809.         if ( !it->IsSetProduct() ) {
  810.             continue;
  811.         }
  812.         const CSeq_loc&      product_loc = it->GetProduct();
  813.         if (it->IsSetPartial()) {
  814.             completeness = "partial";
  815.         }
  816.         CConstRef<CSeq_feat> prot_feat
  817.             = s_FindLongestFeature(product_loc, scope, CSeqFeatData::e_Prot);
  818.         if (product.empty()  &&  prot_feat.NotEmpty()
  819.             &&  prot_feat->GetData().GetProt().IsSetName()) {
  820.             product = *prot_feat->GetData().GetProt().GetName().begin();
  821.         }
  822.         
  823.         CConstRef<CSeq_feat> gene_feat
  824.             = s_FindLongestFeature(it->GetLocation(), scope,
  825.                                    CSeqFeatData::e_Gene);
  826.         if (locus.empty()  &&  gene_feat.NotEmpty()) {
  827.             if (gene_feat->GetData().GetGene().IsSetLocus()) {
  828.                 locus = gene_feat->GetData().GetGene().GetLocus();
  829.             } else if (gene_feat->GetData().GetGene().IsSetSyn()) {
  830.                 locus = *gene_feat->GetData().GetGene().GetSyn().begin();
  831.             }
  832.         }
  833.         BREAK(it);
  834.     }
  835.     string result = organism;
  836.     if ( !cds_found) {
  837.         if ( !strain.empty() ) {
  838.             result += " strain " + strain;
  839.         } else if ( !clone.empty()  &&  clone.find(" clone ") != NPOS) {
  840.             result += clone;
  841.         } else if ( !isolate.empty() ) {
  842.             result += " isolate " + isolate;
  843.         }
  844.     }
  845.     if ( !product.empty() ) {
  846.         result += ' ' + product;
  847.     }
  848.     if ( !locus.empty() ) {
  849.         result += " (" + locus + ')';
  850.     }
  851.     if ( !product.empty()  ||  !locus.empty() ) {
  852.         result += " gene, " + completeness + " cds";
  853.     }
  854.     return NStr::TruncateSpaces(result);
  855. }
  856. END_SCOPE(sequence)
  857. END_SCOPE(objects)
  858. END_NCBI_SCOPE
  859. /*
  860. * ===========================================================================
  861. * $Log: seqtitle.cpp,v $
  862. * Revision 1000.3  2004/06/01 19:25:27  gouriano
  863. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.37
  864. *
  865. * Revision 1.37  2004/05/21 21:42:14  gorelenk
  866. * Added PCH ncbi_pch.hpp
  867. *
  868. * Revision 1.36  2004/05/10 21:25:17  ucko
  869. * x_TitleFromChromosome: handle organelles with multiple chromosomes,
  870. * such as Guillardia theta nucleomorph (per C toolkit)
  871. *
  872. * Revision 1.35  2004/04/21 15:45:11  ucko
  873. * s_TitleFromSegment: collect strain/clone/isolate information from source
  874. * to use in lieu of information from a CDS (per C version, as usual).
  875. *
  876. * Revision 1.34  2004/04/07 20:02:49  ucko
  877. * x_TitleFromChromosome: spell out "extrachromosomal" per the C Toolkit.
  878. *
  879. * Revision 1.33  2004/04/05 15:56:14  grichenk
  880. * Redesigned CAnnotTypes_CI: moved all data and data collecting
  881. * functions to CAnnotDataCollector. CAnnotTypes_CI is no more
  882. * inherited from SAnnotSelector.
  883. *
  884. * Revision 1.32  2004/03/18 21:08:03  lkhotoml
  885. * Fixed letter case in title MRNA -> mRNA
  886. *
  887. * Revision 1.31  2004/01/22 20:37:20  vasilche
  888. * Added missing return statement.
  889. *
  890. * Revision 1.30  2004/01/22 19:57:33  ucko
  891. * s_TitleFromBioSource: trim trailing spaces and capitalize first letter
  892. * of title [per C Toolkit].
  893. *
  894. * Revision 1.29  2003/12/29 22:16:19  ucko
  895. * s_TitleFromProtein: consult activity if name and desc are both empty.
  896. *
  897. * Revision 1.28  2003/08/20 20:28:12  vasilche
  898. * Fixed null pointer exception when there is no gene in s_TitleFromSegment().
  899. *
  900. * Revision 1.27  2003/08/04 21:17:31  ucko
  901. * For complete chromosome title, if > 3 clones (by counting semicolons)
  902. * then just display count, not full text of clones
  903. *
  904. * Revision 1.26  2003/07/25 17:45:05  ucko
  905. * Add locus tags to hypothetical proteins' titles, per the C Toolkit.
  906. *
  907. * Revision 1.25  2003/07/24 16:36:57  ucko
  908. * As in the C version, check both GenBank and EMBL blocks for keywords
  909. * indicating HTGS sequencing progress.
  910. *
  911. * Revision 1.24  2003/06/23 15:35:03  kuznets
  912. * Fixed problem with calling CBioseq_Handle::TBioseqCore::GetDescr()
  913. * for descriptionless protein molecules (can come from hand made fasta files)
  914. * Added CanGetDescr() guard call.
  915. *
  916. * Revision 1.23  2003/06/02 16:06:39  dicuccio
  917. * Rearranged src/objects/ subtree.  This includes the following shifts:
  918. *     - src/objects/asn2asn --> arc/app/asn2asn
  919. *     - src/objects/testmedline --> src/objects/ncbimime/test
  920. *     - src/objects/objmgr --> src/objmgr
  921. *     - src/objects/util --> src/objmgr/util
  922. *     - src/objects/alnmgr --> src/objtools/alnmgr
  923. *     - src/objects/flat --> src/objtools/flat
  924. *     - src/objects/validator --> src/objtools/validator
  925. *     - src/objects/cddalignview --> src/objtools/cddalignview
  926. * In addition, libseq now includes six of the objects/seq... libs, and libmmdb
  927. * replaces the three libmmdb? libs.
  928. *
  929. * Revision 1.22  2003/05/23 14:16:00  ucko
  930. * Adjust s_TitleFromProtein's orgname-extraction code to match the C
  931. * version: only look at source descriptors directly on the protein, and
  932. * look at features rather than descriptors when falling back on nucleotides.
  933. *
  934. * Revision 1.21  2003/05/02 20:52:22  ucko
  935. * Sort #include directives to ease maintainability.
  936. * Add support for constructing NR_ titles.
  937. *
  938. * Revision 1.20  2003/04/24 16:15:58  vasilche
  939. * Added missing includes and forward class declarations.
  940. *
  941. * Revision 1.19  2003/03/26 18:57:56  ucko
  942. * Limit HTGS suffix to deltas containing actual gaps.
  943. *
  944. * Revision 1.18  2003/03/18 21:48:35  grichenk
  945. * Removed obsolete class CAnnot_CI
  946. *
  947. * Revision 1.17  2003/03/11 16:00:58  kuznets
  948. * iterate -> ITERATE
  949. *
  950. * Revision 1.16  2003/02/10 18:33:48  ucko
  951. * Don't append organism names that are already present.
  952. *
  953. * Revision 1.15  2003/02/10 15:54:01  grichenk
  954. * Use CFeat_CI->GetMappedFeature() and GetOriginalFeature()
  955. *
  956. * Revision 1.14  2003/01/30 20:01:38  ucko
  957. * Move dot-stripping code up to match the C Toolkit's (arguably broken)
  958. * behavior; extend it to handle spaces too.
  959. *
  960. * Revision 1.13  2002/12/24 16:11:29  ucko
  961. * Simplify slightly now that CFeat_CI takes a const handle.
  962. *
  963. * Revision 1.12  2002/12/20 21:47:07  ucko
  964. * Add an argument of type CFeat_CI::EFeat_Location to
  965. * s_FindLongestFeature, and use it for coding regions in s_TitleFromProtein.
  966. *
  967. * Revision 1.11  2002/12/02 16:22:14  ucko
  968. * s_TitleFromProtein: fall back to "unnamed protein product" if nothing
  969. * better is present.
  970. *
  971. * Revision 1.10  2002/11/18 19:48:44  grichenk
  972. * Removed "const" from datatool-generated setters
  973. *
  974. * Revision 1.9  2002/11/15 17:39:59  ucko
  975. * Make better titles for NM sequences
  976. *
  977. * Revision 1.8  2002/11/08 19:43:38  grichenk
  978. * CConstRef<> constructor made explicit
  979. *
  980. * Revision 1.7  2002/08/27 15:25:20  ucko
  981. * Use CSeq_id::IdentifyAccession to improve accession-based tests.
  982. *
  983. * Revision 1.6  2002/08/22 15:36:14  ucko
  984. * Fix stupid MSVC build error by adding yet another redundant .NotEmpty().
  985. *
  986. * Revision 1.5  2002/08/21 15:30:00  ucko
  987. * s_TitleFromProtein: when looking for the organism name, start with the
  988. * actual product, and deal with references to absent sequences.
  989. *
  990. * Revision 1.4  2002/06/28 18:39:20  ucko
  991. * htgs_cancelled keyword suppresses sequencing in progress phrase in defline
  992. *
  993. * Revision 1.3  2002/06/07 16:13:01  ucko
  994. * Move everything into the "sequence" namespace.
  995. *
  996. * Revision 1.2  2002/06/07 13:22:09  clausen
  997. * Removed commented out include for object_manager
  998. *
  999. * Revision 1.1  2002/06/06 18:49:45  clausen
  1000. * Initial version
  1001. *
  1002. * ***  Revisions below are from src/objects/objmgr/bioseq_handle2.cpp ***
  1003. * Revision 1.13  2002/05/14 18:36:55  ucko
  1004. * More HTG title fixes: avoid "1 ... pieces"; phase 3 = "complete sequence"
  1005. *
  1006. * Revision 1.12  2002/05/08 19:26:53  ucko
  1007. * More changes from C version: give more info about WGS sequences,
  1008. * fix count of segments to use #gaps + 1 rather than # non-gap pieces.
  1009. *
  1010. * Revision 1.11  2002/05/06 03:28:46  vakatov
  1011. * OM/OM1 renaming
  1012. *
  1013. * Revision 1.10  2002/05/03 21:28:09  ucko
  1014. * Introduce T(Signed)SeqPos.
  1015. *
  1016. * Revision 1.9  2002/04/22 19:16:13  ucko
  1017. * Fixed problem that could occur when no title descriptors were present.
  1018. *
  1019. * Revision 1.8  2002/04/10 20:59:41  gouriano
  1020. * moved construction of iterators out of "for" loop initialization:
  1021. * Sun Workshop compiler does not call destructors of such objects
  1022. * in case we use break to exit the loop
  1023. *
  1024. * Revision 1.7  2002/03/21 22:22:46  ucko
  1025. * Adjust today's fixes for new objmgr API
  1026. *
  1027. * Revision 1.6  2002/03/21 20:37:16  ucko
  1028. * Pull in full bioseq when counting HTG pieces [also in objmgr]
  1029. *
  1030. * Revision 1.5  2002/03/21 20:09:06  ucko
  1031. * Look at parents' title descriptors in some cases.
  1032. * Incorporate recent changes from the C version (CreateDefLineEx):
  1033. *  * honor wgs (whole genome shotgun) technology.
  1034. *  * don't add strain if already present in organism name.
  1035. * [Also fixed in old objmgr.]
  1036. *
  1037. * Revision 1.4  2002/03/21 17:01:20  ucko
  1038. * Fix stupid bug in s_FindLongestFeature (also fixed in old objmgr).
  1039. *
  1040. * Revision 1.3  2002/03/19 19:16:28  gouriano
  1041. * added const qualifier to GetTitle and GetSeqVector
  1042. *
  1043. * Revision 1.2  2002/02/21 19:27:05  grichenk
  1044. * Rearranged includes. Added scope history. Added searching for the
  1045. * best seq-id match in data sources and scopes. Updated tests.
  1046. *
  1047. * Revision 1.1  2002/01/28 19:44:49  gouriano
  1048. * changed the interface of BioseqHandle: two functions moved from Scope
  1049. *
  1050. *
  1051. * Revision 1.4  2002/01/23 21:59:32  grichenk
  1052. * Redesigned seq-id handles and mapper
  1053. *
  1054. * Revision 1.3  2002/01/16 18:56:28  grichenk
  1055. * Removed CRef<> argument from choice variant setter, updated sources to
  1056. * use references instead of CRef<>s
  1057. *
  1058. * Revision 1.2  2002/01/16 16:25:56  gouriano
  1059. * restructured objmgr
  1060. *
  1061. * Revision 1.1  2002/01/11 19:06:22  gouriano
  1062. * restructured objmgr
  1063. *
  1064. * ===========================================================================
  1065. */