forked from deltadev/bbi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbbi_file.h
189 lines (142 loc) · 4.09 KB
/
bbi_file.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#ifndef _BBI_STREAM_H_
#define _BBI_STREAM_H_
#include <vector>
#include <fstream>
#include <zlib.h>
#include <sstream>
#include "main_header.h"
#include "zoom_header.h"
#include "data_records.h"
#include "r_tree.h"
#include "bp_tree.h"
#include "chromosome_tree.h"
// Local bbi file searching.
//
// The constructer calls the init functions.
//
// After this the hash_map of chrom names is set up to begin a search.
//
//
class bbi_file
{
public:
typedef std::vector<r_tree::leaf_node> leaves_t;
std::vector<zoom_header> z_hdrs;
chromosome_tree chrom_tree;
bbi_file(std::istream& is);
~bbi_file();
// For info on headers including zoom headers when available.
//
void print_headers(std::ostream& os);
void print_index_header(unsigned index, std::ostream& os);
// The zoom level should be 0 for the main data or otherwise selected
// from the z_hdrs.
//
leaves_t const& search_r_tree(data_record r, int zoom_level);
// Obtains data records from r_tree leaf node.
//
template <typename T>
std::vector<T> records_for_leaf(r_tree::leaf_node ln);
// Functions to obtaion wig data records
std::vector<wig_data_record> big_wig_data_records_for_leaf(r_tree::leaf_node ln);
wig_data_header bigWig_header_for_leaf(r_tree::leaf_node ln);
std::vector<wig_data_record> bigWig_records(wig_data_header header);
private:
std::istream& is_;
main_header main_hdr;
bp_tree::header bpt_hdr;
r_tree::header main_rt_hdr;
// For the return results of the recursive r_tree search.
//
leaves_t leaves;
// Called by constructor.
//
void init_chrom_tree();
void init_zoom_headers();
// Recursive helper for r_tree search.
//
void recursive_rtree_find(r_tree::node_header nh, data_record r);
// Calls zlib to inflate the records.
//
template <typename T>
std::vector<T>
inflate_records(std::istream& is, uint64_t comp_sz, size_t decomp_sz);
};
template <typename T>
std::vector<T> bbi_file::records_for_leaf(r_tree::leaf_node ln)
{
std::vector<T> bdrs;
is_.seekg(ln.data_offset);
uint32_t uncomp_buf_sz = main_hdr.uncompress_buf_size;
if (uncomp_buf_sz == 0)
{
T bdr;
while (is_.tellg() < ln.data_offset + ln.data_size)
{
bdr.unpack(is_);
bdrs.push_back(bdr);
}
}
else
{
bdrs = inflate_records<T>(is_, ln.data_size, uncomp_buf_sz);
}
return bdrs;
}
template <typename T>
std::vector<T>
bbi_file::inflate_records(std::istream& is, uint64_t comp_sz, size_t decomp_sz)
{
int ret;
unsigned have;
z_stream strm;
/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&strm);
if (ret != Z_OK) {
std::string err_str = std::string(zError(ret));
throw std::runtime_error("bbi_file::inflate_records inflateInit error: " + err_str);
}
// Buffers.
//
std::vector<unsigned char> out_buff(decomp_sz);
std::vector<unsigned char> in_buff(comp_sz);
is.read((char*)&in_buff.front(), comp_sz);
if (is.gcount() != comp_sz)
throw std::runtime_error("bbi_file::inflate_records failed to read comp_sz bytes");
strm.avail_in = (unsigned)in_buff.size();
strm.next_in = &in_buff.front();
do {
strm.avail_out = (unsigned)out_buff.size();
strm.next_out = &out_buff.front();
ret = inflate(&strm, Z_NO_FLUSH);
have = (unsigned)out_buff.size() - strm.avail_out;
if (strm.avail_in == 0)
break;
} while (strm.avail_out == 0);
if (ret != Z_STREAM_END) {
std::string err_str = "ret != Z_STREAM_END";
throw std::runtime_error("bbi_file::inflate_records " + err_str);
}
ret = inflateEnd(&strm);
if (ret != Z_OK) {
std::string err_str = "bad rv for inflateEnd";
throw std::runtime_error("bbi_file::inflate_records " + err_str);
}
std::string output(out_buff.begin(), out_buff.end());
std::istringstream iss;
iss.str(output);
std::vector<T> bdrs;
while (iss) {
T bdr;
bdr.unpack(iss);
if (bdr.chrom_start != bdr.chrom_end)
bdrs.push_back(bdr);
}
return bdrs;
}
#endif /* _BBI_STREAM_H_ */