libsequence  1.9.5
PolyTableSlice.tcc
1 // Code for the -*- C++ -*- namespace Sequence::PolyTableSlice<T>
2 
3 /*
4 Copyright (C) 2003-2009 Kevin Thornton, krthornt[]@[]uci.edu
5 
6 Remove the brackets to email me.
7 
8 This file is part of libsequence.
9 
10 libsequence is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14 
15 libsequence is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 long with libsequence. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 #include <Sequence/stateCounter.hpp>
26 #include <algorithm>
27 #include <iostream>
28 #include <stdexcept>
29 #include <cmath>
30 namespace Sequence
31 {
32  template<typename T>
33  PolyTableSlice<T>::PolyTableSlice( const PolyTable::const_site_iterator beg,
34  const PolyTable::const_site_iterator end,
35  const unsigned & window_size_S,
36  const unsigned & step_len )
37  : windows( std::vector<range>() )
38  {
39  if(!window_size_S)
40  throw std::logic_error("window size cannot be 0");
41  if(!step_len)
42  throw std::logic_error("step_len cannot be 0");
43  if(!std::is_sorted(beg,end,[](const polymorphicSite & a,
44  const polymorphicSite & b)
45  {
46  return a.first<b.first;
47  }))
48  {
49  throw std::runtime_error("range (beg,end) must be sorted in increasing order");
50  }
51  process_windows_fixed(beg,end,window_size_S,step_len);
52  }
53 
54  template<typename T>
55  PolyTableSlice<T>::PolyTableSlice( const PolyTable::const_site_iterator beg,
56  const PolyTable::const_site_iterator end,
57  const unsigned nwindows)
58  : windows( std::vector<range>() )
59  {
60  if(!std::is_sorted(beg,end,[](const polymorphicSite & a,
61  const polymorphicSite & b)
62  {
63  return a.first<b.first;
64  }))
65  {
66  throw std::runtime_error("range (beg,end) must be sorted in increasing order");
67  }
68  if( end-beg < nwindows )
69  {
70  std::cerr << "here\n";
71  process_windows_fixed(beg,end,1,1);
72  }
73  else
74  {
75  unsigned snp_per_window = unsigned(std::ceil(double(end-beg)/double(nwindows)));
76  process_windows_fixed(beg,end,snp_per_window,snp_per_window);
77  }
78  }
79 
80  template<typename T>
81  PolyTableSlice<T>::PolyTableSlice( const PolyTable::const_site_iterator beg,
82  const PolyTable::const_site_iterator end,
83  const double & window_size,
84  const double & step_len,
85  const double & starting_pos,
86  const double & ending_pos)
87  : windows( std::vector<range>() )
88  {
89  if(window_size<=0.)
90  throw std::logic_error("window_size must be > 0");
91  if(step_len <= 0.)
92  throw std::logic_error("step_len must be > 0");
93  if(!std::is_sorted(beg,end,[](const polymorphicSite & a,
94  const polymorphicSite & b)
95  {
96  return a.first<b.first;
97  }))
98  {
99  throw std::runtime_error("range (beg,end) must be sorted in increasing order");
100  }
101  process_windows(beg,end,window_size,step_len,starting_pos,ending_pos);
102  }
103 
104 
105  template<typename T>
106  void PolyTableSlice<T>::process_windows_fixed(const PolyTable::const_site_iterator beg,
107  const PolyTable::const_site_iterator end,
108  const unsigned & window_size_S,
109  const unsigned & window_step_len )
110  {
111  std::vector<PolyTable::const_site_iterator> variable_pos;
112 
113  //Step 1: record which sites are actually polymorphic,
114  //in case PolyTable contains invariant pos'ns
115  for(auto begc = beg; begc < end ; ++begc )
116  {
117  stateCounter counts = std::for_each( begc->second.begin(),
118  begc->second.end(),
119  stateCounter('-'));
120  if (counts.nStates() > 1) //is a polymorphic site
121  {
122  variable_pos.push_back(begc);
123  }
124  }
125  variable_pos.push_back(end);
126  if(!variable_pos.empty())
127  {
128  for( auto vpitr = variable_pos.begin() ; vpitr < variable_pos.end() ; vpitr += window_step_len )
129  {
130  windows.emplace_back( std::make_pair(*vpitr, (window_step_len < std::distance(*vpitr,end)) ? *(vpitr+window_size_S) : end) );
131  }
132  }
133  }
134 
135  template<typename T>
136  void PolyTableSlice<T>::process_windows( const PolyTable::const_site_iterator beg,
137  const PolyTable::const_site_iterator end,
138  const double & window_size,
139  const double & step_len,
140  const double & starting_pos,
141  const double & ending_pos)
142  {
143  double wbeg = starting_pos;
144 
145  //Obtain ptr to first element with position >= wbeg
146  auto wbeg_itr = std::lower_bound(beg,end,wbeg,
147  [](const polymorphicSite & __p, const double & __value){
148  return __p.first < __value;
149  });
150  int nwindows=int((ending_pos-wbeg)/step_len);
151  for(int win = 0 ; win < nwindows ; ++win)
152  {
153  double wend = wbeg + window_size;
154  //ptr to first element with position > wend
155  auto wend_itr = std::lower_bound(wbeg_itr,end,wend,
156  [](const polymorphicSite & __p, const double & __value){
157  return __p.first <= __value;
158  });
159  windows.push_back( std::make_pair(wbeg_itr,wend_itr) );
160  //update window begin data:
161  //Update the starting position of next window
162  wbeg += step_len;
163  //Update pointer to first data lement whose pos'n is >= wbeg
164  wbeg_itr = std::lower_bound(wbeg_itr,end,wbeg,
165  [](const polymorphicSite & __p, const double & __value){
166  return __p.first < __value;
167  });
168  }
169  }
170 
171  template<typename T>
172  typename PolyTableSlice<T>::const_iterator PolyTableSlice<T>::cbegin() const
173  {
174  return windows.begin();
175  }
176 
177  template<typename T>
178  typename PolyTableSlice<T>::const_iterator PolyTableSlice<T>::cend() const
179  {
180  return windows.end();
181  }
182 
183  template<typename T>
184  T PolyTableSlice<T>::get_slice(const_iterator itr) const
185  {
186  if (itr >= windows.end())
187  throw(std::out_of_range("PolyTableSlice<T>::get_slice() -- iterator out of range"));
188  if(itr->first != itr->second)
189  {
190  T rv;
191  rv.assign(itr->first,itr->second);
192  return rv;
193  }
194  return T();
195  }
196 
197  template<typename T>
198  typename std::vector<typename PolyTableSlice<T>::range>::size_type PolyTableSlice<T>::size() const
199  {
200  return windows.size();
201  }
202 
203  template<typename T>
204  T PolyTableSlice<T>::operator[](const unsigned & i) const
205  {
206  if (i > windows.size())
207  throw(std::out_of_range("PolyTableSlice::operator[] -- subscript out of range"));
208  if(windows[i].first != windows[i].second)
209  {
210  T rv;
211  rv.assign(windows[i].first,windows[i].second);
212  return rv;
213  }
214  return T();
215  }
216 }