#include <iostream>
#include <utility>
#include <vector>
#include <memory>
#include <cassert>
#include "bm.h"
#include "bmintervals.h"
#include "bmsparsevec_compr.h"
#include "bmundef.h"
using namespace std;
typedef bm::interval_enumerator<bm::bvector<> > interval_enumerator_type;
typedef std::vector<std::unique_ptr<bm::bvector<> > > layout_vector_type;
typedef bm::sparse_vector<unsigned char, bm::bvector<> > sparse_vector_u8;
typedef bm::rsc_sparse_vector<unsigned char, sparse_vector_u8> rsc_vector_u8;
typedef std::vector<std::unique_ptr<rsc_vector_u8> > starnds_vector_type;
struct data_model
{
void optimize();
void add_layout(size_t plane, bm::bvector<>* bv);
void add_strand(size_t plane, rsc_vector_u8* strand);
layout_vector_type layout_v; starnds_vector_type strand_v; };
void data_model::optimize()
{
BM_DECLARE_TEMP_BLOCK(tb); for (size_t i = 0; i < layout_v.size(); ++i)
{
auto bv = layout_v[i].get();
if (bv)
bv->optimize(tb); } for (size_t i = 0; i < strand_v.size(); ++i)
{
auto strand_plane = strand_v[i].get();
if (strand_plane)
{
strand_plane->optimize(tb);
strand_plane->sync(); }
} }
void data_model::add_layout(size_t plane, bm::bvector<>* bv)
{
unique_ptr<bm::bvector<> > ap(bv);
if (layout_v.size() == plane) {
layout_v.emplace_back(move(ap));
}
else
{
while (layout_v.size() < plane) layout_v.emplace_back(new bm::bvector<>(bm::BM_GAP));
layout_v[plane] = std::move(ap);
}
}
void data_model::add_strand(size_t plane, rsc_vector_u8* strand)
{
unique_ptr<rsc_vector_u8 > ap(strand);
if (strand_v.size() == plane) {
strand_v.emplace_back(move(ap));
}
else
{
while (strand_v.size() < plane) strand_v.emplace_back(new rsc_vector_u8());
strand_v[plane] = std::move(ap);
}
}
static
void set_feature_strand(data_model& dm, size_t plane,
bm::bvector<>::size_type pos,
unsigned char strand)
{
if (!strand)
return;
while (dm.strand_v.size() <= plane) {
std::unique_ptr<rsc_vector_u8> p2(new rsc_vector_u8());
dm.strand_v.emplace_back(move(p2));
}
rsc_vector_u8* strand_plane = dm.strand_v[plane].get();
if (!strand_plane)
{
strand_plane = new rsc_vector_u8();
dm.strand_v[plane] = unique_ptr<rsc_vector_u8 >(strand_plane);
}
assert(strand_plane->is_null(pos));
strand_plane->set(pos, strand);
}
static
void add_object(data_model& dm,
unsigned start, unsigned end,
unsigned char strand)
{
assert(start <= end);
bm::bvector<>* bv;
for (size_t i = 0; i < dm.layout_v.size(); ++i)
{
bv = dm.layout_v[i].get();
if (!bv)
{
bv = new bm::bvector<>(bm::BM_GAP);
dm.layout_v[i] = unique_ptr<bm::bvector<> >(bv);
bv->set_range(start, end);
set_feature_strand(dm, i, start, strand);
return;
}
if (!bv->any_range(start, end)) {
bv->set_range(start, end); set_feature_strand(dm, i, start, strand);
return;
}
}
bv = new bm::bvector<>(bm::BM_GAP);
dm.layout_v.emplace_back(std::unique_ptr<bm::bvector<> >(bv));
bv->set_range(start, end);
set_feature_strand(dm, dm.layout_v.size()-1, start, strand);
}
static
void splice_model(data_model& dm_target, const data_model& dm,
bm::bvector<>::size_type start,
bm::bvector<>::size_type end,
bool copy_strands)
{
const bm::bvector<>* bv; const rsc_vector_u8* strand_plane;
size_t t_plane = 0;
for (size_t i = 0; i < dm.layout_v.size(); ++i)
{
bv = dm.layout_v[i].get();
if (bv)
{
bm::bvector<>::size_type start_pos;
bm::bvector<>::size_type end_pos;
bool found = bm::find_interval_start(*bv, start, start_pos);
if (!found)
start_pos = start;
found = bm::find_interval_end(*bv, end, end_pos);
if (!found)
end_pos = end;
unique_ptr<bm::bvector<>> bv_ptr(new bm::bvector<>(bm::BM_GAP));
bv_ptr->copy_range(*bv, start_pos, end_pos);
if (bv_ptr->any()) {
dm_target.add_layout(t_plane, bv_ptr.release());
if (copy_strands)
{
if (i < dm.strand_v.size())
{
strand_plane = dm.strand_v[i].get();
if (strand_plane)
{
unique_ptr<rsc_vector_u8> strand_ptr(new rsc_vector_u8());
strand_ptr->copy_range(*strand_plane, start_pos, end_pos);
dm_target.add_strand(t_plane, strand_ptr.release());
}
}
}
++t_plane;
}
} }
}
static
void print_model(const data_model& dm)
{
const bm::bvector<>* bv; const rsc_vector_u8* strand_plane;
cout <<
"-------------------------------------------------------------------------"
<< endl <<
"ATGTTAGCCCGCGCATATTATATATGTAGCGTATTAAGCGDGGAGATTACCCTTGCATTAGGTTANNNNNNNN"
<< endl <<
"-------------------------------------------------------------------------"
<< endl;
for (size_t i = 0; i < dm.layout_v.size(); ++i)
{
bv = dm.layout_v[i].get();
if (bv)
{
strand_plane = i < dm.strand_v.size() ? dm.strand_v[i].get() : nullptr;
interval_enumerator_type ien(*bv);
if (ien.valid())
{
bm::bvector<>::size_type spaces = 0;
do
{
auto st = ien.start(); auto end = ien.end();
char ch_strand = '?';
if (strand_plane)
{
auto strand = strand_plane->get(st);
switch (strand)
{
case 0: ch_strand = '>'; break; case 1: ch_strand = '<'; break; default: break; }
}
for (; spaces < st; ++spaces)
cout << " ";
for (bool first = true; st <= end; ++st, first = false)
{
if (st == end)
cout << ch_strand;
else
cout << (first ? ch_strand : '.');
} spaces = end+1;
} while (ien.advance());
cout << endl;
}
}
} }
enum Strand { positive=0, negative=1, unknown=2 };
int main(void)
{
try
{
data_model dm;
add_object(dm, 0, 0, negative);
add_object(dm, 5, 10, positive);
add_object(dm, 4, 70, negative);
add_object(dm, 15, 20, negative);
add_object(dm, 20, 30, positive);
add_object(dm, 16, 21, unknown);
dm.optimize();
print_model(dm);
{
data_model dm_splice;
splice_model(dm_splice, dm, 5, 10, false);
dm_splice.optimize();
cout << endl;
print_model(dm_splice);
}
{
data_model dm_splice;
splice_model(dm_splice, dm, 5, 10, true);
dm_splice.optimize();
cout << endl;
print_model(dm_splice);
}
}
catch(std::exception& ex)
{
std::cerr << ex.what() << std::endl;
return 1;
}
return 0;
}