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