NCBI C++ ToolKit
macro_fn_feature.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: macro_fn_feature.cpp 47378 2023-02-27 20:09:44Z asztalos $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Andrea Asztalos
27  *
28  */
29 
30 #include <ncbi_pch.hpp>
44 #include <objmgr/util/sequence.hpp>
45 #include <objmgr/seq_vector.hpp>
46 
53 
54 #include <gui/objutils/utils.hpp>
63 
68 
69 /** @addtogroup GUI_MACRO_SCRIPTS_UTIL
70  *
71  * @{
72  */
73 
75 BEGIN_SCOPE(macro)
77 
78 // All DO functions should make changes on the "Edited" object of the BioDataIterator
79 
80 ///////////////////////////////////////////////////////////////////////////////
81 /// class CMacroFunction_TrimStopFromCompleteCDS
82 /// TrimStopsFromCompleteCDS()
83 ///
84 DEFINE_MACRO_FUNCNAME(CMacroFunction_TrimStopFromCompleteCDS, "TrimStopsFromCompleteCDS");
85 
86 void CMacroFunction_TrimStopFromCompleteCDS::TheFunction()
87 {
88  CObjectInfo oi = m_DataIter->GetEditedObject();
90  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
91  if (!edit_feat || !scope)
92  return;
93 
94  // first, modify the feature: here, no modification is made to the CDS
95 
96  // then, modify the related objects (mRNA, protein, etc.):
97  CRef<CCmdComposite> cmd = TrimStopsFromCompleteCDS(*edit_feat, *scope);
98  if (cmd) {
99  m_DataIter->RunCommand(cmd, m_CmdComposite);
101  string best_id;
102  CBioseq_Handle product = scope->GetBioseqHandle(edit_feat->GetProduct());
104  log << "Removed trailing * from protein sequence " << best_id;
105  x_LogFunction(log);
106  }
107 }
108 
109 bool CMacroFunction_TrimStopFromCompleteCDS::x_ValidArguments() const
110 {
111  return (m_Args.empty());
112 }
113 
114 
115 ///////////////////////////////////////////////////////////////////////////////
116 /// class CMacroFunction_SynchronizeCDSPartials
117 /// SynchronizeCDSPartials()
118 ///
119 DEFINE_MACRO_FUNCNAME(CMacroFunction_SynchronizeCDSPartials, "SynchronizeCDSPartials")
120 
121 void CMacroFunction_SynchronizeCDSPartials::TheFunction()
122 {
123  CObjectInfo oi = m_DataIter->GetEditedObject();
125  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
126  if (!edit_feat || !scope)
127  return;
128 
129  // first, modify the feature:
130  bool change = feature::AdjustFeaturePartialFlagForLocation(*edit_feat);
131  if (change) {
132  m_DataIter->SetModified();
133  }
134 
135  // then, modify the related objects (mRNA, protein, etc.):
136  CRef<CCmdComposite> synch_cmd = GetSynchronizeProteinPartialsCommand(*scope, *edit_feat);
137  if (synch_cmd) {
138  m_DataIter->RunCommand(synch_cmd, m_CmdComposite);
139  }
140 
141  if (change || synch_cmd) {
143  log << m_DataIter->GetBestDescr() << " synchronized coding region partials";
144  x_LogFunction(log);
145  }
146 }
147 
148 bool CMacroFunction_SynchronizeCDSPartials::x_ValidArguments() const
149 {
150  return (m_Args.empty());
151 }
152 
153 ///////////////////////////////////////////////////////////////////////////////
154 /// class CMacroFunction_AdjustConsensusSpliceSites
155 /// AdjustCDSConsensusSpliceSites()
156 ///
157 DEFINE_MACRO_FUNCNAME(CMacroFunction_AdjustConsensusSpliceSites, "AdjustCDSConsensusSpliceSites");
158 
159 void CMacroFunction_AdjustConsensusSpliceSites::TheFunction()
160 {
161  CObjectInfo oi = m_DataIter->GetEditedObject();
163  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
164  if (!edit_feat || !scope)
165  return;
166 
167  CSeq_feat orig_feat;
168  orig_feat.Assign(*edit_feat);
169 
170  try {
171  CBioseq_Handle bsh = GetBioseqForSeqFeat(*edit_feat, *scope);
173  CAdjustForConsensusSpliceSite worker(*scope);
174  // first, modify the feature:
175  bool changed = worker.AdjustCDS(*edit_feat);
176  if (changed) {
177  m_DataIter->SetModified();
178 
179  // then, modify the related objects (mRNA, protein, etc.):
180  CRef<CCmdComposite> update_cmd = worker.AdjustmRNAandExonFeatures(*edit_feat, orig_feat);
181  if (update_cmd) {
182  m_DataIter->RunCommand(update_cmd, m_CmdComposite);
183  }
185  log << "Adjusted location for splice consensus: " << m_DataIter->GetBestDescr() << " became ";
186  // append new location to log
187  CSeq_loc loc;
188  loc.Assign(edit_feat->GetLocation());
189  sequence::ChangeSeqLocId(&loc, true, scope);
190  string label;
191  loc.GetLabel(&label);
192  log << label;
193  x_LogFunction(log);
194  }
195  }
196  }
197  catch (const CException& err)
198  {
199  NCBI_RETHROW2(err, CMacroDataException, CException::eUnknown, "AdjustConsensusSpliceSites failed", CConstRef<CSerialObject>(edit_feat));
200  }
201 }
202 
203 bool CMacroFunction_AdjustConsensusSpliceSites::x_ValidArguments() const
204 {
205  return (m_Args.empty());
206 }
207 
208 
209 ///////////////////////////////////////////////////////////////////////////////
210 /// class CMacroFunction_RemoveInvalidECNumbers
211 /// RemoveInvalidECNumbers();
212 ///
213 DEFINE_MACRO_FUNCNAME(CMacroFunction_RemoveInvalidECNumbers, "RemoveInvalidECNumbers");
214 
215 void CMacroFunction_RemoveInvalidECNumbers::TheFunction()
216 {
217  CObjectInfo oi = m_DataIter->GetEditedObject();
219  if (!prot_feat || prot_feat->GetData().GetSubtype() != CSeqFeatData::eSubtype_prot) {
220  return;
221  }
222 
223  CProt_ref& prot = prot_feat->SetData().SetProt();
224  if (!prot.IsSetEc() || prot.GetEc().empty())
225  return;
226 
227  typedef vector< CProt_ref::EECNumberStatus > TVecStatus;
228 
229  TVecStatus st_before;
230  ITERATE(CProt_ref::TEc, ec, prot.GetEc()) {
231  st_before.push_back(CProt_ref::GetECNumberStatus(*ec));
232  }
233 
234  prot.AutoFixEC();
235 
236  unsigned int replaced = 0;
237  TVecStatus::const_iterator it_bef = st_before.begin();
238  CProt_ref::TEc::const_iterator ec = prot.GetEc().begin();
239  for (; ec != prot.GetEc().end() && it_bef != st_before.end(); ++ec, ++it_bef) {
241  if (status == CProt_ref::eEC_specific && (*it_bef) == CProt_ref::eEC_replaced) {
242  replaced++;
243  }
244  }
245 
246  prot.RemoveBadEC();
247  unsigned int removed = (unsigned int)(st_before.size() - prot.GetEc().size());
248 
249  if (replaced || removed) {
250  m_DataIter->SetModified();
252  log << m_DataIter->GetBestDescr() << ": ";
253  if (replaced) {
254  log << " replaced " << replaced << " EC numbers";
255  }
256  if (removed) {
257  log << " removed " << removed << " EC numbers";
258  }
259  x_LogFunction(log);
260  }
261 }
262 
263 bool CMacroFunction_RemoveInvalidECNumbers::x_ValidArguments() const
264 {
265  return (m_Args.empty());
266 }
267 
268 ///////////////////////////////////////////////////////////////////////////////
269 /// class CMacroFunction_UpdateReplacedECNumbers
270 /// UpdateReplacedECNumbers( del_improper_format, del_unrecognized, del_mult_repl)
271 ///
272 // Changes in the function and parameter names require changes in the respective
273 // XRC file used in the macro editor
274 DEFINE_MACRO_FUNCNAME(CMacroFunction_UpdateReplacedECNumbers, "UpdateReplacedECNumbers")
275 
276 void CMacroFunction_UpdateReplacedECNumbers::TheFunction()
277 {
278  bool del_improper_format = m_Args[0]->GetBool(); // remove improperly formatted EC numbers
279  bool del_unrecognized = m_Args[1]->GetBool(); // remove unrecognized EC numbers
280  bool del_mult_replacement = m_Args[2]->GetBool(); // remove EC numbers replaced by more than one number
281 
282  CObjectInfo oi = m_DataIter->GetEditedObject();
284  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
285  if (!prot_feat || !prot_feat->GetData().IsProt() || !scope) {
286  return;
287  }
288 
289  CProt_ref& prot = prot_feat->SetData().SetProt();
290  if (!prot.IsSetEc() || prot.GetEc().empty())
291  return;
292 
293  // for logging:
294  string locus_tag("No locus tag");
295  NMacroUtil::GetLocusTagFromProtRef(*prot_feat, *scope, locus_tag);
297 
298  CProt_ref::TEc::iterator ec = prot.SetEc().begin();
299  while (ec != prot.SetEc().end()) {
300  bool removed = false;
303  if (status == CProt_ref::eEC_replaced) {
304  string repl_ec = CProt_ref::GetECNumberReplacement(*ec);
305  if (!NStr::IsBlank(repl_ec)) {
306  if (NStr::FindNoCase(repl_ec, "\t") == NPOS) {
307  log << locus_tag << ": replaced " << *ec << " with " << repl_ec << "\n";
308  *ec = repl_ec;
309  }
310  else if (del_mult_replacement) {
311  log << locus_tag << ": removed " << *ec << "\n";
312  ec = prot.SetEc().erase(ec);
313  removed = true;
314  }
315  }
316  }
317  else if (del_unrecognized && status != CProt_ref::eEC_specific && status != CProt_ref::eEC_ambiguous) {
318  log << locus_tag << ": removed " << *ec << "\n";
319  ec = prot.SetEc().erase(ec);
320  removed = true;
321  }
322  }
323  else {
324  if (del_improper_format) {
325  log << locus_tag << ": removed " << *ec << "\n";
326  ec = prot.SetEc().erase(ec);
327  removed = true;
328  }
329  }
330 
331  if (!removed) {
332  ++ec;
333  }
334  }
335 
336  if (prot.GetEc().empty()) {
337  prot.ResetEc();
338  }
339 
340  m_DataIter->SetModified();
341  x_LogFunction(log);
342 }
343 
344 bool CMacroFunction_UpdateReplacedECNumbers::x_ValidArguments() const
345 {
346  size_t arg_size = m_Args.size();
347  if (arg_size != 3) {
348  return false;
349  }
350 
351  for (size_t n = 0; n < arg_size; ++n) {
352  if (m_Args[n]->GetDataType() != CMQueryNodeValue::eBool)
353  return false;
354  }
355  return true;
356 }
357 
358 
359 ///////////////////////////////////////////////////////////////////////////////
360 /// class CMacroFunction_UpdatemRNAProduct
361 /// UpdatemRNAProduct()
362 ///
363 DEFINE_MACRO_FUNCNAME(CMacroFunction_UpdatemRNAProduct, "UpdatemRNAProduct");
364 void CMacroFunction_UpdatemRNAProduct::TheFunction()
365 {
366  if (!m_Args.empty()) {
367  // for backward compatibility:
368  CMQueryNodeValue& bool_obj = m_Args[0].GetNCObject();
369  bool_obj.Dereference();
370  if (bool_obj.GetDataType() != CMQueryNodeValue::eBool) {
371  return;
372  }
373  // don't update the mRNA product name if the argument is false
374  if (!bool_obj.GetBool()) {
375  return;
376  }
377  }
378 
379  CObjectInfo oi = m_DataIter->GetEditedObject();
381  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
382  // assuming that the iterated object is a protein feature
383  if (!prot_feat || !scope ||
384  prot_feat->GetData().GetSubtype() != CSeqFeatData::eSubtype_prot ||
385  !prot_feat->GetData().GetProt().IsSetName()) {
386  return;
387  }
388 
389  const CProt_ref& prot = prot_feat->GetData().GetProt();
390  string product = prot.GetName().front();
392  log << m_DataIter->GetBestDescr() << ": ";
393 
394  CBioseq_Handle prot_bsh = scope->GetBioseqHandle(prot_feat->GetLocation());
395  if (prot_bsh) {
396  const CSeq_feat* cds = sequence::GetCDSForProduct(*prot_bsh.GetCompleteBioseq(), scope.GetPointer());
397  if (cds) {
398  CConstRef<CSeq_feat> mrna = sequence::GetmRNAforCDS(*cds, *scope);
399  if (mrna) {
400  CRef<CSeq_feat> new_mrna(new CSeq_feat());
401  new_mrna->Assign(*mrna);
402 
403  bool modified = false;
404  if (mrna->GetData().IsRna() && mrna->GetData().GetRna().GetType() == CRNA_ref::eType_mRNA) {
405  CRNA_ref& rna = new_mrna->SetData().SetRna();
406  if (NStr::IsBlank(product)) {
407  rna.ResetExt();
408  log << "Reset the mRNA product name ";
409  modified = true;
410  }
411  else if (!rna.IsSetExt() || (rna.IsSetExt() && !NStr::Equal(rna.GetExt().GetName(), product))){
412  rna.SetExt().SetName(product);
413  log << "Applied " << product << " to mRNA product name ";
414  modified = true;
415  }
416  }
417 
418  if (modified) {
419  CSeq_feat_Handle fh = scope->GetSeq_featHandle(*mrna);
420  CIRef<IEditCommand> chgFeat(new CCmdChangeSeq_feat(fh, *new_mrna));
421  CRef<CCmdComposite> cmd(new CCmdComposite("Update mRNA product to match CDS product name"));
422  cmd->AddCommand(*chgFeat);
423  m_DataIter->RunCommand(cmd, m_CmdComposite);
424  x_LogFunction(log);
425  }
426  }
427  }
428  }
429 }
430 
431 bool CMacroFunction_UpdatemRNAProduct::x_ValidArguments() const
432 {
433  if (m_Args.empty())
434  return true;
435  // for backward compatibility:
436  return (m_Args.size() == 1 && m_Args[0]->GetDataType() == CMQueryNodeValue::eRef);
437 }
438 
439 
440 ///////////////////////////////////////////////////////////////////////////////
441 /// class CMacroFunction_RemoveFeature
442 /// RemoveFeature([delete_overlapping_gene]) - also works for removing biosource and pub features
443 /// Set the flag TRUE to delete the overlapping gene
444 ///
445 DEFINE_MACRO_FUNCNAME(CMacroFunction_RemoveFeature, "RemoveFeature")
446 
447 void CMacroFunction_RemoveFeature::TheFunction()
448 {
449  if (!m_DataIter->IsFeature()) {
450  return;
451  }
452 
453  m_DataIter->SetToDelete(true);
454 
455  bool delete_gene = false;
456 
457  if (m_Args.size() == 1 && m_Args[0]->GetBool()) {
458  // delete overlapping gene
459  CObjectInfo oi = m_DataIter->GetEditedObject();
461  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
462 
464  if (gene) {
465  CRef<CCmdDelSeq_feat> del_cmd(new CCmdDelSeq_feat(scope->GetSeq_featHandle(*gene)));
466  CRef<CCmdComposite> cmd(new CCmdComposite("Delete overlapping gene"));
467  cmd->AddCommand(*del_cmd);
468  m_DataIter->RunCommand(cmd, m_CmdComposite);
469  delete_gene = true;
470  }
471  }
472 
474  log << m_DataIter->GetBestDescr() << ": feature removed";
475  if (delete_gene) {
476  log << " and the overlapping gene";
477  }
478  x_LogFunction(log);
479 }
480 
481 bool CMacroFunction_RemoveFeature::x_ValidArguments() const
482 {
483  return m_Args.empty() || (m_Args.size() == 1 && m_Args[0]->IsBool());
484 }
485 
486 ///////////////////////////////////////////////////////////////////////////////
487 // class CMacroFunction_CopyNameToCDSNote
488 /// CopyNameToCDSNote();
489 /// Copies the first protein name to the cds comment
490 ///
491 DEFINE_MACRO_FUNCNAME(CMacroFunction_CopyNameToCDSNote, "CopyNameToCDSNote")
492 void CMacroFunction_CopyNameToCDSNote::TheFunction()
493 {
494  CObjectInfo oi = m_DataIter->GetEditedObject();
496  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
497  // assuming that the iterated object is a protein feature
498  if (!prot_feat || !scope ||
499  !prot_feat->GetData().IsProt() ||
500  !prot_feat->GetData().GetProt().IsSetName()) {
501  return;
502  }
503 
504  const CProt_ref& prot = prot_feat->GetData().GetProt();
505  string product = prot.GetName().front();
507  log << m_DataIter->GetBestDescr() << ": ";
508 
509  CBioseq_Handle prot_bsh = scope->GetBioseqHandle(prot_feat->GetLocation());
510  if (prot_bsh) {
511  const CSeq_feat* cds = sequence::GetCDSForProduct(*prot_bsh.GetCompleteBioseq(), scope.GetPointer());
512  if (cds) {
513  CRef<CSeq_feat> new_cds(new CSeq_feat());
514  new_cds->Assign(*cds);
515 
516  bool modified = false;
517  string orig_comment = (new_cds->IsSetComment()) ? new_cds->GetComment() : kEmptyStr;
518  if (edit::AddValueToString(orig_comment, product, edit::eExistingText_append_semi)) {
519  new_cds->SetComment(orig_comment);
520  log << "Copied protein name to CDS note";
521  modified = true;
522  }
523 
524  if (modified) {
525  CSeq_feat_Handle fh = scope->GetSeq_featHandle(*cds);
526  CIRef<IEditCommand> chgFeat(new CCmdChangeSeq_feat(fh, *new_cds));
527  CRef<CCmdComposite> cmd(new CCmdComposite("Copy protein name to CDS note"));
528  cmd->AddCommand(*chgFeat);
529  m_DataIter->RunCommand(cmd, m_CmdComposite);
530  x_LogFunction(log);
531  }
532  }
533  }
534 }
535 
536 bool CMacroFunction_CopyNameToCDSNote::x_ValidArguments() const
537 {
538  return (m_Args.empty());
539 }
540 
541 
542 /// class CMacroFunction_RemoveAllFeatures
543 /// RemoveAllFeatures();
544 ///
547 {
548  CConstRef<CObject> obj = m_DataIter->GetScopedObject().object;
549  const CBioseq* bseq = dynamic_cast<const CBioseq*>(obj.GetPointer());
550  const CSeq_entry* entry = dynamic_cast<const CSeq_entry*>(obj.GetPointer());
551  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
552  if (!scope) return;
553 
554  size_t count = 0;
555  bool remove_proteins = true;
556  CRef<CCmdComposite> delete_features_cmd;
557  if (entry) {
558  delete_features_cmd = GetDeleteAllFeaturesCommand(m_DataIter->GetSEH(), count, remove_proteins);
559  }
560  else if (bseq && bseq->IsNa()) { // deprecated part
561  delete_features_cmd.Reset(new CCmdComposite("Remove All Features"));
562  // only delete features on nucleotide sequences, protein features are automatically removed with the coding region
563  CBioseq_Handle bsh = scope->GetBioseqHandle(*bseq);
564  if (!bsh)
565  return;
566 
567  if (!m_DataIter->HasBeenCompleted()) {
568  m_ProductToCds.clear();
569  GetProductToCDSMap(*scope, m_ProductToCds);
570  m_DataIter->SetCompleted();
571  }
572 
573  CFeat_CI it(bsh);
574  while (it) {
575  CRef<CCmdComposite> cmd = GetDeleteFeatureCommand(it->GetSeq_feat_Handle(), remove_proteins, m_ProductToCds);
576  delete_features_cmd->AddCommand(*cmd);
577  count++;
578  ++it;
579  }
580  }
581 
582  if (count > 0) {
583  m_DataIter->RunCommand(delete_features_cmd, m_CmdComposite);
585  log << "Removed " << count << " features";
586  x_LogFunction(log);
587  }
588 }
589 
591 {
592  return (m_Args.empty());
593 }
594 ///////////////////////////////////////////////////////////////////////////////
595 /// class CMacroFunction_RemoveDuplFeatures
596 /// RemoveDuplicateFeatures(feat_type, check_partials, case_sensitive, remove_proteins)
597 ///
598 DEFINE_MACRO_FUNCNAME(CMacroFunction_RemoveDuplFeatures, "RemoveDuplicateFeatures")
599 
600 void CMacroFunction_RemoveDuplFeatures::TheFunction()
601 {
602  CConstRef<CObject> obj = m_DataIter->GetScopedObject().object;
603  const CBioseq* bseq = dynamic_cast<const CBioseq*>(obj.GetPointer());
604  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
605  if (!bseq || !scope)
606  return;
607 
608  CSeqFeatData::ESubtype type = NMacroUtil::GetFeatSubtype(m_Args[0]->GetString());
609  bool check_partials = m_Args[1]->GetBool();
610  bool case_sensitive = m_Args[2]->GetBool();
611  bool remove_proteins = m_Args[3]->GetBool();
612 
613  CBioseq_Handle bsh = scope->GetBioseqHandle(*bseq);
614  SAnnotSelector sel(type);
615  set<CSeq_feat_Handle> duplicates;
616 
617  for (CFeat_CI feat_it1(bsh, sel); feat_it1; ++feat_it1) {
618  for (CFeat_CI feat_it2(*scope, feat_it1->GetLocation(), sel); feat_it2; ++feat_it2) {
619  if (feat_it1->GetSeq_feat_Handle() < feat_it2->GetSeq_feat_Handle()) {
620  validator::EDuplicateFeatureType dup_type = validator::IsDuplicate(feat_it1->GetSeq_feat_Handle(), feat_it2->GetSeq_feat_Handle(), check_partials, case_sensitive);
622  duplicates.insert(feat_it2->GetSeq_feat_Handle());
623  }
624  }
625  }
626  }
627 
628  if (duplicates.empty())
629  return;
630 
631  CRef<CCmdComposite> cmd(new CCmdComposite("Delete duplicate features"));
632  ITERATE(set<CSeq_feat_Handle>, fh, duplicates) {
633  cmd->AddCommand(*GetDeleteFeatureCommand(*fh, remove_proteins));
634  }
635 
636  m_DataIter->RunCommand(cmd, m_CmdComposite);
637  TChangedQuals report;
638  report["removal of duplicate features"] = duplicates.size();
639  CRef<IFunctionLog> fnc_log(new CGeneralFuncLog(report));
640  x_LogChangedQuals(fnc_log);
641 }
642 
643 bool CMacroFunction_RemoveDuplFeatures::x_ValidArguments() const
644 {
645  if (m_Args.size() != 4 || !m_Args[0]->IsString()) {
646  return false;
647  }
648 
649  for (size_t i = 1; i < m_Args.size(); ++i) {
650  if (!m_Args[i]->IsBool())
651  return false;
652  }
653  return true;
654 }
655 
656 ///////////////////////////////////////////////////////////////////////////////
657 /// class CMacroFunction_FixProteinFormat
658 /// FixProteinFormat() - removes organism names from protein names
659 ///
661 
663 {
664  CObjectInfo oi = m_DataIter->GetEditedObject();
665  // the object should be a protein feature
667  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
668  if (!prot_feat || !prot_feat->GetData().IsProt() || !scope)
669  return;
670 
671  m_NewNames.clear();
672  m_OrigNames.clear();
673 
674  if (m_DataIter->IsHugeDataMode()) {
675  vector<string> seh_taxnames;
676  FindOrgNames(m_DataIter->GetSEH(), seh_taxnames);
677  // restrict search for a much smaller set as it's most likely that the taxname will be inside this TSE
678  x_FixProteinNames(prot_feat->SetData().SetProt(), seh_taxnames);
679  }
680 
681  if (m_NewNames.empty()) {
682  const auto& taxnames = m_DataIter->GetTaxnames();
683  x_FixProteinNames(prot_feat->SetData().SetProt(), taxnames);
684  }
685 
686  if (!m_NewNames.empty()) {
687  m_DataIter->SetModified();
689  for (size_t n = 0; n < m_NewNames.size(); ++n) {
690  log << "On " << m_DataIter->GetBestDescr();
691  log << ": changed protein name from " << m_OrigNames[n];
692  log << " to " << m_NewNames[n];
693  }
694  x_LogFunction(log);
695  }
696 }
697 
698 void CMacroFunction_FixProteinFormat::x_FixProteinNames(CProt_ref& prot, const vector<string>& taxnames)
699 {
700  for (auto& it : prot.SetName()) {
701  string prot_name = s_FixProteinNameFormat(it, taxnames);
702  if (!prot_name.empty() && !NStr::EqualCase(it, prot_name)) {
703  m_OrigNames.push_back(it);
704  it = prot_name;
705  m_NewNames.push_back(it);
706  }
707  }
708 }
709 
711 {
712  return (m_Args.empty());
713 }
714 
715 
716 string CMacroFunction_FixProteinFormat::s_FixProteinNameFormat(const string& protein, const vector<string>& taxnames)
717 {
718  if (NStr::IsBlank(protein))
719  return kEmptyStr;
720  if (taxnames.empty())
721  return protein;
722 
723  string new_prot(protein);
724  vector<string> pattern;
725  pattern.push_back("()");
726  pattern.push_back("( )");
727  pattern.push_back("[]");
728  pattern.push_back("[ ]");
729  ITERATE(vector<string>, name, taxnames) {
730  SIZE_TYPE pos = NStr::FindNoCase(new_prot, *name);
731  if (pos != NPOS) {
732  new_prot = protein.substr(0, pos) + protein.substr(pos + name->length());
733  NStr::ReplaceInPlace(new_prot, " ", "");
734 
735  // delete any brackets around the taxname:
736  ITERATE(vector<string>, pat_it, pattern) {
737  if (NStr::FindNoCase(new_prot, *pat_it) != NPOS) {
738  NStr::ReplaceInPlace(new_prot, *pat_it, "");
739  }
740  }
741  NStr::ReplaceInPlace(new_prot, " ", " ");
742  }
743  }
744  NStr::TruncateSpacesInPlace(new_prot);
745 
746  return new_prot;
747 }
748 
750 {
751  CConstRef<CObject> obj = m_DataIter->GetScopedObject().object;
752  m_Origfeat = ConstRef(dynamic_cast<const CSeq_feat*>(obj.GetPointer()));
753  m_Scope = m_DataIter->GetScopedObject().scope;
754  if (!m_Origfeat || !m_Scope) {
755  return false;
756  }
757 
758  CObjectInfo oi = m_DataIter->GetEditedObject();
760  if (!m_Seqfeat || !m_Seqfeat->IsSetLocation()) {
761  return false;
762  }
763 
764  return true;
765 }
766 
768 {
770  m_Seqfeat->SetPartial(m_Seqfeat->GetLocation().IsPartialStart(eExtreme_Biological)
771  || m_Seqfeat->GetLocation().IsPartialStop(eExtreme_Biological));
772 
773  m_DataIter->SetModified();
774  string new_loc;
775  m_Seqfeat->GetLocation().GetLabel(&new_loc);
777  log << descr << " for " << m_DataIter->GetBestDescr() << " to " << new_loc;
778 
780 
781  if (m_AdjustGene && !m_Seqfeat->GetData().IsGene()) {
783  if (adjust_gene_cmd) {
784  CRef<CCmdComposite> cmd(new CCmdComposite("Adjust gene"));
785  cmd->AddCommand(*adjust_gene_cmd);
786  m_DataIter->RunCommand(cmd, m_CmdComposite);
787  log << " and adjusted gene location.";
788  }
789  }
791 }
792 
794 {
795  if (m_Seqfeat->GetData().IsCdregion()) {
799  if (!m_DataIter->HasBeenCompleted() && feat_iter) {
800  feat_iter->SetCreateGeneralIdFlag();
801  m_DataIter->SetCompleted();
802  }
803 
804  bool cds_change = false;
805  // this function might make changes in the cds, but changes are not included in the command
806  CRef<CCmdComposite> retransl_cmd = GetRetranslateCDSCommand(*m_Scope, *m_Seqfeat, cds_change, feat_iter->GetCreateGeneralIdFlag());
807  if (retransl_cmd) {
808  m_DataIter->RunCommand(retransl_cmd, m_CmdComposite);
809  log << " and retranslated the coding region ";
810  }
811  }
812  else {
813  // this function/command is not changing the feature
815  if (synch_cmd) {
816  m_DataIter->RunCommand(synch_cmd, m_CmdComposite);
817  log << " and synchronized CDS partials";
818  }
819  }
820  }
821 }
822 
823 ///////////////////////////////////////////////////////////////////////////////
824 /// class CMacroFunction_SetBothPartials
825 /// SetBothEndsPartial("all"|"at-end", extend(boolean) [,retranslate_cds][,adjust_gene])
826 /// The first parameter is for feature selection
827 /// use "at-end" to only apply to features whose both ends are at the end of sequence
828 /// use extend = true, to extend to ends of sequence if partials are set
829 ///
831 
833 {
834  if (!x_CheckInitFeature())
835  return;
836 
837  m_Modified = s_SetBothEndsPartial(*m_Seqfeat, *m_Scope, m_Args[0]->GetString(), m_Args[1]->GetBool());
838  if (m_Modified) {
839  m_RetranslateCDS = (m_Args.size() > 2) ? m_Args[2]->GetBool() : false;
840  m_AdjustGene = (m_Args.size() == 4) ? m_Args[3]->GetBool() : false;
841  x_RetranslateCDSAdjustGene("Set both end partials");
842  }
843 }
844 
845 bool CMacroFunction_SetBothPartials::s_SetBothEndsPartial(CSeq_feat& feat, CScope& scope, const string& descr, bool extend)
846 {
847  if (!ENUM_METHOD_NAME(EPartial_both_set_constraint)()->IsValidName(descr)) {
848  NCBI_THROW(CException, eUnknown, "Unrecognized option to set both partials: " + descr);
849  }
850 
851  EPartial_both_set_constraint apply_mode =
853 
854  edit::CLocationEditPolicy::EPartialPolicy policy5 = edit::CLocationEditPolicy::ePartialPolicy_eNoChange;
855  edit::CLocationEditPolicy::EPartialPolicy policy3 = edit::CLocationEditPolicy::ePartialPolicy_eNoChange;
856  if (apply_mode == ePartial_both_set_constraint_all) {
857  policy5 = edit::CLocationEditPolicy::ePartialPolicy_eSet;
858  policy3 = edit::CLocationEditPolicy::ePartialPolicy_eSet;
859  }
860  else {
861  CBioseq_Handle bsh = GetBioseqForSeqFeat(feat, scope);
862  if (bsh
863  && edit::CLocationEditPolicy::Is5AtEndOfSeq(feat.GetLocation(), bsh)
864  && edit::CLocationEditPolicy::Is3AtEndOfSeq(feat.GetLocation(), bsh)) {
865  // when both ends of location coincide with the sequence ends
866  policy5 = edit::CLocationEditPolicy::ePartialPolicy_eSetAtEnd;
867  policy3 = edit::CLocationEditPolicy::ePartialPolicy_eSetAtEnd;
868  }
869  }
870 
871  bool extend5(false), extend3(false);
872  if (extend) {
873  extend5 = true;
874  extend3 = true;
875  }
876 
877  CRef<edit::CLocationEditPolicy> policy(new edit::CLocationEditPolicy(policy5, policy3, extend5, extend3));
878  return policy->ApplyPolicyToFeature(feat, scope);
879 }
880 
881 
883 {
884  if (m_Args.size() < 2 || m_Args.size() > 4)
885  return false;
886 
887  for (size_t i = 1; i < m_Args.size(); ++i) {
888  if (m_Args[i]->GetDataType() != CMQueryNodeValue::eBool) {
889  return false;
890  }
891  }
892  return m_Args[0]->GetDataType() == CMQueryNodeValue::eString;
893 }
894 
895 ///////////////////////////////////////////////////////////////////////////////
896 /// class CMacroFunction_RemoveBothPartials
897 /// RemoveBothEndsPartial("all"|"not-at-end" [,retranslate_cds][,adjust_gene])
898 /// First parameter specifies which features to select:
899 /// "all" - all features, "not-at-end" - features whose both ends are not at the sequence ends
900 ///
902 
904 {
905  if (!x_CheckInitFeature())
906  return;
907 
908  m_Modified = s_RemoveBothPartials(*m_Seqfeat, *m_Scope, m_Args[0]->GetString());
909  if (m_Modified) {
910  m_RetranslateCDS = (m_Args.size() > 1) ? m_Args[1]->GetBool() : false;
911  m_AdjustGene = (m_Args.size() == 3) ? m_Args[2]->GetBool() : false;
912  x_RetranslateCDSAdjustGene("Removed both ends partial");
913  }
914 }
915 
917 {
918  if (!ENUM_METHOD_NAME(EPartial_both_clear_constraint)()->IsValidName(descr)) {
919  NCBI_THROW(CException, eUnknown, "Unrecognized option to clear partials: " + descr);
920  }
921 
922  EPartial_both_clear_constraint apply_mode =
924 
925  edit::CLocationEditPolicy::EPartialPolicy policy5 = edit::CLocationEditPolicy::ePartialPolicy_eNoChange;
926  edit::CLocationEditPolicy::EPartialPolicy policy3 = edit::CLocationEditPolicy::ePartialPolicy_eNoChange;
927  if (apply_mode == ePartial_both_clear_constraint_all) {
928  policy5 = edit::CLocationEditPolicy::ePartialPolicy_eClear;
929  policy3 = edit::CLocationEditPolicy::ePartialPolicy_eClear;
930  }
931  else {
932  CBioseq_Handle bsh = GetBioseqForSeqFeat(feat, scope);
933  if (bsh
934  && !edit::CLocationEditPolicy::Is5AtEndOfSeq(feat.GetLocation(), bsh)
935  && !edit::CLocationEditPolicy::Is3AtEndOfSeq(feat.GetLocation(), bsh)) {
936  // when both ends of location do not coincide with the sequence ends
937  policy5 = edit::CLocationEditPolicy::ePartialPolicy_eClearNotAtEnd;
938  policy3 = edit::CLocationEditPolicy::ePartialPolicy_eClearNotAtEnd;
939  }
940  }
941 
942  bool extend5 = false, extend3 = false;
943  CRef<edit::CLocationEditPolicy> policy(new edit::CLocationEditPolicy(policy5, policy3, extend5, extend3));
944  return policy->ApplyPolicyToFeature(feat, scope);
945 }
946 
948 {
949  if (m_Args.size() < 1 || m_Args.size() > 3)
950  return false;
951 
952  for (size_t i = 1; i < m_Args.size(); ++i) {
953  if (m_Args[i]->GetDataType() != CMQueryNodeValue::eBool) {
954  return false;
955  }
956  }
957  return m_Args[0]->GetDataType() == CMQueryNodeValue::eString;
958 }
959 
960 
961 ///////////////////////////////////////////////////////////////////////////////
962 /// class CMacroFunction_Set5Partial
963 /// SetPartialStart("all"|"at-end"|"bad-start"|"frame-not-one", extend(boolean) [,retranslate_cds][,adjust_gene])
964 ///
966 void CMacroFunction_Set5Partial::TheFunction()
967 {
968  if (!x_CheckInitFeature())
969  return;
970 
971  m_Modified = s_Set5EndPartial(*m_Seqfeat, *m_Scope, m_Args[0]->GetString(), m_Args[1]->GetBool());
972  if (m_Modified) {
973  m_RetranslateCDS = (m_Args.size() > 2) ? m_Args[2]->GetBool() : false;
974  m_AdjustGene = (m_Args.size() == 4) ? m_Args[3]->GetBool() : false;
975  x_RetranslateCDSAdjustGene("Set 5' end partial");
976  }
977 }
978 
979 bool CMacroFunction_Set5Partial::s_Set5EndPartial(CSeq_feat& feat, CScope& scope, const string& descr, bool extend5)
980 {
981  if (!ENUM_METHOD_NAME(EPartial_5_set_constraint)()->IsValidName(descr)) {
982  NCBI_THROW(CException, eUnknown, "Unrecognized option to set 5' partials: " + descr);
983  }
984 
987 
988  edit::CLocationEditPolicy::EPartialPolicy policy5 = edit::CLocationEditPolicy::ePartialPolicy_eNoChange;
989  switch (filter) {
991  policy5 = edit::CLocationEditPolicy::ePartialPolicy_eSet;
992  break;
994  policy5 = edit::CLocationEditPolicy::ePartialPolicy_eSetAtEnd;
995  break;
997  policy5 = edit::CLocationEditPolicy::ePartialPolicy_eSetForBadEnd;
998  break;
1000  policy5 = edit::CLocationEditPolicy::ePartialPolicy_eSetForFrame;
1001  break;
1002  }
1003 
1004  bool extend3 = false;
1005  CRef<edit::CLocationEditPolicy> policy(new edit::CLocationEditPolicy(policy5, edit::CLocationEditPolicy::ePartialPolicy_eNoChange, extend5, extend3));
1006  return policy->ApplyPolicyToFeature(feat, scope);
1007 }
1008 
1010 {
1011  if (m_Args.size() < 2 || m_Args.size() > 4)
1012  return false;
1013 
1014  for (size_t i = 1; i < m_Args.size(); ++i) {
1015  if (m_Args[i]->GetDataType() != CMQueryNodeValue::eBool) {
1016  return false;
1017  }
1018  }
1019  return m_Args[0]->GetDataType() == CMQueryNodeValue::eString;
1020 }
1021 
1022 ///////////////////////////////////////////////////////////////////////////////
1023 /// class CMacroFunction_Set3Partial
1024 /// SetPartialStop("all"|"at-end"|"bad-end", extend(boolean) [,retranslate_cds][,adjust_gene])
1025 ///
1027 
1028 void CMacroFunction_Set3Partial::TheFunction()
1029 {
1030  if (!x_CheckInitFeature())
1031  return;
1032 
1033  m_Modified = s_Set3EndPartial(*m_Seqfeat, *m_Scope, m_Args[0]->GetString(), m_Args[1]->GetBool());
1034  if (m_Modified) {
1035  m_RetranslateCDS = (m_Args.size() > 2) ? m_Args[2]->GetBool() : false;
1036  m_AdjustGene = (m_Args.size() == 4) ? m_Args[3]->GetBool() : false;
1037  x_RetranslateCDSAdjustGene("Set 3' end partial");
1038  }
1039 }
1040 
1041 bool CMacroFunction_Set3Partial::s_Set3EndPartial(CSeq_feat& feat, CScope& scope, const string& descr, bool extend3)
1042 {
1043  if (!ENUM_METHOD_NAME(EPartial_3_set_constraint)()->IsValidName(descr)) {
1044  NCBI_THROW(CException, eUnknown, "Unrecognized option to set 3' partials: " + descr);
1045  }
1046 
1047  EPartial_3_set_constraint filter =
1049 
1050  edit::CLocationEditPolicy::EPartialPolicy policy3 = edit::CLocationEditPolicy::ePartialPolicy_eNoChange;
1051  switch (filter) {
1053  policy3 = edit::CLocationEditPolicy::ePartialPolicy_eSet;
1054  break;
1056  policy3 = edit::CLocationEditPolicy::ePartialPolicy_eSetAtEnd;
1057  break;
1059  policy3 = edit::CLocationEditPolicy::ePartialPolicy_eSetForBadEnd;
1060  break;
1061  }
1062 
1063  bool extend5 = false;
1064  CRef<edit::CLocationEditPolicy> policy(new edit::CLocationEditPolicy(edit::CLocationEditPolicy::ePartialPolicy_eNoChange, policy3, extend5, extend3));
1065  return policy->ApplyPolicyToFeature(feat, scope);
1066 }
1067 
1069 {
1070  if (m_Args.size() < 2 || m_Args.size() > 4)
1071  return false;
1072 
1073  for (size_t i = 1; i < m_Args.size(); ++i) {
1074  if (m_Args[i]->GetDataType() != CMQueryNodeValue::eBool) {
1075  return false;
1076  }
1077  }
1078  return m_Args[0]->GetDataType() == CMQueryNodeValue::eString;
1079 }
1080 
1081 ///////////////////////////////////////////////////////////////////////////////
1082 /// class CMacroFunction_Clear5Partial
1083 /// ClearPartialStart("all"|"not-at-end"|"good-start" [,retranslate_cds][,adjust_gene])
1084 ///
1086 void CMacroFunction_Clear5Partial::TheFunction()
1087 {
1088  if (!x_CheckInitFeature())
1089  return;
1090 
1091  m_Modified = s_Clear5EndPartial(*m_Seqfeat, *m_Scope, m_Args[0]->GetString());
1092  if (m_Modified) {
1093  m_RetranslateCDS = (m_Args.size() > 1) ? m_Args[1]->GetBool() : false;
1094  m_AdjustGene = (m_Args.size() == 3) ? m_Args[2]->GetBool() : false;
1095  x_RetranslateCDSAdjustGene("Cleared 5' end partial");
1096  }
1097 }
1098 
1100 {
1101  if (!ENUM_METHOD_NAME(EPartial_5_clear_constraint)()->IsValidName(descr)) {
1102  NCBI_THROW(CException, eUnknown, "Unrecognized option to clear 5' partials: " + descr);
1103  }
1104 
1107 
1108  edit::CLocationEditPolicy::EPartialPolicy policy5 = edit::CLocationEditPolicy::ePartialPolicy_eNoChange;
1109  switch (filter) {
1111  policy5 = edit::CLocationEditPolicy::ePartialPolicy_eClear;
1112  break;
1114  policy5 = edit::CLocationEditPolicy::ePartialPolicy_eClearNotAtEnd;
1115  break;
1117  policy5 = edit::CLocationEditPolicy::ePartialPolicy_eClearForGoodEnd;
1118  break;
1119  }
1120 
1121  bool extend5 = false, extend3 = false;
1122  CRef<edit::CLocationEditPolicy> policy(new edit::CLocationEditPolicy(policy5, edit::CLocationEditPolicy::ePartialPolicy_eNoChange, extend5, extend3));
1123  return policy->ApplyPolicyToFeature(feat, scope);
1124 }
1125 
1127 {
1128  if (m_Args.empty() || m_Args.size() > 3)
1129  return false;
1130 
1131  for (size_t i = 1; i < m_Args.size(); ++i) {
1132  if (m_Args[i]->GetDataType() != CMQueryNodeValue::eBool) {
1133  return false;
1134  }
1135  }
1136  return m_Args[0]->GetDataType() == CMQueryNodeValue::eString;
1137 }
1138 
1139 
1140 ///////////////////////////////////////////////////////////////////////////////
1141 /// class CMacroFunction_Clear3Partial
1142 /// ClearPartialStop("all"|"not-at-end"|"good-end" [,retranslate_cds][,adjust_gene])
1143 ///
1145 
1146 void CMacroFunction_Clear3Partial::TheFunction()
1147 {
1148  if (!x_CheckInitFeature())
1149  return;
1150 
1151  m_Modified = s_Clear3EndPartial(*m_Seqfeat, *m_Scope, m_Args[0]->GetString());
1152  if (m_Modified) {
1153  m_RetranslateCDS = (m_Args.size() > 1) ? m_Args[1]->GetBool() : false;
1154  m_AdjustGene = (m_Args.size() == 3) ? m_Args[2]->GetBool() : false;
1155  x_RetranslateCDSAdjustGene("Cleared 3' end partial");
1156  }
1157 }
1158 
1160 {
1161  if (!ENUM_METHOD_NAME(EPartial_3_clear_constraint)()->IsValidName(descr)) {
1162  NCBI_THROW(CException, eUnknown, "Unrecognized option to clear 3' partials: " + descr);
1163  }
1164 
1167 
1168  edit::CLocationEditPolicy::EPartialPolicy policy3 = edit::CLocationEditPolicy::ePartialPolicy_eNoChange;
1169  switch (filter) {
1171  policy3 = edit::CLocationEditPolicy::ePartialPolicy_eClear;
1172  break;
1174  policy3 = edit::CLocationEditPolicy::ePartialPolicy_eClearNotAtEnd;
1175  break;
1177  policy3 = edit::CLocationEditPolicy::ePartialPolicy_eClearForGoodEnd;
1178  break;
1179  }
1180 
1181  bool extend5 = false, extend3 = false;
1182  CRef<edit::CLocationEditPolicy> policy(new edit::CLocationEditPolicy(edit::CLocationEditPolicy::ePartialPolicy_eNoChange, policy3, extend5, extend3));
1183  return policy->ApplyPolicyToFeature(feat, scope);
1184 }
1185 
1187 {
1188  if (m_Args.empty() || m_Args.size() > 3)
1189  return false;
1190 
1191  for (size_t i = 1; i < m_Args.size(); ++i) {
1192  if (m_Args[i]->GetDataType() != CMQueryNodeValue::eBool) {
1193  return false;
1194  }
1195  }
1196  return m_Args[0]->GetDataType() == CMQueryNodeValue::eString;
1197 }
1198 
1199 
1200 ///////////////////////////////////////////////////////////////////////////////
1201 /// class CMacroFunction_ConvertLocStrand
1202 /// ConvertLocationStrand(from_strand, to_strand [,retranslate_cds][,adjust_gene])
1203 /// from_strand can be one of {any, plus, minus, unknown, both}
1204 /// to_strand can be one of {plus, minus, unknown, both, reverse}
1205 ///
1208 {
1209  if (!x_CheckInitFeature())
1210  return;
1211 
1212  m_RetranslateCDS = (m_Args.size() > 2) ? m_Args[2]->GetBool() : false;
1213  m_AdjustGene = (m_Args.size() == 4) ? m_Args[3]->GetBool() : false;
1214 
1215  m_Modified = s_ConvertLocationStrand(*m_Seqfeat, *m_Scope, m_Args[0]->GetString(), m_Args[1]->GetString());
1216  if (m_Modified) {
1217  m_Seqfeat->SetPartial(m_Seqfeat->GetLocation().IsPartialStart(eExtreme_Biological)
1218  || m_Seqfeat->GetLocation().IsPartialStop(eExtreme_Biological));
1219 
1220  m_DataIter->SetModified();
1221  string new_loc;
1222  m_Seqfeat->GetLocation().GetLabel(&new_loc);
1224  log << "Converted location strand for " << m_DataIter->GetBestDescr() << " to " << new_loc;
1225 
1226 
1227  x_RetranslateCDS(log);
1228 
1229  if (m_AdjustGene && !m_Seqfeat->GetData().IsGene()) {
1230  CConstRef<CSeq_feat> overlap_gene = sequence::GetGeneForFeature(*m_Origfeat, *m_Scope);
1231  if (overlap_gene) {
1232  CRef<CSeq_feat> new_gene(new CSeq_feat);
1233  new_gene->Assign(*overlap_gene);
1234  bool change_gene = s_ConvertLocationStrand(*new_gene, *m_Scope, m_Args[0]->GetString(), m_Args[1]->GetString());
1235  if (change_gene) {
1236  CSeq_feat_Handle fh = m_Scope->GetSeq_featHandle(*overlap_gene);
1237  CIRef<IEditCommand> chgFeat(new CCmdChangeSeq_feat(fh, *new_gene));
1238  if (chgFeat) {
1239  CRef<CCmdComposite> cmd(new CCmdComposite("Adjust gene"));
1240  cmd->AddCommand(*chgFeat);
1241  m_DataIter->RunCommand(cmd, m_CmdComposite);
1242  log << " and adjusted gene location.";
1243  }
1244  }
1245  }
1246  }
1247  x_LogFunction(log);
1248  }
1249 }
1250 
1252 {
1253  ENa_strand strand = eNa_strand_unknown;
1254  if (NStr::EqualNocase(str, "minus")) {
1255  strand = eNa_strand_minus;
1256  }
1257  else if (NStr::EqualNocase(str, "plus")) {
1258  strand = eNa_strand_plus;
1259  }
1260  else if (NStr::EqualNocase(str, "both")) {
1261  strand = eNa_strand_both;
1262  }
1263  return strand;
1264 }
1265 
1266 bool CMacroFunction_ConvertLocStrand::s_ConvertLocationStrand(CSeq_feat& feat, CScope& scope, const string& str_from, const string& str_to)
1267 {
1268  bool modified = false;
1269  if (!feat.IsSetLocation()) {
1270  return modified;
1271  }
1272 
1273  string from = str_from;
1274  NStr::ToLower(from);
1275  string to = str_to;
1276  NStr::ToLower(to);
1277  if (!ENUM_METHOD_NAME(EFeature_location_strand_from)()->IsValidName(from)) {
1278  NCBI_THROW(CException, eUnknown, "Unrecognized source strand: " + from);
1279  }
1280  if (!ENUM_METHOD_NAME(EFeature_location_strand_to)()->IsValidName(to)) {
1281  NCBI_THROW(CException, eUnknown, "Unrecognized target strand: " + to);
1282  }
1283 
1284  ENa_strand strand_from = s_GetStrandFromString(from);
1285  ENa_strand strand_to = s_GetStrandFromString(to);
1286  bool start_any = NStr::EqualNocase(from, "any");
1287  bool reverse = NStr::EqualNocase(to, "reverse");
1288  ENa_strand current_strand = eNa_strand_plus;
1289 
1290 
1291  if (feat.GetLocation().IsSetStrand())
1292  current_strand = feat.GetLocation().GetStrand();
1293 
1294  if (start_any || strand_from == current_strand) {
1295  // count for cases where the strand will be reversed
1296  if (!reverse) {
1297  if ((current_strand == eNa_strand_plus || current_strand == eNa_strand_unknown)
1298  && strand_to == eNa_strand_minus) {
1299  reverse = true;
1300  }
1301  else if (current_strand == eNa_strand_minus
1302  && (strand_to == eNa_strand_plus || strand_to == eNa_strand_unknown)) {
1303  reverse = true;
1304  }
1305  }
1306 
1307  if (reverse) {
1308  CRef<CSeq_loc> rev_loc(sequence::SeqLocRevCmpl(feat.GetLocation(), &scope));
1309  feat.SetLocation().Assign(*rev_loc);
1310  modified = true;
1311  }
1312  else if (strand_to != current_strand) {
1313  feat.SetLocation().SetStrand(strand_to);
1314  modified = true;
1315  }
1316  }
1317 
1318  return modified;
1319 }
1320 
1322 {
1323  if (m_Args.size() < 2 || m_Args.size() > 4)
1324  return false;
1325 
1326  for (size_t i = 2; i < m_Args.size(); ++i) {
1327  if (m_Args[i]->GetDataType() != CMQueryNodeValue::eBool) {
1328  return false;
1329  }
1330  }
1331  return m_Args[0]->GetDataType() == CMQueryNodeValue::eString
1332  && m_Args[1]->GetDataType() == CMQueryNodeValue::eString;
1333 }
1334 
1335 ///////////////////////////////////////////////////////////////////////////////
1336 /// class CMacroFunction_ConvertLocType
1337 /// ConvertLocationType("join"|"order"|"single-interval" [,retranslate_cds][,adjust_gene])
1338 ///
1341 {
1342  if (!x_CheckInitFeature())
1343  return;
1344 
1345  m_RetranslateCDS = (m_Args.size() > 1) ? m_Args[1]->GetBool() : false;
1346  m_AdjustGene = (m_Args.size() == 3) ? m_Args[2]->GetBool() : false;
1347 
1348  m_Modified = s_ConvertLocationType(*m_Seqfeat, *m_Scope, m_Args[0]->GetString());
1349  if (m_Modified) {
1350  m_Seqfeat->SetPartial(m_Seqfeat->GetLocation().IsPartialStart(eExtreme_Biological)
1351  || m_Seqfeat->GetLocation().IsPartialStop(eExtreme_Biological));
1352 
1353  m_DataIter->SetModified();
1354  string new_loc;
1355  m_Seqfeat->GetLocation().GetLabel(&new_loc);
1357  log << "Converted location type for " << m_DataIter->GetBestDescr() << " to " << new_loc;
1358 
1359 
1360  x_RetranslateCDS(log);
1361 
1362  if (m_AdjustGene && !m_Seqfeat->GetData().IsGene()) {
1363  CConstRef<CSeq_feat> overlap_gene = sequence::GetGeneForFeature(*m_Origfeat, *m_Scope);
1364  if (overlap_gene) {
1365  CRef<CSeq_feat> new_gene(new CSeq_feat);
1366  new_gene->Assign(*overlap_gene);
1367  bool change_gene = s_ConvertLocationType(*new_gene, *m_Scope, m_Args[0]->GetString());
1368  if (change_gene) {
1369  CSeq_feat_Handle fh = m_Scope->GetSeq_featHandle(*overlap_gene);
1370  CIRef<IEditCommand> chgFeat(new CCmdChangeSeq_feat(fh, *new_gene));
1371  if (chgFeat) {
1372  CRef<CCmdComposite> cmd(new CCmdComposite("Adjust gene"));
1373  cmd->AddCommand(*chgFeat);
1374  m_DataIter->RunCommand(cmd, m_CmdComposite);
1375  log << " and adjusted gene location.";
1376  }
1377  }
1378  }
1379  }
1380  x_LogFunction(log);
1381  }
1382 }
1383 
1385 {
1386  edit::CLocationEditPolicy::EMergePolicy merge_type = edit::CLocationEditPolicy::eMergePolicy_NoChange;
1387 
1388  if (NStr::EqualNocase(descr, "join")) {
1389  merge_type = edit::CLocationEditPolicy::eMergePolicy_Join;
1390  }
1391  else if (NStr::EqualNocase(descr, "order")) {
1392  merge_type = edit::CLocationEditPolicy::eMergePolicy_Order;
1393  }
1394  else if (NStr::EqualNocase(descr, "single-interval")) {
1395  merge_type = edit::CLocationEditPolicy::eMergePolicy_SingleInterval;
1396  }
1397  else {
1398  NCBI_THROW(CException, eUnknown, "Unrecognized location merge policy: " + descr);
1399  }
1400 
1401  CRef<edit::CLocationEditPolicy> policy(new edit::CLocationEditPolicy());
1402  policy->SetMergePolicy(merge_type);
1403  return policy->ApplyPolicyToFeature(feat, scope);
1404 }
1405 
1407 {
1408  if (m_Args.empty() || m_Args.size() > 3)
1409  return false;
1410 
1411  for (size_t i = 1; i < m_Args.size(); ++i) {
1412  if (m_Args[i]->GetDataType() != CMQueryNodeValue::eBool) {
1413  return false;
1414  }
1415  }
1416  return m_Args[0]->GetDataType() == CMQueryNodeValue::eString;
1417 }
1418 
1419 ///////////////////////////////////////////////////////////////////////////////
1420 /// class CMacroFunction_Extend5Feature - extends the feature ends to the respective end of the sequence
1421 /// ExtendFeatToSeqStart([retranslate_cds][,adjust_gene])
1422 ///
1425 {
1426  if (!x_CheckInitFeature())
1427  return;
1428 
1429  m_Modified = edit::CLocationEditPolicy::Extend5(*m_Seqfeat, *m_Scope);
1430  if (m_Modified) {
1431  m_RetranslateCDS = (m_Args.empty()) ? false : m_Args[0]->GetBool();
1432  m_AdjustGene = (m_Args.size() == 2) ? m_Args[1]->GetBool() : false;
1433  x_RetranslateCDSAdjustGene("Extended feature to 5' end");
1434  }
1435 }
1436 
1438 {
1439  if (m_Args.size() > 2)
1440  return false;
1441 
1442  for (auto& it : m_Args) {
1443  if (it->GetDataType() != CMQueryNodeValue::eBool) {
1444  return false;
1445  }
1446  }
1447  return true;
1448 }
1449 
1450 ///////////////////////////////////////////////////////////////////////////////
1451 /// class CMacroFunction_Extend3Feature - extends the feature ends to the respective end of the sequence
1452 /// ExtendFeatToSeqStop([retranslate_cds][,adjust_gene])
1453 ///
1455 
1457 {
1458  if (!x_CheckInitFeature())
1459  return;
1460 
1461  m_Modified = edit::CLocationEditPolicy::Extend3(*m_Seqfeat, *m_Scope);
1462  if (m_Modified) {
1463  m_RetranslateCDS = (m_Args.empty()) ? false : m_Args[0]->GetBool();
1464  m_AdjustGene = (m_Args.size() == 2) ? m_Args[1]->GetBool() : false;
1465  x_RetranslateCDSAdjustGene("Extended feature to 3' end");
1466  }
1467 }
1468 
1470 {
1471  if (m_Args.size() > 2)
1472  return false;
1473 
1474  for (auto& it : m_Args) {
1475  if (it->GetDataType() != CMQueryNodeValue::eBool) {
1476  return false;
1477  }
1478  }
1479  return true;
1480 }
1481 
1482 ///////////////////////////////////////////////////////////////////////////////
1483 /// class CMacroFunction_ApplyCDSFrame
1484 /// ApplyCDSFrame("best"|"match")
1485 ///
1487 
1488 void CMacroFunction_ApplyCDSFrame::TheFunction()
1489 {
1490  CObjectInfo oi = m_DataIter->GetEditedObject();
1492  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
1493  if (!cds || !cds->GetData().IsCdregion() || !scope) {
1494  return;
1495  }
1496 
1497  ECdsFrame frame = s_GetFrameFromName(m_Args[0]->GetString());
1498  if (frame == eNotSet) {
1499  // warn the user about the existing options
1500  return;
1501  }
1502  bool modified = s_SetCDSFrame(*cds, frame, *scope);
1503 
1504  if (modified) {
1505  m_DataIter->SetModified();
1506 
1507  //note: if product existed before, it will be retranslated
1508  if (cds->IsSetProduct()) {
1510  Ref(dynamic_cast<CMacroBioData_FeatIterBase*>(m_DataIter.GetPointer()));
1511  if (!m_DataIter->HasBeenCompleted() && feat_iter) {
1512  feat_iter->SetCreateGeneralIdFlag();
1513  m_DataIter->SetCompleted();
1514  }
1515 
1516  // this command will not make changes in the cds
1517  CRef<CCmdComposite> upd_cmd = GetRetranslateCDSCommand(*scope, *cds, feat_iter->GetCreateGeneralIdFlag());
1518  if (upd_cmd) {
1519  m_DataIter->RunCommand(upd_cmd, m_CmdComposite);
1520  }
1521  }
1523  log << m_DataIter->GetBestDescr() << ": the " << m_Args[0]->GetString() << " frame was set";
1524  x_LogFunction(log);
1525  }
1526 }
1527 
1529 {
1530  if (!cds.IsSetData() || !cds.GetData().IsCdregion())
1531  return false;
1532 
1534  if (cds.GetData().GetCdregion().IsSetFrame()) {
1535  orig_frame = cds.GetData().GetCdregion().GetFrame();
1536  }
1537  // retrieve the new frame
1538  CCdregion::TFrame new_frame = orig_frame;
1539  switch (frame_type) {
1540  case eNotSet:
1541  break;
1542  case eBest:
1543  new_frame = CSeqTranslator::FindBestFrame(cds, scope);
1544  break;
1545  case eMatch:
1546  new_frame = s_FindMatchingFrame(cds, scope);
1547  break;
1548  }
1549 
1550  bool modified = false;
1551  if (orig_frame != new_frame) {
1552  cds.SetData().SetCdregion().SetFrame(new_frame);
1553  modified = true;
1554  }
1555  return modified;
1556 }
1557 
1559 {
1561  //return the frame that matches the protein sequence if it can find one
1562  if (!cds.IsSetData() || !cds.GetData().IsCdregion() || !cds.IsSetLocation() || !cds.IsSetProduct()) {
1563  return new_frame;
1564  }
1565 
1566  // get the protein sequence
1567  CBioseq_Handle product = scope.GetBioseqHandle(cds.GetProduct());
1568  if (!product || !product.IsProtein()) {
1569  return new_frame;
1570  }
1571 
1572  // obtaining the original protein sequence
1574  prot_vec.SetCoding(CSeq_data::e_Ncbieaa);
1575  string orig_prot_seq;
1576  prot_vec.GetSeqData(0, prot_vec.size(), orig_prot_seq);
1577  if (NStr::IsBlank(orig_prot_seq)) {
1578  return new_frame;
1579  }
1580 
1581  CRef<CSeq_feat> tmp_cds(new CSeq_feat);
1582  tmp_cds->Assign(cds);
1583  for (int enumI = CCdregion::eFrame_one; enumI < CCdregion::eFrame_three + 1; ++enumI) {
1584  CCdregion::EFrame fr = (CCdregion::EFrame) (enumI);
1585  tmp_cds->SetData().SetCdregion().SetFrame(fr);
1586 
1587  string new_prot_seq;
1588  CSeqTranslator::Translate(*tmp_cds, scope, new_prot_seq);
1589  if (NStr::EndsWith(new_prot_seq, '*'))
1590  new_prot_seq.erase(new_prot_seq.end() - 1);
1591  if (NStr::EqualNocase(new_prot_seq, orig_prot_seq)) {
1592  new_frame = fr;
1593  break;
1594  }
1595  }
1596 
1597  return new_frame;
1598 }
1599 
1601 {
1602  ECdsFrame frame = eNotSet;
1603  if (NStr::EqualNocase(name, "best")) {
1604  frame = eBest;
1605  } else if (NStr::EqualNocase(name, "match")) {
1606  frame = eMatch;
1607  }
1608  return frame;
1609 }
1610 
1612 {
1613  return (m_Args.size() == 1 && m_Args[0]->GetDataType() == CMQueryNodeValue::eString);
1614 }
1615 
1616 ///////////////////////////////////////////////////////////////////////////////
1617 /// class CMacroFunction_ConvertFeature
1618 /// ConvertFeature(feat_type);
1619 /// ConvertFeature(feat_type, subtype) // subtype can be used for specifying type of bond, ncRNA class or type of site
1620 /// ConvertFeature(feat_type, create_on_protein) // when the feat_type is region, create_on_protein is of bool type
1621 /// ConvertCDSToFeature(feat_type, rem_mRNA, rem_gene, rem_transcript_id);
1622 /// ConvertCDSToFeature(feat_type, subtype, rem_mRNA, rem_gene, rem_transcript_id);
1623 /// ConvertCDSToFeature(feat_type, create_on_protein, rem_mRNA, rem_gene, rem_transcript_id);
1624 ///
1626 DEFINE_MACRO_FUNCNAME(CMacroFunction_ConvertCDS, "ConvertCDSToFeature")
1627 
1629 {
1630  CObjectInfo oi = m_DataIter->GetEditedObject();
1632  CConstRef<CObject> obj = m_DataIter->GetScopedObject().object;
1633  const CSeq_feat* const_feat = dynamic_cast<const CSeq_feat*>(obj.GetPointer());
1634  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
1635  if (!from_feat || !const_feat || !scope) {
1636  return;
1637  }
1638 
1639  const string& to_feat = m_Args[0]->GetString();
1640  m_FromType = from_feat->GetData().GetSubtype();
1641  m_ToType = NMacroUtil::GetFeatSubtype(to_feat);
1642 
1643  CRef<CConvertFeatureBase> converter = CConvertFeatureBaseFactory::Create(m_FromType, m_ToType);
1644  // when conversion is not supported
1648  x_LogFunction(log);
1649  return;
1650  }
1651 
1652  x_SetConvertOptions(converter);
1653 
1654  bool keep_orig(true);
1655  CRef<CCmdComposite> convert_cmd = converter->Convert(*from_feat, keep_orig, *scope);
1656 
1657  if (convert_cmd) {
1658  m_DataIter->RunCommand(convert_cmd, m_CmdComposite);
1660  log << "Converted " << m_DataIter->GetBestDescr() << " to " << to_feat;
1661  x_LogFunction(log);
1662  }
1663 }
1664 
1666 {
1667  if (m_Args.empty() || !m_Args[0]->IsString()) {
1668  return false;
1669  }
1670 
1671  if (m_Args.size() == 2 && (!m_Args[1]->IsString() && !m_Args[1]->IsBool())) {
1672  return false;
1673  }
1674  return true;
1675 }
1676 
1678 {
1679  CConvertFeatureBase::TOptions& opts = converter->SetOptions();
1681  size_t index = (m_Args[1]->GetDataType() != CMQueryNodeValue::eBool) ? 2 : 1;
1683  const string& opt_label = (*it)->GetLabel();
1685  (*it)->SetBool()->SetVal(m_Args[index]->GetBool());
1686  ++index;
1687  }
1689  (*it)->SetBool()->SetVal(m_Args[index]->GetBool());
1690  ++index;
1691  }
1693  (*it)->SetBool()->SetVal(m_Args[index]->GetBool());
1694  ++index;
1695  }
1696  }
1697  }
1698 
1701  const string& opt_label = (*it)->GetLabel();
1703  (*it)->SetString()->SetVal(m_Args[1]->GetString());
1704  }
1705  }
1706  } else if (m_ToType == CSeqFeatData::eSubtype_site) {
1708  const string& opt_label = (*it)->GetLabel();
1710  (*it)->SetString()->SetVal(m_Args[1]->GetString());
1711  }
1712  }
1713  } else if (m_ToType == CSeqFeatData::eSubtype_bond) {
1715  const string& opt_label = (*it)->GetLabel();
1717  (*it)->SetString()->SetVal(m_Args[1]->GetString());
1718  }
1719  }
1723  const string& opt_label = (*it)->GetLabel();
1725  (*it)->SetBool()->SetVal(m_Args[1]->GetBool());
1726  }
1727  }
1728  }
1729 }
1730 
1732 {
1733  if (m_Args.empty() ||
1734  m_Args.size() < 4 ||
1735  m_Args[0]->GetDataType() != CMQueryNodeValue::eString) {
1736  return false;
1737  }
1738 
1739  if (m_Args[1]->GetDataType() != CMQueryNodeValue::eString && m_Args[1]->GetDataType() != CMQueryNodeValue::eBool) {
1740  return false;
1741  }
1742 
1743  for (size_t index = m_Args.size() - 1; index < m_Args.size() - 3; --index) {
1744  if (m_Args[index]->GetDataType() != CMQueryNodeValue::eBool) {
1745  return false;
1746  }
1747  }
1748  return true;
1749 }
1750 
1751 ///////////////////////////////////////////////////////////////////////////////
1752 /// class CMacroFunction_AddGeneXref
1753 /// AddGeneXref(); - add a gene Xref to the selected feature
1754 ///
1755 DEFINE_MACRO_FUNCNAME(CMacroFunction_AddGeneXref, "AddGeneXref")
1756 
1757 void CMacroFunction_AddGeneXref::TheFunction()
1758 {
1759  CObjectInfo oi = m_DataIter->GetEditedObject();
1761  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
1762  if (!edit_feat || (edit_feat->IsSetData() && edit_feat->GetData().IsGene()) || !scope) {
1763  return;
1764  }
1765 
1766  CConstRef<CSeq_feat> gene = sequence::GetOverlappingGene(edit_feat->GetLocation(), *scope);
1767  if (!gene || !gene->IsSetData() || !gene->GetData().IsGene())
1768  return;
1769 
1770  edit_feat->SetGeneXref().Assign(gene->GetData().GetGene());
1771  m_DataIter->SetModified();
1772 
1774  log << "Added Gene xref to " << m_DataIter->GetBestDescr();
1775  x_LogFunction(log);
1776 }
1777 
1778 bool CMacroFunction_AddGeneXref::x_ValidArguments() const
1779 {
1780  return (m_Args.empty());
1781 }
1782 
1783 ///////////////////////////////////////////////////////////////////////////////
1784 /// class CMacroFunction_RemoveGeneXref
1785 /// RemoveGeneXref(suppressing_type, necessary_type);
1786 /// suppressing_type = {"any", "suppressing", "nonsuppressing"}
1787 /// necessary_type = {"any", "necessary", "unnecessary"}
1788 ///
1791 {
1792  CObjectInfo oi = m_DataIter->GetEditedObject();
1794  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
1795  if (!edit_feat || !edit_feat->IsSetXref() || !scope) {
1796  return;
1797  }
1798 
1800  const string& suppr_str = m_Args[0]->GetString();
1801  if (NStr::EqualNocase(suppr_str, "suppressing")) {
1803  } else if (NStr::EqualNocase(suppr_str, "nonsuppressing")) {
1805  }
1806 
1808  const string& necessary_str = m_Args[0]->GetString();
1809  if (NStr::EqualNocase(necessary_str, "necessary")) {
1810  necessary_type = eGene_xref_necessary_type_necessary;
1811  } else if (NStr::EqualNocase(necessary_str, "unnecessary")) {
1812  necessary_type = eGene_xref_necessary_type_unnecessary;
1813  }
1814 
1815  bool removed(false);
1816  CSeq_feat::TXref::iterator xref_it = edit_feat->SetXref().begin();
1817  while (xref_it != edit_feat->SetXref().end()) {
1818  if ((*xref_it)->IsSetData() && (*xref_it)->GetData().IsGene() &&
1819  s_GeneXrefMatchesSuppression((*xref_it)->GetData().GetGene(), suppr_type) &&
1820  s_GeneXrefMatchesNecessary((*xref_it)->GetData().GetGene(), *edit_feat, *scope, necessary_type)) {
1821  xref_it = edit_feat->SetXref().erase(xref_it);
1822  removed = true;
1823  }
1824  else {
1825  ++xref_it;
1826  }
1827  }
1828 
1829  if (removed) {
1830  if (edit_feat->IsSetXref() && edit_feat->GetXref().empty()) {
1831  edit_feat->ResetXref();
1832  }
1833 
1834  m_DataIter->SetModified();
1836  log << "Removed Gene xref from " << m_DataIter->GetBestDescr();
1837  x_LogFunction(log);
1838  }
1839 }
1840 
1842 {
1843  if (m_Args.size() != 2) {
1844  return false;
1845  }
1846 
1847  return (m_Args[0]->GetDataType() == CMQueryNodeValue::eString &&
1848  m_Args[1]->GetDataType() == CMQueryNodeValue::eString);
1849 }
1850 
1852  EGene_xref_necessary_type necessary_type)
1853 {
1854  bool rval(false);
1855  switch (necessary_type) {
1857  rval = true;
1858  break;
1860  rval = !CCleanup::IsGeneXrefUnnecessary(feat, scope, gene);
1861  break;
1863  rval = CCleanup::IsGeneXrefUnnecessary(feat, scope, gene);
1864  break;
1865  }
1866  return rval;
1867 }
1868 
1870 {
1871  bool rval(false);
1872  switch (suppr_type) {
1874  rval = true;
1875  break;
1877  rval = gene.IsSuppressed();
1878  break;
1880  rval = !gene.IsSuppressed();
1881  break;
1882  }
1883  return rval;
1884 }
1885 
1886 ///////////////////////////////////////////////////////////////////////////////
1887 /// class CMacroFunction_JoinShorttRNAs
1888 /// JoinShorttRNAs() - joins short (< 50bp) tRNAs and extends the corresponding genes
1889 ///
1890 static bool s_SortShorttRNAs(const CConstRef<CSeq_feat>& feat1, const CConstRef<CSeq_feat>& feat2)
1891 {
1892  const string& product1 = feat1->GetData().GetRna().GetRnaProductName();
1893  const string& product2 = feat2->GetData().GetRna().GetRnaProductName();
1894 
1895  ENa_strand strand1 = feat1->GetLocation().GetStrand();
1896  ENa_strand strand2 = feat2->GetLocation().GetStrand();
1897 
1898  const TSeqPos start1 = feat1->GetLocation().GetStart(eExtreme_Positional);
1899  const TSeqPos start2 = feat2->GetLocation().GetStart(eExtreme_Positional);
1900  if (NStr::EqualNocase(product1, product2)) {
1901  if (strand1 == strand2) {
1902  if (strand1 == eNa_strand_minus) {
1903  return (start1 > start2);
1904  }
1905  else {
1906  return (start1 < start2);
1907  }
1908  }
1909  else {
1910  return strand1 < strand2;
1911  }
1912  }
1913  return product1 < product2;
1914 }
1915 
1916 static bool s_ShouldBeMerged(const CSeq_feat& feat1, const CSeq_feat& feat2)
1917 {
1918  string product1 = feat1.GetData().GetRna().GetRnaProductName();
1919  string product2 = feat2.GetData().GetRna().GetRnaProductName();
1920 
1921  ENa_strand strand1 = feat1.GetLocation().GetStrand();
1922  ENa_strand strand2 = feat2.GetLocation().GetStrand();
1923 
1924  bool merged = NStr::EqualNocase(product1, product2) &&
1925  ((strand1 == eNa_strand_minus && strand2 == eNa_strand_minus)
1926  || (strand1 != eNa_strand_minus && strand2 != eNa_strand_minus));
1927  return merged;
1928 }
1929 
1930 DEFINE_MACRO_FUNCNAME(CMacroFunction_JoinShorttRNAs, "JoinShorttRNAs")
1931 
1932 void CMacroFunction_JoinShorttRNAs::TheFunction()
1933 {
1934  CConstRef<CObject> obj = m_DataIter->GetScopedObject().object;
1935  const CBioseq* bseq = dynamic_cast<const CBioseq*>(obj.GetPointer());
1936  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
1937  if (!bseq || !scope)
1938  return;
1939 
1940  vector<CConstRef<CSeq_feat> > tRNAFeats;
1941  CBioseq_Handle bsh = scope->GetBioseqHandle(*bseq);
1942  for (CFeat_CI feat_it(bsh, SAnnotSelector(CSeqFeatData::eSubtype_tRNA)); feat_it; ++feat_it) {
1943  const CSeq_feat& feature = *feat_it->GetOriginalSeq_feat();
1944  if (sequence::GetLength(feature.GetLocation(), scope) < 50) { // short tRNA
1945  tRNAFeats.push_back(feat_it->GetOriginalSeq_feat());
1946  }
1947  }
1948 
1949  sort(tRNAFeats.begin(), tRNAFeats.end(), s_SortShorttRNAs);
1950 
1952  CRef<CCmdComposite> cmd(new CCmdComposite("Join short tRNAs"));
1953  auto it = tRNAFeats.begin();
1954  auto modified = false;
1955  while (it != tRNAFeats.end()) {
1956  auto next = it;
1957  ++next;
1958 
1959  CRef<CSeq_loc> rnaLoc(new CSeq_loc);
1960  vector<string> comments;
1961 
1963  CRef<CSeq_loc> geneLoc(new CSeq_loc);
1964 
1965  while (next != tRNAFeats.end() && s_ShouldBeMerged(**it, **next)) {
1966  rnaLoc->Add((*next)->GetLocation());
1967  if ((*next)->IsSetComment()) {
1968  comments.push_back((*next)->GetComment());
1969  }
1970 
1971  if (gene) {
1973  if (geneNext) {
1974  geneLoc->Add(geneNext->GetLocation());
1975  CSeq_feat_Handle gNexth = scope->GetSeq_featHandle(*geneNext);
1976  CRef<CCmdComposite> delGene = GetDeleteFeatureCommand(gNexth);
1977  cmd->AddCommand(*delGene);
1978  modified = true;
1979  } else {
1980  geneLoc->Add((*next)->GetLocation());
1981  }
1982  }
1983 
1984  CSeq_feat_Handle featNexth = scope->GetSeq_featHandle(**next);
1985  CRef<CCmdComposite> delNext = GetDeleteFeatureCommand(featNexth);
1986  cmd->AddCommand(*delNext);
1987  modified = true;
1988  ++next;
1989  }
1990 
1991  if (rnaLoc->Which() != CSeq_loc::e_not_set || !comments.empty()) {
1992  CRef<CSeq_feat> newtRNA(new CSeq_feat);
1993  newtRNA->Assign(**it);
1994 
1995  rnaLoc->Add((*it)->GetLocation());
1996  rnaLoc = sequence::Seq_loc_Merge(*rnaLoc, CSeq_loc::fSortAndMerge_All, scope);
1997  newtRNA->SetLocation(*rnaLoc);
1998 
1999  if (!comments.empty()) {
2000  string origComment = (*it)->IsSetComment() ? (*it)->GetComment() : kEmptyStr;
2001  size_t index = 0;
2002  if (origComment.empty()) {
2003  origComment = comments[0];
2004  ++index;
2005  }
2006  for ( ; index < comments.size(); ++index) {
2007  edit::AddValueToString(origComment, comments[index], edit::eExistingText_append_semi);
2008  }
2009  if (!origComment.empty()) {
2010  newtRNA->SetComment(origComment);
2011  }
2012  }
2013 
2014  CSeq_feat_Handle fh = scope->GetSeq_featHandle(**it);
2015  cmd->AddCommand(*CRef<CCmdChangeSeq_feat>(new CCmdChangeSeq_feat(fh, *newtRNA)));
2016 
2017  CSeq_loc_CI loc_ci(newtRNA->GetLocation());
2018  if (!IsOssEmpty(log)) {
2019  log << "\n";
2020  }
2021  log << "Joined " << loc_ci.GetSize() << " short tRNAs with product name " << newtRNA->GetData().GetRna().GetRnaProductName();
2022  modified = true;
2023 
2024  if (geneLoc->Which() != CSeq_loc::e_not_set) {
2025  geneLoc->Add(gene->GetLocation());
2027  if (geneLoc) {
2028  CRef<CSeq_feat> newGene(new CSeq_feat);
2029  newGene->Assign(*gene);
2030  newGene->SetLocation(*geneLoc);
2031 
2032  CSeq_feat_Handle geneh = scope->GetSeq_featHandle(*gene);
2033  cmd->AddCommand(*CRef<CCmdChangeSeq_feat>(new CCmdChangeSeq_feat(geneh, *newGene)));
2034  string label;
2035  newGene->GetLocation().GetLabel(&label);
2036  log << "\n" << "Corresponding gene has been extended to " << label << "\n";
2037  modified = true;
2038  }
2039  }
2040  }
2041  it = next;
2042  }
2043 
2044  if (modified) {
2045  m_DataIter->RunCommand(cmd, m_CmdComposite);
2046  x_LogFunction(log);
2047  }
2048 }
2049 
2050 bool CMacroFunction_JoinShorttRNAs::x_ValidArguments() const
2051 {
2052  return (m_Args.empty());
2053 }
2054 
2055 ///////////////////////////////////////////////////////////////////////////////
2056 /// class CMacroFunction_ReplaceStopWithSelenocysteine
2057 /// ReplaceSelenocysteineStops();
2058 /// Replace all stops with selenocysteine (U) if the codon is TGA and the product name contains "seleno"
2059 ///
2061 
2063 {
2064  CObjectInfo oi = m_DataIter->GetEditedObject();
2066  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
2067  if (!cds_feat ||
2068  !cds_feat->GetData().IsCdregion() ||
2069  !cds_feat->IsSetProduct() ||
2070  !scope) {
2071  return;
2072  }
2073 
2074  // check if protein name contains "seleno"
2075  CBioseq_Handle protein = scope->GetBioseqHandle(cds_feat->GetProduct());
2076  if (!protein)
2077  return;
2078 
2080  if (!feat_it || !feat_it->GetData().GetProt().IsSetName()) {
2081  return;
2082  }
2083 
2084  const CProt_ref::TName& names = feat_it->GetData().GetProt().GetName();
2085  auto it = find_if(names.begin(), names.end(), [](const string& str) { return (NStr::Find(str, "seleno") != NPOS); });
2086  if (it == names.end()) {
2087  return;
2088  }
2089 
2090  // check if protein has stop codons
2092  prot_vec.SetCoding(CSeq_data::e_Ncbieaa);
2093  string prot_seq;
2094  prot_vec.GetSeqData(0, prot_vec.size(), prot_seq);
2095  if (NStr::Find(prot_seq, "*") == NPOS) {
2096  return;
2097  }
2098 
2099  // protein id and label
2100  CConstRef<CSeq_id> prot_id = protein.GetAccessSeq_id_Handle().GetSeqId();
2101  string prot_label;
2102  prot_id->GetLabel(&prot_label);
2103 
2104  CBioseq_Handle bsh = scope->GetBioseqHandle(cds_feat->GetLocation());
2106  nuc_vec.SetIupacCoding();
2107 
2108  unsigned int replaced = 0;
2110 
2112  for (size_t index = 0; index < prot_seq.size(); ++index) {
2113  if (prot_seq[index] == '*') {
2114  CRef<CSeq_loc> prot_loc = x_GetProteinLoc(*prot_id, (TSeqPos)index);
2115  CRef<CSeq_loc> nuc_loc = prot2nuc->Map(*prot_loc);
2116  if (!nuc_loc) {
2117  continue;
2118  }
2119 
2120  string codon;
2121  nuc_vec.GetSeqData(nuc_loc->GetStart(eExtreme_Biological), nuc_loc->GetStop(eExtreme_Biological) +1 , codon);
2122 
2123  if (codon == "TGA") {
2124  CRef<CCode_break> code_break(new CCode_break);
2125  code_break->SetLoc(*nuc_loc);
2126  code_break->SetAa().SetNcbieaa('U');
2127  cds_feat->SetData().SetCdregion().SetCode_break().push_back(code_break);
2128  replaced++;
2129  }
2130  else {
2131  log << "Unable to add transl_except for stop codon at position " << index + 1;
2132  log << " in protein " << prot_label << " because codon is not TGA\n";
2133  }
2134  }
2135  }
2136 
2137  if (replaced) {
2138  // retranslate CDS
2139  if (!sequence::IsPseudo(*cds_feat, *scope)) {
2141  Ref(dynamic_cast<CMacroBioData_FeatIterBase*>(m_DataIter.GetPointer()));
2142  if (!m_DataIter->HasBeenCompleted() && feat_iter) {
2143  feat_iter->SetCreateGeneralIdFlag();
2144  m_DataIter->SetCompleted();
2145  }
2146 
2147  bool transl_change = false;
2148  CRef<CCmdComposite> retransl_cmd = GetRetranslateCDSCommand(*scope, *cds_feat, transl_change, feat_iter->GetCreateGeneralIdFlag());
2149  if (retransl_cmd) {
2150  m_DataIter->RunCommand(retransl_cmd, m_CmdComposite);
2151  }
2152  }
2153 
2154  m_DataIter->SetModified();
2155  log << "Replaced " << replaced << " stops with selenocysteine.";
2156  x_LogFunction(log);
2157  }
2158 }
2159 
2161 {
2162  return (m_Args.empty());
2163 }
2164 
2166 {
2167  CRef<CSeq_id> new_id(new CSeq_id);
2168  SerialAssign(*new_id, prot_id);
2169  CRef<CSeq_point> prot_pnt(new CSeq_point(*new_id, pos));
2170 
2171  CRef<CSeq_loc> prot_loc(new CSeq_loc);
2172  prot_loc->SetPnt(*prot_pnt);
2173  return prot_loc;
2174 }
2175 
2176 ///////////////////////////////////////////////////////////////////////////////
2177 /// class CMacroFunction_RetranslateCDS
2178 /// RetranslateCDS(obey_stop_codon);
2179 ///
2180 
2181 // Changes in the function and parameter names require changes in the respective
2182 // XRC file used in the macro editor
2183 DEFINE_MACRO_FUNCNAME(CMacroFunction_RetranslateCDS, "RetranslateCDS")
2184 
2185 void CMacroFunction_RetranslateCDS::TheFunction()
2186 {
2187  CObjectInfo oi = m_DataIter->GetEditedObject();
2189  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
2190  if (!cds ||
2191  !cds->GetData().IsCdregion() ||
2192  !scope ||
2193  sequence::IsPseudo(*cds, *scope)) { // check if feature is pseudo
2194  return;
2195  }
2196 
2197  bool obey_stop_codon = m_Args[0]->GetBool();
2198  bool cds_change = (obey_stop_codon && edit::TruncateCDSAtStop(*cds, *scope)) ? true : false;
2199 
2201  Ref(dynamic_cast<CMacroBioData_FeatIterBase*>(m_DataIter.GetPointer()));
2202  if (!m_DataIter->HasBeenCompleted() && feat_iter) {
2203  feat_iter->SetCreateGeneralIdFlag();
2204  m_DataIter->SetCompleted();
2205  }
2206 
2207  bool transl_change = false;
2208  CRef<CCmdComposite> retransl_cmd = GetRetranslateCDSCommand(*scope, *cds, transl_change, feat_iter->GetCreateGeneralIdFlag());
2209  if (retransl_cmd) {
2211  m_DataIter->RunCommand(retransl_cmd, m_CmdComposite);
2212  if (cds_change || transl_change) {
2213  m_DataIter->SetModified();
2214  }
2215  log << "Retranslated " << m_DataIter->GetBestDescr();
2216  x_LogFunction(log);
2217  }
2218 }
2219 
2220 bool CMacroFunction_RetranslateCDS::x_ValidArguments() const
2221 {
2222  return (m_Args.size() == 1 && m_Args[0]->GetDataType() == CMQueryNodeValue::eBool);
2223 }
2224 
2225 ///////////////////////////////////////////////////////////////////////////////
2226 /// class CMacroFunction_MakeLocation
2227 /// Generates different type of seq-loc objects
2228 ///
2229 
2231 {
2232  CConstRef<CObject> obj = m_DataIter->GetScopedObject().object;
2233  const CBioseq* bseq = dynamic_cast<const CBioseq*>(obj.GetPointer());
2234  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
2235  if (!bseq || !scope)
2236  return false;
2237 
2238  m_Bsh = scope->GetBioseqHandle(*bseq);
2239  return (m_Bsh);
2240 }
2241 
2243 {
2244  if (index < m_Args.size()) {
2245  _ASSERT(m_Args[index]->GetDataType() == CMQueryNodeValue::eInt);
2246  if (m_Args[index]->GetInt() < 1) {
2247  NCBI_THROW(CException, eUnknown, "Negative sequence coordinate(s) provided: " + NStr::Int8ToString(m_Args[index]->GetInt()));
2248  }
2249  }
2250 }
2251 
2253 {
2254  if (!ENUM_METHOD_NAME(ENa_strand)()->IsValidName(str)) {
2255  NCBI_THROW(CException, eUnknown, "Unrecognized strand: " + str);
2256  }
2257 
2258  return (ENa_strand)ENUM_METHOD_NAME(ENa_strand)()->FindValue(str);
2259 }
2260 
2261 ///////////////////////////////////////////////////////////////////////////////
2262 /// class CMacroFunction_MakeInterval
2263 /// MakeInterval(from, to, partial5(bool), partial3(bool), "plus"|"minus")
2264 ///
2266 void CMacroFunction_MakeInterval::TheFunction()
2267 {
2268  if (!x_SetCurrentBioseq())
2269  return;
2270 
2271  x_HandleNegativeCoordinates(0);
2272  x_HandleNegativeCoordinates(1);
2273 
2274  ENa_strand strand = x_GetStrand(m_Args.back()->GetString());
2275  TSeqPos from = (TSeqPos)m_Args[0]->GetInt() - 1;
2276  TSeqPos to = (TSeqPos)m_Args[1]->GetInt() - 1;
2277  if (from > to) {
2278  swap(from, to);
2279  }
2280  if (to > m_Bsh.GetBioseqLength() - 1) {
2281  to = m_Bsh.GetBioseqLength() - 1;
2282  }
2283  CRef<CSeq_loc> location = m_Bsh.GetRangeSeq_loc(from, to, strand);
2284  if (m_Args[2]->GetBool()) {
2285  location->SetPartialStart(true, eExtreme_Biological);
2286  }
2287  if (m_Args[3]->GetBool()) {
2288  location->SetPartialStop(true, eExtreme_Biological);
2289  }
2290 
2291  CObjectInfo objInfo(location, location->GetTypeInfo());
2292  ResolveIdentToObjects(objInfo, kEmptyStr, m_Result.GetNCObject());
2293 }
2294 
2296 {
2297  if (m_Args.size() != 5)
2298  return false;
2299 
2300  bool good = false;
2301  good = m_Args[0]->GetDataType() == CMQueryNodeValue::eInt
2302  && m_Args[1]->GetDataType() == CMQueryNodeValue::eInt
2303  && m_Args[2]->GetDataType() == CMQueryNodeValue::eBool
2304  && m_Args[3]->GetDataType() == CMQueryNodeValue::eBool
2305  && m_Args[4]->GetDataType() == CMQueryNodeValue::eString;
2306  return good;
2307 }
2308 
2309 ///////////////////////////////////////////////////////////////////////////////
2310 /// class CMacroFunction_MakeWholeSeqInterval
2311 /// MakeWholeSeqInterval(partial5, partial3, "plus" | "minus")
2312 ///
2314 
2316 {
2317  if (!x_SetCurrentBioseq())
2318  return;
2319 
2320  ENa_strand strand = x_GetStrand(m_Args.back()->GetString());
2321  CRef<CSeq_loc> location = m_Bsh.GetRangeSeq_loc(0, 0, strand);
2322  if (m_Args[0]->GetBool()) {
2323  location->SetPartialStart(true, eExtreme_Biological);
2324  }
2325  if (m_Args[1]->GetBool()) {
2326  location->SetPartialStop(true, eExtreme_Biological);
2327  }
2328 
2329  CObjectInfo objInfo(location, location->GetTypeInfo());
2330  ResolveIdentToObjects(objInfo, kEmptyStr, m_Result.GetNCObject());
2331 }
2332 
2334 {
2335  if (m_Args.size() != 3)
2336  return false;
2337 
2338  bool good = false;
2339  good = m_Args[0]->GetDataType() == CMQueryNodeValue::eBool
2340  && m_Args[1]->GetDataType() == CMQueryNodeValue::eBool
2341  && m_Args[2]->GetDataType() == CMQueryNodeValue::eString;
2342  return good;
2343 }
2344 
2345 ///////////////////////////////////////////////////////////////////////////////
2346 /// class CMacroFunction_MakePoint
2347 /// MakePoint(point(integer), partial5, partial3, strand)
2348 ///
2350 
2351 void CMacroFunction_MakePoint::TheFunction()
2352 {
2353  if (!x_SetCurrentBioseq())
2354  return;
2355 
2356  x_HandleNegativeCoordinates(0);
2357  ENa_strand strand = x_GetStrand(m_Args.back()->GetString());
2358  TSeqPos point = (TSeqPos)m_Args[0]->GetInt() - 1;
2359  if (point > m_Bsh.GetBioseqLength() - 1) {
2360  point = m_Bsh.GetBioseqLength() - 1;
2361  }
2362 
2364  location->SetPnt().SetPoint(point);
2365  location->SetPnt().SetId().Assign(*m_Bsh.GetCompleteBioseq()->GetFirstId());
2366  location->SetPnt().SetStrand(strand);
2367  if (m_Args[1]->GetBool()) {
2368  location->SetPartialStart(true, eExtreme_Biological);
2369  }
2370  if (m_Args[2]->GetBool()) {
2371  location->SetPartialStop(true, eExtreme_Biological);
2372  }
2373 
2374  CObjectInfo objInfo(location, location->GetTypeInfo());
2375  ResolveIdentToObjects(objInfo, kEmptyStr, m_Result.GetNCObject());
2376 }
2377 
2379 {
2380  if (m_Args.size() != 4)
2381  return false;
2382 
2383  bool good = false;
2384  good = m_Args[0]->GetDataType() == CMQueryNodeValue::eInt
2385  && m_Args[1]->GetDataType() == CMQueryNodeValue::eBool
2386  && m_Args[2]->GetDataType() == CMQueryNodeValue::eBool
2387  && m_Args[3]->GetDataType() == CMQueryNodeValue::eString;
2388  return good;
2389 }
2390 
2391 
2392 /// class CMacroFunction_ApplyFeature
2393 /// Generates different types of apply feature commands
2394 
2396 {
2397  _ASSERT(!m_NewFeat.IsNull());
2398  bool add_redundant = m_Args[index]->GetBool();
2399  if (add_redundant) {
2400  return true;
2401  }
2402 
2403  _ASSERT(m_Bsh.GetCompleteBioseq());
2404  CFeat_CI feat_it(m_Bsh, m_NewFeat->GetData().GetSubtype());
2405  return !(feat_it);
2406 }
2407 
2409 {
2410  CMQueryNodeValue::TObs location_obj;
2411  x_GetObjectsFromRef(location_obj, index);
2412  if (location_obj.empty()) {
2413  return false;
2414  }
2415 
2416  if (NStr::EqualCase(location_obj.front().field.GetName(), "Seq-loc")) {
2417  m_Location.Reset(CTypeConverter<CSeq_loc>::SafeCast(location_obj.front().field.GetObjectPtr()));
2418  }
2419 
2420  if (!m_Location) {
2421  NCBI_THROW(CMacroExecException, eVarNotResolved, "Location run-time variable could not be resolved");
2422  }
2423 
2424  _ASSERT(!m_NewFeat.IsNull());
2425  m_NewFeat->SetLocation().Assign(*m_Location);
2426  if (m_NewFeat->GetLocation().IsPartialStart(objects::eExtreme_Biological)
2427  || m_NewFeat->GetLocation().IsPartialStop(objects::eExtreme_Biological)) {
2428  m_NewFeat->SetPartial(true);
2429  }
2430  return true;
2431 }
2432 
2434 {
2435  _ASSERT(!m_NewFeat.IsNull());
2436  size_t arg_size = m_Args.size();
2437  while (index < arg_size) {
2438  const string field = m_Args[index]->GetString();
2439  if (field == "qual.qual") { // it will be a GB-qualifier
2440  const string qualifier = m_Args[++index]->GetString();
2441  index += 2;
2442  const string value = (index < arg_size) ? m_Args[index]->GetString() : kEmptyStr;
2443  CRef<CGb_qual> new_gbqual(new CGb_qual(qualifier, value));
2444  m_NewFeat->SetQual().push_back(new_gbqual);
2445  ++index;
2446  }
2447  else {
2448  CObjectInfo oi(m_NewFeat, m_NewFeat->GetTypeInfo());
2449  CMQueryNodeValue::TObs res_oi;
2450  SetFieldsByName(&res_oi, oi, field);
2451 
2452  ++index;
2453  if (index < arg_size) {
2454  CMQueryNodeValue& new_value = *m_Args[index];
2456  if (it->field.GetTypeFamily() == eTypeFamilyContainer) {
2457  CObjectInfo new_oi(it->field.AddNewElement());
2458  SetSimpleTypeValue(new_oi, new_value);
2459  } else {
2460  SetSimpleTypeValue(it->field, new_value);
2461  }
2462  }
2463  ++index;
2464  }
2465  }
2466  }
2467 }
2468 
2469 ///////////////////////////////////////////////////////////////////////////////
2470 /// ApplyCDS(protein_name, protein_description, frame("best"|1|2|3), location(object), add_redundant(bool), add_mRNA(bool) [,qualifier_name][,qualifier_value])
2471 /// qualifier_name should be specified by its asn path, relative to the CDS Seq-feat
2472 ///
2474 void CMacroFunction_ApplyCDS::TheFunction()
2475 {
2476  CConstRef<CObject> obj = m_DataIter->GetScopedObject().object;
2477  const CBioseq* bseq = dynamic_cast<const CBioseq*>(obj.GetPointer());
2478  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
2479  m_Bsh = scope->GetBioseqHandle(*bseq);
2480  if (!bseq || !scope || bseq->IsAa())
2481  return;
2482 
2483  m_NewFeat = Ref(new CSeq_feat());
2484  m_NewFeat->SetData().SetCdregion();
2485 
2486  // add appropriate genetic code
2488  if (code) {
2489  m_NewFeat->SetData().SetCdregion().SetCode(*code);
2490  }
2491 
2492  bool find_best_frame = false;
2493  size_t fr_index = 2;
2495  if (m_Args[fr_index]->GetDataType() == CMQueryNodeValue::eString) {
2496  if (NStr::EqualNocase(m_Args[fr_index]->GetString(), "best")) {
2497  find_best_frame = true;
2498  }
2499  else {
2500  NCBI_THROW(CException, eUnknown, "Wrong frame specified (try \"best\")");
2501  }
2502  }
2503  else {
2504  switch (m_Args[fr_index]->GetInt()) {
2505  case 1:
2506  codon_start = CCdregion::eFrame_one;
2507  break;
2508  case 2:
2509  codon_start = CCdregion::eFrame_two;
2510  break;
2511  case 3:
2512  codon_start = CCdregion::eFrame_three;
2513  break;
2514  default:
2515  NCBI_THROW(CException, eUnknown, "Wrong frame specified: " + NStr::Int8ToString(m_Args[fr_index]->GetInt()));
2516  }
2517  }
2518 
2519  if (!x_SetLocation(3) || !x_ShouldAddRedundant(4))
2520  return;
2521 
2522  x_SetAdditionalFields(6);
2523 
2524  bool add_mRNA = m_Args[5]->GetBool();
2525  const string& protein_name = m_Args[0]->GetString();
2526  const string& protein_descr = m_Args[1]->GetString();
2527 
2528  CSeq_entry_Handle seh = m_Bsh.GetSeq_entry_Handle();
2529  CRef<CCmdComposite> cmd(new CCmdComposite("Add CDS"));
2530  if (add_mRNA) {
2531  CRef<CSeq_feat> new_mrna(new CSeq_feat());
2532  new_mrna->SetData().SetRna().SetType(CRNA_ref::eType_mRNA);
2533  new_mrna->SetLocation(*m_Location);
2535  new_mrna->SetData().SetRna().SetExt().SetName(protein_name);
2536  cmd->AddCommand(*(CRef<CCmdCreateFeat>(new CCmdCreateFeat(seh, *new_mrna))));
2537  }
2538 
2539  if (m_Location->IsPnt()) {
2540  m_NewFeat->SetData().SetCdregion().SetFrame(CCdregion::eFrame_not_set);
2541  }
2542  else {
2543  if (find_best_frame) {
2544  bool ambiguous = false;
2545  m_NewFeat->SetData().SetCdregion().SetFrame(CSeqTranslator::FindBestFrame(*m_NewFeat, m_Bsh.GetScope(), ambiguous));
2546  }
2547  else {
2548  m_NewFeat->SetData().SetCdregion().SetFrame(codon_start);
2549  }
2550  bool create_general_only = objects::edit::IsGeneralIdProtPresent(m_Bsh.GetTopLevelEntry());
2551  CRef<CSeq_entry> protein_entry = CreateTranslatedProteinSequence(m_NewFeat, m_Bsh, create_general_only);
2553  m_NewFeat->GetLocation().IsPartialStart(eExtreme_Biological),
2554  m_NewFeat->GetLocation().IsPartialStop(eExtreme_Biological));
2555 
2556  if (!protein_name.empty()) {
2557  prot->SetData().SetProt().SetName().push_back(protein_name);
2558  }
2559  if (!protein_descr.empty()) {
2560  prot->SetData().SetProt().SetDesc(protein_descr);
2561  }
2562 
2563  CCleanup cleanup;
2564  cleanup.BasicCleanup(*prot);
2565  cmd->AddCommand(*CRef<CCmdAddSeqEntry>(new CCmdAddSeqEntry(protein_entry, seh)));
2566  }
2567 
2568  CCleanup cleanup;
2569  cleanup.BasicCleanup(*m_NewFeat);
2570  cmd->AddCommand(*CRef<CCmdCreateFeat>(new CCmdCreateFeat(seh, *m_NewFeat)));
2571 
2572  if (cmd) {
2573  m_DataIter->RunCommand(cmd, m_CmdComposite);
2574 
2576  string best_id;
2577  CWriteUtil::GetBestId(CSeq_id_Handle::GetHandle(*(m_Bsh.GetCompleteBioseq()->GetFirstId())), m_Bsh.GetScope(), best_id);
2578  log << "Added CDS feature to " << best_id;
2579  x_LogFunction(log);
2580  }
2581 }
2582 
2584 {
2585  if (m_Args.size() < 6)
2586  return false;
2587 
2588  bool good = m_Args[0]->IsString()
2589  && m_Args[1]->IsString()
2590  && (m_Args[2]->IsString() || m_Args[2]->IsInt())
2591  && m_Args[3]->IsRef()
2592  && m_Args[4]->IsBool()
2593  && m_Args[5]->IsBool();
2594 
2595  if (m_Args.size() > 6) {
2596  for (size_t index = 6; index < m_Args.size(); ++index) {
2597  if (!m_Args[index]->IsString()) {
2598  return false;
2599  }
2600  }
2601  }
2602  return good;
2603 }
2604 
2605 ///////////////////////////////////////////////////////////////////////////////
2606 /// ApplyRNA(type, rna_name, location(object), add_redundant(bool) [,qualifier_name][,qualifier_value])
2607 /// qualifier_name should be specified by its asn path, relative to the Seq-feat
2608 /// Type of RNA can be one of: preRNA, mRNA, tRNA, rRNA, ncRNA, tmRNA, miscRNA
2609 ///
2611 void CMacroFunction_ApplyRNA::TheFunction()
2612 {
2613  CConstRef<CObject> obj = m_DataIter->GetScopedObject().object;
2614  const CBioseq* bseq = dynamic_cast<const CBioseq*>(obj.GetPointer());
2615  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
2616  m_Bsh = scope->GetBioseqHandle(*bseq);
2617  if (!bseq || !scope || bseq->IsAa())
2618  return;
2619 
2620  CRNA_ref::EType rna_type = NMacroUtil::GetRNAType(m_Args[0]->GetString());
2621  if (rna_type == CRNA_ref::eType_unknown) {
2622  NCBI_THROW(CException, eUnknown, "Wrong type of RNA specified: " + m_Args[0]->GetString());
2623  }
2624 
2625  CRef<CRNA_ref> rna_ref(new CRNA_ref());
2626  rna_ref->SetType(rna_type);
2627  const string& rna_name = m_Args[1]->GetString();
2628  string remainder;
2629  rna_ref->SetRnaProductName(rna_name, remainder);
2630 
2631  m_NewFeat = Ref(new CSeq_feat());
2632  m_NewFeat->SetData().SetRna().Assign(*rna_ref);
2633 
2634  if (!x_SetLocation(2) || !x_ShouldAddRedundant(3))
2635  return;
2636 
2637  x_SetAdditionalFields(4);
2638  CCleanup cleanup;
2639  cleanup.BasicCleanup(*m_NewFeat);
2640  CSeq_entry_Handle seh = m_Bsh.GetSeq_entry_Handle();
2641  CRef<CCmdComposite> cmd(new CCmdComposite("Add RNA"));
2642  cmd->AddCommand(*CRef<CCmdCreateFeat>(new CCmdCreateFeat(seh, *m_NewFeat)));
2643 
2644  if (cmd) {
2645  m_DataIter->RunCommand(cmd, m_CmdComposite);
2646 
2648  string best_id;
2649  CWriteUtil::GetBestId(CSeq_id_Handle::GetHandle(*(m_Bsh.GetCompleteBioseq()->GetFirstId())), m_Bsh.GetScope(), best_id);
2650  log << "Added " << m_Args[0]->GetString() << " feature to " << best_id;
2651  x_LogFunction(log);
2652  }
2653 }
2654 
2656 {
2657  if (m_Args.size() < 4)
2658  return false;
2659 
2660  bool good = m_Args[0]->GetDataType() == CMQueryNodeValue::eString
2661  && m_Args[1]->GetDataType() == CMQueryNodeValue::eString
2662  && m_Args[2]->GetDataType() == CMQueryNodeValue::eRef
2663  && m_Args[3]->GetDataType() == CMQueryNodeValue::eBool;
2664 
2665  if (m_Args.size() > 4) {
2666  for (size_t index = 4; index < m_Args.size(); ++index) {
2667  if (m_Args[index]->GetDataType() != CMQueryNodeValue::eString) {
2668  return false;
2669  }
2670  }
2671  }
2672  return good;
2673 }
2674 
2675 
2676 ///////////////////////////////////////////////////////////////////////////////
2677 /// class CMacroFunction_ApplyGene
2678 /// ApplyGene(location [,qualifier_name][,qualifier_value])
2679 /// Different from ApplyFeature() function as it always applies a gene to the sequence
2680 /// Used mostly together with ApplyCDS/ApplyRNA/ApplyFeature functions to create an additional gene
2681 ///
2683 
2684 void CMacroFunction_ApplyGene::TheFunction()
2685 {
2686  CConstRef<CObject> obj = m_DataIter->GetScopedObject().object;
2687  const CBioseq* bseq = dynamic_cast<const CBioseq*>(obj.GetPointer());
2688  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
2689  m_Bsh = scope->GetBioseqHandle(*bseq);
2690  // don't create gene if the selected sequence is protein
2691  if (!bseq || !scope || bseq->IsAa())
2692  return;
2693 
2694  m_NewFeat = Ref(new CSeq_feat);
2695  if (!x_SetLocation(0))
2696  return;
2697 
2698  x_SetAdditionalFields(1);
2699 
2700  CSeq_entry_Handle seh = m_Bsh.GetSeq_entry_Handle();
2701  CRef<CCmdComposite> cmd(new CCmdComposite("Add Gene"));
2702  cmd->AddCommand(*CRef<CCmdCreateFeat>(new CCmdCreateFeat(seh, *m_NewFeat)));
2703 
2704  if (cmd) {
2705  m_DataIter->RunCommand(cmd, m_CmdComposite);
2707  string best_id;
2708  CWriteUtil::GetBestId(CSeq_id_Handle::GetHandle(*(m_Bsh.GetCompleteBioseq()->GetFirstId())), m_Bsh.GetScope(), best_id);
2709  log << "Added Gene feature to " << best_id;
2710  x_LogFunction(log);
2711  }
2712 }
2713 
2715 {
2716  if (m_Args.empty())
2717  return false;
2718 
2719  bool good = m_Args[0]->GetDataType() == CMQueryNodeValue::eRef;
2720 
2721  if (m_Args.size() > 1) {
2722  for (size_t index = 1; index < m_Args.size(); ++index) {
2723  if (m_Args[index]->GetDataType() != CMQueryNodeValue::eString) {
2724  return false;
2725  }
2726  }
2727  }
2728  return good;
2729 }
2730 
2731 ///////////////////////////////////////////////////////////////////////////////
2732 /// CMacroFunction_ApplyOtherFeature
2733 /// ApplyFeature(type, name, location, add_redundant(bool) [,qualifier_name][,qualifier_value])
2734 /// Example:
2735 /// ApplyFeature("data.prot.name", "new protein", location, true, "data.prot.processed", "preprotein")
2736 /// ApplyFeature("data.psec-str", "helix", location, false)
2737 /// ApplyFeature("data.imp.key", "misc_feature", location, true);
2738 /// ApplyFeature("data.gene.locus", "", location, true, "data.gene.desc", "gene description")
2739 ///
2742 {
2743  CConstRef<CObject> obj = m_DataIter->GetScopedObject().object;
2744  const CBioseq* bseq = dynamic_cast<const CBioseq*>(obj.GetPointer());
2745  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
2746  m_Bsh = scope->GetBioseqHandle(*bseq);
2747  if (!bseq || !scope)
2748  return;
2749 
2750  m_NewFeat = Ref(new CSeq_feat);
2751  CObjectInfo oi(m_NewFeat, m_NewFeat->GetTypeInfo());
2752  CMQueryNodeValue::TObs res_oi;
2753  if (!SetFieldsByName(&res_oi, oi, m_Args[0]->GetString())) {
2754  NCBI_THROW(CException, eUnknown, "Feature " + m_Args[0]->GetString() + " could not be set");
2755  }
2756 
2757  CMQueryNodeValue& new_value = *m_Args[1];
2758  const string& new_str = m_Args[1]->GetString();
2760 
2761  CObjectInfo set_oi = it->field;
2762  switch (set_oi.GetTypeFamily()) {
2763  case eTypeFamilyPrimitive:
2764  if (!SetSimpleTypeValue(it->field, new_value)) {
2765  NCBI_THROW(CException, eUnknown, "Value " + new_str + " could not be set");
2766  }
2767  break;
2768  case eTypeFamilyContainer: {
2771 
2772  if (objs.empty()) { // add new element when the container is empty
2773  CObjectInfo new_oi(set_oi.AddNewElement());
2774  if (!SetQualStringValue(new_oi, new_str)) {
2775  NCBI_THROW(CException, eUnknown, "Value " + new_str + " could not be set");
2776  }
2777  }
2778  break;
2779  }
2780  default:
2781  NCBI_THROW(CException, eUnknown, "Value " + new_str + " could not be set");
2782  }
2783  }
2784 
2785  if (!x_SetLocation(2) || !x_ShouldAddRedundant(3))
2786  return;
2787 
2788  x_SetAdditionalFields(4);
2789 
2790  CSeq_entry_Handle seh = m_Bsh.GetSeq_entry_Handle();
2791  CRef<CCmdComposite> cmd(new CCmdComposite("Add Feature"));
2792  cmd->AddCommand(*CRef<CCmdCreateFeat>(new CCmdCreateFeat(seh, *m_NewFeat)));
2793 
2794  if (cmd) {
2795  m_DataIter->RunCommand(cmd, m_CmdComposite);
2796 
2798  string best_id;
2799  CWriteUtil::GetBestId(CSeq_id_Handle::GetHandle(*(m_Bsh.GetCompleteBioseq()->GetFirstId())), m_Bsh.GetScope(), best_id);
2800  log << "Added feature to " << best_id;
2801  x_LogFunction(log);
2802  }
2803 }
2804 
2806 {
2807  if (m_Args.size() < 4)
2808  return false;
2809 
2810  bool good = m_Args[0]->IsString() && m_Args[1]->IsString() && m_Args[2]->IsRef() && m_Args[3]->IsBool();
2811 
2812  if (m_Args.size() > 4) {
2813  for (size_t index = 4; index < m_Args.size(); ++index) {
2814  if (m_Args[index]->GetDataType() != CMQueryNodeValue::eString) {
2815  return false;
2816  }
2817  }
2818  }
2819  return good;
2820 }
2821 
2822 
2823 ///////////////////////////////////////////////////////////////////////////////
2824 /// class CMacroFunction_RestoreRNAEditing
2825 /// RestoreRNAEditing(protein_name)
2826 ///
2827 DEFINE_MACRO_FUNCNAME(CMacroFunction_RestoreRNAEditing, "RestoreRNAEditing");
2828 
2829 void CMacroFunction_RestoreRNAEditing::TheFunction()
2830 {
2831  CObjectInfo oi = m_DataIter->GetEditedObject();
2833  CRef<CScope> scope = m_DataIter->GetScopedObject().scope;
2834  if (!edit_feat || !scope || !(edit_feat->IsSetData() && edit_feat->GetData().IsCdregion()))
2835  return;
2836 
2837  string prot_name = m_Args[0]->GetString();
2838  NStr::TruncateSpacesInPlace(prot_name);
2839 
2840  bool good_cds = false;
2841  CBioseq_Handle prot_bsh;
2842  string prot_seq;
2843 
2844  if (edit_feat->IsSetProduct()) {
2845  const CSeq_id* seq_id = edit_feat->GetProduct().GetId();
2846  if (seq_id) {
2847  prot_bsh = scope->GetBioseqHandle(*seq_id);
2848  if (prot_bsh) {
2849  CSeqVector prot_vec(*(prot_bsh.GetCompleteBioseq()), scope);
2850  prot_vec.SetCoding(CSeq_data::e_Ncbieaa);
2851  prot_vec.GetSeqData(0, prot_vec.size(), prot_seq);
2852 
2853  if (!prot_seq.empty() && prot_seq.front() != 'M') {
2854  CFeat_CI prot_feat_ci(prot_bsh, SAnnotSelector(CSeqFeatData::eSubtype_prot));
2855  if (prot_feat_ci) {
2856  CSeq_feat_Handle prot_fh = prot_feat_ci->GetSeq_feat_Handle();
2857  if (prot_fh.IsSetData() && prot_fh.GetData().IsProt()) {
2858  FOR_EACH_NAME_ON_PROTREF(name_it, prot_fh.GetData().GetProt()) {
2859  if (prot_name == *name_it) {
2860  good_cds = true;
2861  break;
2862  }
2863  }
2864  }
2865  }
2866  }
2867  }
2868  }
2869  }
2870 
2871  if (!good_cds)
2872  return;
2873 
2874  // first, modify the coding region
2875  if (CCleanup::FixRNAEditingCodingRegion(*edit_feat)) {
2876  m_DataIter->SetModified();
2877  }
2878 
2879  // then, update the protein sequence:
2880  CRef<CCmdComposite> upd_cmd(new CCmdComposite("Update protein sequence"));
2881 
2882  CRef<objects::CSeq_inst> new_inst(new objects::CSeq_inst());
2883  new_inst->Assign(prot_bsh.GetInst());
2884  new_inst->ResetSeq_data();
2885 
2886  prot_seq[0] = 'M';
2887  new_inst->ResetExt();
2888  new_inst->SetRepr(objects::CSeq_inst::eRepr_raw);
2889  new_inst->SetSeq_data().SetNcbieaa().Set(prot_seq);
2890  new_inst->SetLength(TSeqPos(prot_seq.length()));
2891  new_inst->SetMol(CSeq_inst::eMol_aa);
2892  CRef<CCmdChangeBioseqInst> chgInst(new CCmdChangeBioseqInst(prot_bsh, *new_inst));
2893  upd_cmd->AddCommand(*chgInst);
2894 
2895  if (upd_cmd) {
2896  m_DataIter->RunCommand(upd_cmd, m_CmdComposite);
2897  }
2898 
2900  log << m_DataIter->GetBestDescr() << " restored RNA editing";
2901  x_LogFunction(log);
2902 }
2903 
2904 bool CMacroFunction_RestoreRNAEditing::x_ValidArguments() const
2905 {
2906  return (m_Args.size() == 1 && m_Args[0]->IsString());
2907 }
2908 
2909 
2910 END_SCOPE(macro)
2912 
2913 /* @} */
static CRef< CScope > m_Scope
User-defined methods of the data storage class.
User-defined methods of the data storage class.
@ eExtreme_Positional
numerical value
Definition: Na_strand.hpp:63
@ eExtreme_Biological
5' and 3'
Definition: Na_strand.hpp:62
User-defined methods of the data storage class.
User-defined methods of the data storage class.
User-defined methods of the data storage class.
User-defined methods of the data storage class.
User-defined methods of the data storage class.
User-defined methods of the data storage class.
User-defined methods of the data storage class.
bool TruncateCDSAtStop(CSeq_feat &cds, CScope &scope)
TruncateCDSAtStop A function to truncate a CDS location after the first stop codon in the protein tra...
Definition: cds_fix.cpp:786
bool IsGeneralIdProtPresent(objects::CSeq_entry_Handle tse)
CRef< CGenetic_code > GetGeneticCodeForBioseq(CBioseq_Handle bh)
GetGeneticCodeForBioseq A function to construct the appropriate CGenetic_code object to use when cons...
Definition: cds_fix.cpp:707
static bool s_IsBioseqGood_Strict(const objects::CBioseq_Handle &bsh)
CBioseq_Handle –.
const CSeq_id * GetFirstId() const
Definition: Bioseq.cpp:271
bool IsNa(void) const
Definition: Bioseq.cpp:345
bool IsAa(void) const
Definition: Bioseq.cpp:350
static bool IsGeneXrefUnnecessary(const CSeq_feat &sf, CScope &scope, const CGene_ref &gene_xref)
Calculates whether a Gene-xref is unnecessary (because it refers to the same gene as would be calcula...
Definition: cleanup.cpp:744
static bool FixRNAEditingCodingRegion(CSeq_feat &cds)
From GB-7563 An action has been requested that will do the following: 1.
Definition: cleanup.cpp:4849
void AddCommand(IEditCommand &command)
CCode_break –.
Definition: Code_break.hpp:66
static CRef< CConvertFeatureBase > Create(objects::CSeqFeatData::ESubtype subtype_from, objects::CSeqFeatData::ESubtype subtype_to)
static const string s_PlaceOnProt
static const string s_RemoveTranscriptID
static const string s_SiteType
virtual CRef< CCmdComposite > Convert(const objects::CSeq_feat &orig, bool keep_orig, objects::CScope &scope)
TOptions & SetOptions()
static const string s_BondType
virtual string GetDescription()
static const string s_NcrnaClass
static const string s_RemovemRNA
vector< CRef< CConversionOption > > TOptions
static const string s_RemoveGene
CFeat_CI –.
Definition: feat_ci.hpp:64
@Gb_qual.hpp User-defined methods of the data storage class.
Definition: Gb_qual.hpp:61
bool IsSuppressed(void) const
Definition: Gene_ref.cpp:75
Subclass of the IQueryParseUserObject which is held as the user-defined object in each CQueryParseNod...
Definition: macro_exec.hpp:71
CMacroBioData_FeatIterBase - iterates over any type of features.
class CMacroExecException
Definition: macro_ex.hpp:146
class CMacroExecException
Definition: macro_ex.hpp:196
CObjectInfo –.
Definition: objectinfo.hpp:597
static bool IsValidECNumberFormat(const string &ecno)
Verify correct form of EC number.
Definition: Prot_ref.cpp:257
static const string & GetECNumberReplacement(const string &old_ecno)
Return a replaced EC number's replacement.
Definition: Prot_ref.cpp:204
EECNumberStatus
Enzyme Commission number status.
Definition: Prot_ref.hpp:63
@ eEC_replaced
Obsolete synonym for some other EC number.
Definition: Prot_ref.hpp:66
@ eEC_ambiguous
Valid wildcard for a broader family.
Definition: Prot_ref.hpp:65
@ eEC_specific
Specifically identifies a valid classification.
Definition: Prot_ref.hpp:64
static EECNumberStatus GetECNumberStatus(const string &ecno)
Determine an EC number's validity and specificity.
Definition: Prot_ref.cpp:190
@RNA_ref.hpp User-defined methods of the data storage class.
Definition: RNA_ref.hpp:54
string GetRnaProductName(void) const
Definition: RNA_ref.cpp:145
void SetRnaProductName(const string &product, string &remainder)
Definition: RNA_ref.cpp:225
CScope –.
Definition: scope.hpp:92
ESubtype GetSubtype(void) const
static E_Choice GetTypeFromSubtype(ESubtype subtype)
CSeqVector –.
Definition: seq_vector.hpp:65
CSeq_entry_Handle –.
Definition: Seq_entry.hpp:56
CSeq_feat_Handle –.
namespace ncbi::objects::
Definition: Seq_feat.hpp:58
void SetGeneXref(CGene_ref &value)
Definition: Seq_feat.cpp:192
Seq-loc iterator class – iterates all intervals from a seq-loc in the correct order.
Definition: Seq_loc.hpp:453
CSeq_loc_Mapper –.
static bool GetBestId(CSeq_id_Handle, CScope &, string &)
Definition: write_util.cpp:675
Definition: set.hpp:45
iterator_bool insert(const value_type &val)
Definition: set.hpp:149
size_type size() const
Definition: set.hpp:132
bool empty() const
Definition: set.hpp:133
CRef< objects::CSeq_entry > CreateTranslatedProteinSequence(CRef< objects::CSeq_feat > cds, objects::CBioseq_Handle nuc_h, bool create_general_only, int *offset=nullptr)
CRef< objects::CSeq_feat > AddProteinFeatureToProtein(CRef< objects::CSeq_entry > protein, bool partial5, bool partial3)
static const string kConversionNotSupported
constexpr auto end(const ct_const_array< T, N > &in) noexcept
static auto & FindOrgNames
static CS_COMMAND * cmd
Definition: ct_dynamic.c:26
static void cleanup(void)
Definition: ct_dynamic.c:30
static const struct name_t names[]
static DLIST_TYPE *DLIST_NAME() next(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:56
static const char * str(char *buf, int n)
Definition: stats.c:84
static const char location[]
Definition: config.c:97
unsigned int TSeqPos
Type for sequence locations and lengths.
Definition: ncbimisc.hpp:875
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
void swap(NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair1, NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair2)
Definition: ncbimisc.hpp:1508
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
#define NCBI_RETHROW2(prev_exception, exception_class, err_code, message, extra)
Re-throw exception with extra parameter.
Definition: ncbiexpt.hpp:1761
@ eUnknown
Unknown exception.
Definition: ncbiexpt.hpp:887
void x_FixProteinNames(objects::CProt_ref &prot, const vector< string > &taxnames)
static bool s_Set5EndPartial(objects::CSeq_feat &feat, objects::CScope &scope, const string &descr, bool extend5=false)
CRef< objects::CScope > m_Scope
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
void x_SetConvertOptions(CRef< CConvertFeatureBase > converter)
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
static bool s_Clear5EndPartial(objects::CSeq_feat &feat, objects::CScope &scope, const string &descr)
static ECdsFrame s_GetFrameFromName(const string &name)
static bool s_ShouldBeMerged(const CSeq_feat &feat1, const CSeq_feat &feat2)
objects::CSeqFeatData::ESubtype GetFeatSubtype(const string &feat_type)
Definition: macro_util.cpp:350
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
static bool s_ConvertLocationType(objects::CSeq_feat &feat, objects::CScope &scope, const string &descr)
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
CConstRef< objects::CSeq_feat > m_Origfeat
list< SResolvedField > TObs
Definition: macro_exec.hpp:92
void x_RetranslateCDS(CNcbiOstrstream &log)
static string s_FixProteinNameFormat(const string &protein, const vector< string > &taxnames)
void Dereference()
If it is a reference it is resolved to the first non reference type in the hierarchy.
Definition: macro_exec.cpp:94
static bool s_GeneXrefMatchesSuppression(const objects::CGene_ref &gene, objects::EGene_xref_suppression_type suppr_type)
bool ResolveIdentToObjects(const CObjectInfo &oi, const string &identifier, CMQueryNodeValue &v)
Resolve name to the list of objects.
bool SetSimpleTypeValue(CObjectInfo &oi, const CMQueryNodeValue &value, objects::edit::EExistingText existing_text=objects::edit::eExistingText_replace_old)
Set single node data to the node specified by parameter of type CObjectInfo.
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
bool x_SetCurrentBioseq()
class CMacroFunction_MakeLocation Generates different type of seq-loc objects
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
CRef< objects::CSeq_feat > m_Seqfeat
const string & GetString() const
Definition: macro_exec.hpp:139
EType GetDataType() const
Definition: macro_exec.hpp:122
void GetPrimitiveObjectInfos(CMQueryNodeValue::TObs &objs, const CMQueryNodeValue::SResolvedField &info)
Definition: macro_util.cpp:212
objects::CRNA_ref::EType GetRNAType(const string &rna_type)
Definition: macro_util.cpp:484
bool x_ShouldAddRedundant(size_t index)
class CMacroFunction_ApplyFeature Generates different types of apply feature commands
objects::CBioseq_Handle m_Bsh
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
bool GetBool() const
Definition: macro_exec.hpp:141
static objects::ENa_strand s_GetStrandFromString(const string &str)
void x_RetranslateCDSAdjustGene(const string &descr)
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
static bool s_GeneXrefMatchesNecessary(const objects::CGene_ref &gene, const objects::CSeq_feat &feat, objects::CScope &scope, objects::EGene_xref_necessary_type necessary_type)
bool SetFieldsByName(CMQueryNodeValue::TObs *results, CObjectInfo &oi_i, const string &field_name)
Resolve not necessarily existing dot qualified ASN.1 name (field_name) starting from the object infor...
static bool s_SetBothEndsPartial(objects::CSeq_feat &feat, objects::CScope &scope, const string &descr, bool extend=false)
void x_GetObjectsFromRef(CMQueryNodeValue::TObs &objects, const size_t &index)
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
bool GetLocusTagFromProtRef(const objects::CSeq_feat &prot_feat, objects::CScope &scope, string &locus_tag)
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
static bool s_SortShorttRNAs(const CConstRef< CSeq_feat > &feat1, const CConstRef< CSeq_feat > &feat2)
class CMacroFunction_JoinShorttRNAs JoinShorttRNAs() - joins short (< 50bp) tRNAs and extends the cor...
objects::ENa_strand x_GetStrand(const string &str)
CRef< objects::CSeq_loc > m_Location
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
static bool s_Clear3EndPartial(objects::CSeq_feat &feat, objects::CScope &scope, const string &descr)
DEFINE_MACRO_FUNCNAME(CMacroFunction_TrimStopFromCompleteCDS, "TrimStopsFromCompleteCDS")
class CMacroFunction_TrimStopFromCompleteCDS TrimStopsFromCompleteCDS()
CRef< objects::CSeq_feat > m_NewFeat
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
static bool s_RemoveBothPartials(objects::CSeq_feat &feat, objects::CScope &scope, const string &descr)
void x_LogFunction(CNcbiOstrstream &logstr)
CRef< objects::CSeq_loc > x_GetProteinLoc(const objects::CSeq_id &prot_id, TSeqPos pos) const
static bool s_Set3EndPartial(objects::CSeq_feat &feat, objects::CScope &scope, const string &descr, bool extend3=false)
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
void x_SetAdditionalFields(size_t index)
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
static bool s_ConvertLocationStrand(objects::CSeq_feat &feat, objects::CScope &scope, const string &str_from, const string &str_to)
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
static objects::CCdregion::TFrame s_FindMatchingFrame(const objects::CSeq_feat &cds, objects::CScope &scope)
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
CIRef< IMacroBioDataIter > m_DataIter
static bool s_SetCDSFrame(objects::CSeq_feat &cds, ECdsFrame frame_type, objects::CScope &scope)
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
void x_HandleNegativeCoordinates(size_t index)
objects::CBioseq_Handle m_Bsh
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
virtual bool x_ValidArguments() const
Tests the number and the type of function arguments.
objects::CBioseq_Handle GetBioseqForSeqFeat(const objects::CSeq_feat &f, objects::CScope &scope)
@ eUnknown
Definition: app_popup.hpp:72
C & SerialAssign(C &dest, const C &src, ESerialRecursionMode how=eRecursive)
Set object to copy of another one.
Definition: serialbase.hpp:482
virtual void Assign(const CSerialObject &source, ESerialRecursionMode how=eRecursive)
Set object to copy of another one.
#define ENUM_METHOD_NAME(EnumName)
Definition: serialbase.hpp:994
static const TObjectType * SafeCast(TTypeInfo type)
Definition: serialutil.hpp:76
@ eTypeFamilyContainer
Definition: serialdef.hpp:142
@ eTypeFamilyPrimitive
Definition: serialdef.hpp:139
void GetLabel(string *label, ELabelType type=eDefault, TLabelFlags flags=fLabel_Default) const
Append a label for this Seq-id to the supplied string.
Definition: Seq_id.cpp:2040
CConstRef< CSeq_id > GetSeqId(void) const
static CSeq_id_Handle GetHandle(const CSeq_id &id)
Normal way of getting a handle, works for any seq-id.
bool IsPartialStart(ESeqLocExtremes ext) const
check start or stop of location for e_Lim fuzz
Definition: Seq_loc.cpp:3222
ENa_strand GetStrand(void) const
Get the location's strand.
Definition: Seq_loc.cpp:882
virtual void Assign(const CSerialObject &source, ESerialRecursionMode how=eRecursive)
Override Assign() to incorporate cache invalidation.
Definition: Seq_loc.cpp:337
TSeqPos GetStart(ESeqLocExtremes ext) const
Return start and stop positions of the seq-loc.
Definition: Seq_loc.cpp:915
void SetPnt(TPnt &v)
Definition: Seq_loc.hpp:985
bool IsSetStrand(EIsSetStrand flag=eIsSetStrand_Any) const
Check if strand is set for any/all part(s) of the seq-loc depending on the flag.
Definition: Seq_loc.cpp:858
const CSeq_id * GetId(void) const
Get the id of the location return NULL if has multiple ids or no id at all.
Definition: Seq_loc.hpp:941
void GetLabel(string *label) const
Appends a label suitable for display (e.g., error messages) label must point to an existing string ob...
Definition: Seq_loc.cpp:3467
bool IsPartialStop(ESeqLocExtremes ext) const
Definition: Seq_loc.cpp:3251
TSeqPos GetStop(ESeqLocExtremes ext) const
Definition: Seq_loc.cpp:963
@ fSortAndMerge_All
Definition: Seq_loc.hpp:334
@ fMerge_SingleRange
Definition: Seq_loc.hpp:332
TObjectPtr GetObjectPtr(void) const
Get pointer to object.
CObjectInfo AddNewElement(void) const
Add and return new element object.
Definition: objectinfo.cpp:321
ETypeFamily GetTypeFamily(void) const
Get data type family.
bool AdjustFeaturePartialFlagForLocation(CSeq_feat &new_feat)
AdjustFeaturePartialFlagForLocation A function to ensure that Seq-feat.partial is set if either end o...
Definition: feature.cpp:3983
TSeqPos GetLength(const CSeq_id &id, CScope *scope)
Get sequence length if scope not null, else return max possible TSeqPos.
void ChangeSeqLocId(CSeq_loc *loc, bool best, CScope *scope)
Change each of the CSeq_ids embedded in a CSeq_loc to the best or worst CSeq_id accoring to the value...
CRef< CSeq_loc > Seq_loc_Merge(const CSeq_loc &loc, CSeq_loc::TOpFlags flags, CScope *scope)
Merge ranges in the seq-loc.
CSeq_loc * SeqLocRevCmpl(const CSeq_loc &loc, CScope *scope)
Get reverse complement of the seq-loc (?)
const CSeq_feat * GetCDSForProduct(const CBioseq &product, CScope *scope)
Get the encoding CDS feature of a given protein sequence.
Definition: sequence.cpp:2549
bool IsPseudo(const CSeq_feat &feat, CScope &scope)
Determines whether given feature is pseudo, using gene associated with feature if necessary Checks to...
Definition: sequence.cpp:1428
CConstRef< CSeq_feat > GetOverlappingGene(const CSeq_loc &loc, CScope &scope, ETransSplicing eTransSplicing=eTransSplicing_Auto)
Definition: sequence.cpp:1366
CConstRef< CSeq_feat > GetGeneForFeature(const CSeq_feat &feat, CScope &scope)
Finds gene for feature, but obeys SeqFeatXref directives.
Definition: sequence.cpp:1529
static CCdregion::EFrame FindBestFrame(const CSeq_feat &cds, CScope &scope)
Find "best" frame for a coding region.
Definition: sequence.cpp:4376
CConstRef< CSeq_feat > GetmRNAforCDS(const CSeq_feat &cds, CScope &scope)
GetmRNAforCDS A function to find a CSeq_feat representing the appropriate mRNA for a given CDS.
Definition: sequence.cpp:1261
static void Translate(const string &seq, string &prot, const CGenetic_code *code, bool include_stop=true, bool remove_trailing_X=false, bool *alt_start=NULL, bool is_5prime_complete=true, bool is_3prime_complete=true)
Translate a string using a specified genetic code.
Definition: sequence.cpp:4095
CRef< CSeq_loc > Map(const CSeq_loc &src_loc)
Map seq-loc.
CBioseq_Handle GetBioseqHandle(const CSeq_id &id)
Get bioseq handle by seq-id.
Definition: scope.cpp:95
CSeq_feat_Handle GetSeq_featHandle(const CSeq_feat &feat, EMissing action=eMissing_Default)
Definition: scope.cpp:200
@ eProductToLocation
Map from the feature's product to location.
CConstRef< CBioseq > GetCompleteBioseq(void) const
Get the complete bioseq.
CSeq_id_Handle GetAccessSeq_id_Handle(void) const
Get any CSeq_id_Handle handle that can be used to access this bioseq Use GetSeq_id_Handle() if it's n...
const CSeqFeatData & GetData(void) const
bool IsProtein(void) const
bool IsSetData(void) const
CSeqVector GetSeqVector(EVectorCoding coding, ENa_strand strand=eNa_strand_plus) const
Get sequence: Iupacna or Iupacaa if use_iupac_coding is true.
const TInst & GetInst(void) const
@ eCoding_Ncbi
Set coding to binary coding (Ncbi4na or Ncbistdaa)
@ eCoding_Iupac
Set coding to printable coding (Iupacna or Iupacaa)
const CSeq_feat_Handle & GetSeq_feat_Handle(void) const
Get original feature handle.
Definition: mapped_feat.hpp:71
void GetSeqData(TSeqPos start, TSeqPos stop, string &buffer) const
Fill the buffer string with the sequence data for the interval [start, stop).
Definition: seq_vector.cpp:304
TSeqPos size(void) const
Definition: seq_vector.hpp:291
void SetCoding(TCoding coding)
void SetIupacCoding(void)
Set coding to either Iupacaa or Iupacna depending on molecule type.
TObjectType * GetPointer(void) const THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:1684
CConstRef< C > ConstRef(const C *object)
Template function for conversion of const object pointer to CConstRef.
Definition: ncbiobj.hpp:2024
CRef< C > Ref(C *object)
Helper functions to get CRef<> and CConstRef<> objects.
Definition: ncbiobj.hpp:2015
TObjectType * GetPointer(void) THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:998
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
bool IsNull(void) const THROWS_NONE
Check if pointer is null – same effect as Empty().
Definition: ncbiobj.hpp:735
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define USING_SCOPE(ns)
Use the specified namespace.
Definition: ncbistl.hpp:78
#define END_SCOPE(ns)
End the previously defined scope.
Definition: ncbistl.hpp:75
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define BEGIN_SCOPE(ns)
Define a new scope.
Definition: ncbistl.hpp:72
bool IsOssEmpty(CNcbiOstrstream &oss)
Definition: ncbistre.hpp:831
NCBI_NS_STD::string::size_type SIZE_TYPE
Definition: ncbistr.hpp:132
static string Int8ToString(Int8 value, TNumToStringFlags flags=0, int base=10)
Convert Int8 to string.
Definition: ncbistr.hpp:5159
#define kEmptyStr
Definition: ncbistr.hpp:123
static SIZE_TYPE FindNoCase(const CTempString str, const CTempString pattern, SIZE_TYPE start, SIZE_TYPE end, EOccurrence which=eFirst)
Find the pattern in the specified range of a string using a case insensitive search.
Definition: ncbistr.cpp:2993
static bool EndsWith(const CTempString str, const CTempString end, ECase use_case=eCase)
Check if a string ends with a specified suffix value.
Definition: ncbistr.hpp:5430
static bool IsBlank(const CTempString str, SIZE_TYPE pos=0)
Check if a string is blank (has no text).
Definition: ncbistr.cpp:106
#define NPOS
Definition: ncbistr.hpp:133
static void TruncateSpacesInPlace(string &str, ETrunc where=eTrunc_Both)
Truncate spaces in a string (in-place)
Definition: ncbistr.cpp:3201
static SIZE_TYPE Find(const CTempString str, const CTempString pattern, ECase use_case=eCase, EDirection direction=eForwardSearch, SIZE_TYPE occurrence=0)
Find the pattern in the string.
Definition: ncbistr.cpp:2891
static bool EqualCase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-sensitive equality of a substring with another string.
Definition: ncbistr.hpp:5325
static bool EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive equality of a substring with another string.
Definition: ncbistr.hpp:5353
static bool Equal(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2, ECase use_case=eCase)
Test for equality of a substring with another string.
Definition: ncbistr.hpp:5384
static string & ReplaceInPlace(string &src, const string &search, const string &replace, SIZE_TYPE start_pos=0, SIZE_TYPE max_replace=0, SIZE_TYPE *num_replace=0)
Replace occurrences of a substring within a string.
Definition: ncbistr.cpp:3405
static string & ToLower(string &str)
Convert string to lower case – string& version.
Definition: ncbistr.cpp:405
static const char label[]
EPartial_both_clear_constraint
Access to EPartial_both_clear_constraint's attributes (values, names) as defined in spec.
EPartial_3_clear_constraint
Access to EPartial_3_clear_constraint's attributes (values, names) as defined in spec.
EPartial_3_set_constraint
Access to EPartial_3_set_constraint's attributes (values, names) as defined in spec.
EPartial_both_set_constraint
Access to EPartial_both_set_constraint's attributes (values, names) as defined in spec.
EGene_xref_suppression_type
Access to EGene_xref_suppression_type's attributes (values, names) as defined in spec.
EGene_xref_necessary_type
Access to EGene_xref_necessary_type's attributes (values, names) as defined in spec.
EFeature_location_strand_from
Access to EFeature_location_strand_from's attributes (values, names) as defined in spec.
EPartial_5_clear_constraint
Access to EPartial_5_clear_constraint's attributes (values, names) as defined in spec.
EPartial_5_set_constraint
Access to EPartial_5_set_constraint's attributes (values, names) as defined in spec.
EFeature_location_strand_to
Access to EFeature_location_strand_to's attributes (values, names) as defined in spec.
@ ePartial_both_clear_constraint_all
@ ePartial_3_clear_constraint_good_end
@ ePartial_3_clear_constraint_not_at_end
@ ePartial_3_clear_constraint_all
@ ePartial_3_set_constraint_all
@ ePartial_3_set_constraint_bad_end
@ ePartial_3_set_constraint_at_end
@ ePartial_both_set_constraint_all
@ eGene_xref_suppression_type_non_suppressing
@ eGene_xref_suppression_type_any
@ eGene_xref_suppression_type_suppressing
@ eGene_xref_necessary_type_any
@ eGene_xref_necessary_type_unnecessary
@ eGene_xref_necessary_type_necessary
@ ePartial_5_clear_constraint_all
@ ePartial_5_clear_constraint_not_at_end
@ ePartial_5_clear_constraint_good_start
@ ePartial_5_set_constraint_bad_start
@ ePartial_5_set_constraint_frame_not_one
@ ePartial_5_set_constraint_at_end
@ ePartial_5_set_constraint_all
list< string > TName
Definition: Prot_ref_.hpp:108
const TName & GetName(void) const
Get the Name member data.
Definition: Prot_ref_.hpp:378
list< string > TEc
Definition: Prot_ref_.hpp:110
bool IsSetName(void) const
protein name Check if a value has been assigned to Name data member.
Definition: Prot_ref_.hpp:366
TType GetType(void) const
Get the Type member data.
Definition: RNA_ref_.hpp:529
EType
type of RNA feature
Definition: RNA_ref_.hpp:95
void SetType(TType value)
Assign a value to Type data member.
Definition: RNA_ref_.hpp:538
void SetAa(TAa &value)
Assign a value to Aa data member.
TXref & SetXref(void)
Assign a value to Xref data member.
Definition: Seq_feat_.hpp:1314
bool IsSetData(void) const
the specific data Check if a value has been assigned to Data data member.
Definition: Seq_feat_.hpp:913
bool IsProt(void) const
Check if variant Prot is selected.
void SetLocation(TLocation &value)
Assign a value to Location data member.
Definition: Seq_feat_.cpp:131
bool IsCdregion(void) const
Check if variant Cdregion is selected.
void SetPartial(TPartial value)
Assign a value to Partial data member.
Definition: Seq_feat_.hpp:971
bool IsSetXref(void) const
cite other relevant features Check if a value has been assigned to Xref data member.
Definition: Seq_feat_.hpp:1296
const TLocation & GetLocation(void) const
Get the Location member data.
Definition: Seq_feat_.hpp:1117
bool IsGene(void) const
Check if variant Gene is selected.
TFrame GetFrame(void) const
Get the Frame member data.
Definition: Cdregion_.hpp:534
const TData & GetData(void) const
Get the Data member data.
Definition: Seq_feat_.hpp:925
void SetData(TData &value)
Assign a value to Data data member.
Definition: Seq_feat_.cpp:94
const TCdregion & GetCdregion(void) const
Get the variant data.
void SetLoc(TLoc &value)
Assign a value to Loc data member.
const TProduct & GetProduct(void) const
Get the Product member data.
Definition: Seq_feat_.hpp:1096
const TGene & GetGene(void) const
Get the variant data.
const TProt & GetProt(void) const
Get the variant data.
const TXref & GetXref(void) const
Get the Xref member data.
Definition: Seq_feat_.hpp:1308
void ResetXref(void)
Reset Xref data member.
Definition: Seq_feat_.cpp:182
const TRna & GetRna(void) const
Get the variant data.
bool IsSetProduct(void) const
product of process Check if a value has been assigned to Product data member.
Definition: Seq_feat_.hpp:1084
bool IsRna(void) const
Check if variant Rna is selected.
bool IsSetFrame(void) const
Check if a value has been assigned to Frame data member.
Definition: Cdregion_.hpp:509
bool IsSetLocation(void) const
feature made from Check if a value has been assigned to Location data member.
Definition: Seq_feat_.hpp:1105
@ eFrame_not_set
not set, code uses one
Definition: Cdregion_.hpp:95
@ eFrame_three
reading frame
Definition: Cdregion_.hpp:98
ENa_strand
strand of nucleic acid
Definition: Na_strand_.hpp:64
@ eNa_strand_plus
Definition: Na_strand_.hpp:66
@ eNa_strand_minus
Definition: Na_strand_.hpp:67
@ eNa_strand_unknown
Definition: Na_strand_.hpp:65
@ eNa_strand_both
in forward orientation
Definition: Na_strand_.hpp:68
@ e_not_set
No variant selected.
Definition: Seq_loc_.hpp:97
@ e_Ncbieaa
extended ASCII 1 letter aa codes
Definition: Seq_data_.hpp:111
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
int i
yy_size_t n
Macro exceptions.
Functions that resolve field names described in asn format.
constexpr auto sort(_Init &&init)
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
EDuplicateFeatureType IsDuplicate(const CSeq_feat_Handle &f1, const CSeq_feat_Handle &f2, bool check_partials=false, bool case_sensitive=false)
Reports how two features duplicate each other.
Definition: utilities.cpp:1838
EDuplicateFeatureType
Definition: utilities.hpp:191
@ eDuplicate_Duplicate
Definition: utilities.hpp:193
@ eDuplicate_DuplicateDifferentTable
Definition: utilities.hpp:195
Utility macros and typedefs for exploring NCBI objects from seqfeat.asn.
#define FOR_EACH_NAME_ON_PROTREF(Itr, Var)
FOR_EACH_NAME_ON_PROTREF EDIT_EACH_NAME_ON_PROTREF.
@ eNotSet
Definition: splign_app.cpp:550
@ eExistingText_append_semi
bool AddValueToString(string &str, const string &value, EExistingText existing_text)
Add text to an existing string, using the "existing_text" directive to combine new text with existing...
SAnnotSelector –.
Definition: inftrees.h:24
Definition: type.c:6
#define _ASSERT
CRef< CCmdChangeSeq_feat > AdjustGene(const objects::CSeq_feat &orig_feat, const objects::CSeq_feat &new_feat, objects::CScope &scope)
CRef< CCmdComposite > GetSynchronizeProteinPartialsCommand(objects::CScope &scope, const objects::CSeq_feat &cds)
CRef< CCmdComposite > GetRetranslateCDSCommand(objects::CScope &scope, const objects::CSeq_feat &cds, bool create_general_only)
void GetProductToCDSMap(objects::CScope &scope, map< objects::CBioseq_Handle, set< objects::CSeq_feat_Handle > > &product_to_cds)
CRef< CCmdComposite > TrimStopsFromCompleteCDS(const objects::CSeq_feat &cds, objects::CScope &scope)
CRef< CCmdComposite > GetDeleteAllFeaturesCommand(objects::CSeq_entry_Handle seh, size_t &count, bool remove_proteins=true)
CRef< CCmdComposite > GetDeleteFeatureCommand(const objects::CSeq_feat_Handle &fh, bool remove_proteins=true)
Modified on Wed Apr 17 13:10:16 2024 by modify_doxy.py rev. 669887