1 /* $Id: seq_loc_reverse_complementer.cpp 348987 2012-01-06 14:04:00Z kornbluh $
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 * Author: Clifford Clausen, Aaron Ucko, Aleksey Grichenko, Michael Kornbluh
27 *
28 * File Description:
29 * Get reverse complement of a CSeq_loc.
30 *
31 * ===========================================================================
32 */
33 #include <ncbi_pch.hpp>
34
35 #include <objects/seq/seq_loc_reverse_complementer.hpp>
36
37 #include <objects/seqloc/Seq_interval.hpp>
38 #include <objects/seqloc/Seq_point.hpp>
39 #include <objects/seqloc/Seq_loc_equiv.hpp>
40 #include <objects/seqloc/Seq_bond.hpp>
41
42 /////////////////////////////////////////////////////////////////////
43 //
44 // Implementation of GetReverseComplement()
45 //
46
47 BEGIN_NCBI_SCOPE
BEGIN_SCOPE(objects)48 BEGIN_SCOPE(objects)
49
50 static ENa_strand s_GetPackedPntStrand(const CSeq_loc & loc )
51 {
52 _ASSERT( loc.IsPacked_pnt() );
53 return ( loc.GetPacked_pnt().IsSetStrand() ?
54 loc.GetPacked_pnt().GetStrand() :
55 eNa_strand_unknown );
56 }
57
s_SeqIntRevCmp(const CSeq_interval & i)58 static CSeq_interval* s_SeqIntRevCmp(const CSeq_interval& i)
59 {
60 auto_ptr<CSeq_interval> rev_int(new CSeq_interval);
61 rev_int->Assign(i);
62
63 ENa_strand s = i.CanGetStrand() ? i.GetStrand() : eNa_strand_unknown;
64 rev_int->SetStrand(Reverse(s));
65
66 return rev_int.release();
67 }
68
69
s_SeqPntRevCmp(const CSeq_point & pnt)70 static CSeq_point* s_SeqPntRevCmp(const CSeq_point& pnt)
71 {
72 auto_ptr<CSeq_point> rev_pnt(new CSeq_point);
73 rev_pnt->Assign(pnt);
74
75 ENa_strand s = pnt.CanGetStrand() ? pnt.GetStrand() : eNa_strand_unknown;
76 rev_pnt->SetStrand(Reverse(s));
77
78 return rev_pnt.release();
79 }
80
81 CSeq_loc*
GetReverseComplement(const CSeq_loc & loc,CReverseComplementHelper * helper)82 GetReverseComplement(const CSeq_loc& loc, CReverseComplementHelper* helper)
83 {
84 _ASSERT( helper != NULL );
85
86 auto_ptr<CSeq_loc> rev_loc( new CSeq_loc );
87
88 switch ( loc.Which() ) {
89
90 // -- reverse is the same.
91 case CSeq_loc::e_Null:
92 case CSeq_loc::e_Empty:
93 case CSeq_loc::e_Whole:
94 rev_loc->Assign(loc);
95 break;
96
97 // -- just reverse the strand
98 case CSeq_loc::e_Int:
99 rev_loc->SetInt(*s_SeqIntRevCmp(loc.GetInt()));
100 break;
101 case CSeq_loc::e_Pnt:
102 rev_loc->SetPnt(*s_SeqPntRevCmp(loc.GetPnt()));
103 break;
104 case CSeq_loc::e_Packed_pnt:
105 rev_loc->SetPacked_pnt().Assign(loc.GetPacked_pnt());
106 rev_loc->SetPacked_pnt().SetStrand(Reverse( s_GetPackedPntStrand(loc) ));
107 break;
108
109 // -- possibly more than one sequence
110 case CSeq_loc::e_Packed_int:
111 {
112 // reverse each interval and store them in reverse order
113 typedef CRef< CSeq_interval > TInt;
114 CPacked_seqint& pint = rev_loc->SetPacked_int();
115 ITERATE (CPacked_seqint::Tdata, it, loc.GetPacked_int().Get()) {
116 pint.Set().push_front(TInt(s_SeqIntRevCmp(**it)));
117 }
118 break;
119 }
120 case CSeq_loc::e_Mix:
121 {
122 // reverse each location and store them in reverse order
123 typedef CRef< CSeq_loc > TLoc;
124 CSeq_loc_mix& mix = rev_loc->SetMix();
125 ITERATE (CSeq_loc_mix::Tdata, it, loc.GetMix().Get()) {
126 mix.Set().push_front(TLoc(GetReverseComplement(**it, helper)));
127 }
128 break;
129 }
130 case CSeq_loc::e_Equiv:
131 {
132 // reverse each location (no need to reverse order)
133 typedef CRef< CSeq_loc > TLoc;
134 CSeq_loc_equiv& e = rev_loc->SetEquiv();
135 ITERATE (CSeq_loc_equiv::Tdata, it, loc.GetEquiv().Get()) {
136 e.Set().push_back(TLoc(GetReverseComplement(**it, helper)));
137 }
138 break;
139 }
140
141 case CSeq_loc::e_Bond:
142 {
143 CSeq_bond& bond = rev_loc->SetBond();
144 bond.SetA(*s_SeqPntRevCmp(loc.GetBond().GetA()));
145 if ( loc.GetBond().CanGetB() ) {
146 bond.SetA(*s_SeqPntRevCmp(loc.GetBond().GetB()));
147 }
148 }
149
150 // -- not supported
151 case CSeq_loc::e_Feat:
152 default:
153 NCBI_THROW(CException, eUnknown,
154 "CSeq_loc::GetReverseComplement -- unsupported location type");
155 }
156
157 return rev_loc.release();
158 }
159
160 END_SCOPE(objects)
161 END_NCBI_SCOPE
162