/src/htslib/cram/cram_structs.h
Line | Count | Source |
1 | | /* |
2 | | Copyright (c) 2012-2016, 2018-2020, 2023, 2026 Genome Research Ltd. |
3 | | Author: James Bonfield <jkb@sanger.ac.uk> |
4 | | |
5 | | Redistribution and use in source and binary forms, with or without |
6 | | modification, are permitted provided that the following conditions are met: |
7 | | |
8 | | 1. Redistributions of source code must retain the above copyright notice, |
9 | | this list of conditions and the following disclaimer. |
10 | | |
11 | | 2. Redistributions in binary form must reproduce the above copyright notice, |
12 | | this list of conditions and the following disclaimer in the documentation |
13 | | and/or other materials provided with the distribution. |
14 | | |
15 | | 3. Neither the names Genome Research Ltd and Wellcome Trust Sanger |
16 | | Institute nor the names of its contributors may be used to endorse or promote |
17 | | products derived from this software without specific prior written permission. |
18 | | |
19 | | THIS SOFTWARE IS PROVIDED BY GENOME RESEARCH LTD AND CONTRIBUTORS "AS IS" AND |
20 | | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
21 | | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | | DISCLAIMED. IN NO EVENT SHALL GENOME RESEARCH LTD OR CONTRIBUTORS BE LIABLE |
23 | | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
25 | | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
26 | | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
27 | | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | | */ |
30 | | |
31 | | #ifndef HTSLIB_CRAM_STRUCTS_H |
32 | | #define HTSLIB_CRAM_STRUCTS_H |
33 | | |
34 | | /* |
35 | | * Defines in-memory structs for the basic file-format objects in the |
36 | | * CRAM format. |
37 | | * |
38 | | * The basic file format is: |
39 | | * File-def SAM-hdr Container Container ... |
40 | | * |
41 | | * Container: |
42 | | * Service-block data-block data-block ... |
43 | | * |
44 | | * Multiple blocks in a container are grouped together as slices, |
45 | | * also sometimes referred to as landmarks in the spec. |
46 | | */ |
47 | | |
48 | | |
49 | | #include <pthread.h> |
50 | | #include <stdint.h> |
51 | | #include <sys/types.h> |
52 | | |
53 | | #include "../htslib/thread_pool.h" |
54 | | #include "../htslib/cram.h" |
55 | | #include "string_alloc.h" |
56 | | #include "mFILE.h" |
57 | | #include "../htslib/khash.h" |
58 | | |
59 | | #ifdef __cplusplus |
60 | | extern "C" { |
61 | | #endif |
62 | | |
63 | | // Generic hash-map integer -> integer |
64 | 0 | KHASH_MAP_INIT_INT64(m_i2i, int) |
65 | 0 |
|
66 | 0 | // Generic hash-set integer -> (existence) |
67 | 0 | KHASH_SET_INIT_INT(s_i2i) |
68 | 0 |
|
69 | 0 | // For brevity |
70 | 0 | typedef unsigned char uc; |
71 | 0 |
|
72 | 0 | /* |
73 | 0 | * A union for the preservation map. Required for khash. |
74 | 0 | */ |
75 | 0 | typedef union { |
76 | 0 | int i; |
77 | 0 | char *p; |
78 | 0 | } pmap_t; |
79 | 0 |
|
80 | 0 | // Generates static functions here which isn't ideal, but we have no way |
81 | 0 | // currently to declare the kh_map_t structure here without also declaring a |
82 | 0 | // duplicate in the .c files due to the nature of the KHASH macros. |
83 | 0 | KHASH_MAP_INIT_STR(map, pmap_t) Unexecuted instantiation: cram_decode.c:kh_resize_map Unexecuted instantiation: cram_encode.c:kh_resize_map |
84 | 0 |
|
85 | 0 | struct hFILE; |
86 | 0 |
|
87 | 33.0k | #define SEQS_PER_SLICE 10000 |
88 | 16.5k | #define BASES_PER_SLICE (SEQS_PER_SLICE*500) |
89 | 16.5k | #define SLICE_PER_CNT 1 |
90 | | |
91 | 401k | #define CRAM_SUBST_MATRIX "CGTNGTANCATNGCANACGT" |
92 | | |
93 | 2.68G | #define MAX_STAT_VAL 1024 |
94 | | //#define MAX_STAT_VAL 16 |
95 | | typedef struct cram_stats { |
96 | | int freqs[MAX_STAT_VAL]; |
97 | | khash_t(m_i2i) *h; |
98 | | int nsamp; // total number of values added |
99 | | int nvals; // total number of unique values added |
100 | | int64_t min_val, max_val; |
101 | | } cram_stats; |
102 | | |
103 | | /* NB: matches java impl, not the spec */ |
104 | | enum cram_encoding { |
105 | | E_NULL = 0, |
106 | | E_EXTERNAL = 1, |
107 | | E_GOLOMB = 2, |
108 | | E_HUFFMAN = 3, |
109 | | E_BYTE_ARRAY_LEN = 4, |
110 | | E_BYTE_ARRAY_STOP = 5, |
111 | | E_BETA = 6, |
112 | | E_SUBEXP = 7, |
113 | | E_GOLOMB_RICE = 8, |
114 | | E_GAMMA = 9, |
115 | | |
116 | | // Total number of codecs, not a real one. |
117 | | E_NUM_CODECS, |
118 | | }; |
119 | | |
120 | | enum cram_external_type { |
121 | | E_INT = 1, |
122 | | E_LONG = 2, |
123 | | E_BYTE = 3, |
124 | | E_BYTE_ARRAY = 4, |
125 | | E_BYTE_ARRAY_BLOCK = 5, |
126 | | }; |
127 | | |
128 | | /* External IDs used by this implementation (only assumed during writing) */ |
129 | | enum cram_DS_ID { |
130 | | DS_CORE = 0, |
131 | | DS_aux = 1, // aux_blk |
132 | | DS_aux_OQ = 2, |
133 | | DS_aux_BQ = 3, |
134 | | DS_aux_BD = 4, |
135 | | DS_aux_BI = 5, |
136 | | DS_aux_FZ = 6, // also ZM:B |
137 | | DS_aux_oq = 7, // other qualities |
138 | | DS_aux_os = 8, // other sequences |
139 | | DS_aux_oz = 9, // other strings |
140 | | DS_ref, |
141 | | DS_RN, // name_blk |
142 | | DS_QS, // qual_blk |
143 | | DS_IN, // base_blk |
144 | | DS_SC, // soft_blk |
145 | | |
146 | | DS_BF, // start loop |
147 | | DS_CF, |
148 | | DS_AP, |
149 | | DS_RG, |
150 | | DS_MQ, |
151 | | DS_NS, |
152 | | DS_MF, |
153 | | DS_TS, |
154 | | DS_NP, |
155 | | DS_NF, |
156 | | DS_RL, |
157 | | DS_FN, |
158 | | DS_FC, |
159 | | DS_FP, |
160 | | DS_DL, |
161 | | DS_BA, |
162 | | DS_BS, |
163 | | DS_TL, |
164 | | DS_RI, |
165 | | DS_RS, |
166 | | DS_PD, |
167 | | DS_HC, |
168 | | DS_BB, |
169 | | DS_QQ, |
170 | | |
171 | | DS_TN, // end loop |
172 | | |
173 | | DS_RN_len, |
174 | | DS_SC_len, |
175 | | DS_BB_len, |
176 | | DS_QQ_len, |
177 | | |
178 | | DS_TC, // CRAM v1.0 tags |
179 | | DS_TM, // test |
180 | | DS_TV, // test |
181 | | |
182 | | DS_END, |
183 | | }; |
184 | | |
185 | | /* "File Definition Structure" */ |
186 | | struct cram_file_def { |
187 | | char magic[4]; |
188 | | uint8_t major_version; |
189 | | uint8_t minor_version; |
190 | | char file_id[20] HTS_NONSTRING; // Filename or SHA1 checksum |
191 | | }; |
192 | | |
193 | 23.7M | #define CRAM_MAJOR_VERS(v) ((v) >> 8) |
194 | 16.7k | #define CRAM_MINOR_VERS(v) ((v) & 0xff) |
195 | | |
196 | | struct cram_slice; |
197 | | |
198 | | // Internal version of htslib/cram.h enum. |
199 | | // Note these have to match the layout of methmap and methcost in |
200 | | // cram_io.c:cram_compress_block2 |
201 | | enum cram_block_method_int { |
202 | | // Public methods as defined in the CRAM spec. |
203 | | BM_ERROR = -1, |
204 | | |
205 | | // CRAM 2.x and 3.0 |
206 | | RAW = 0, |
207 | | GZIP = 1, |
208 | | BZIP2 = 2, |
209 | | LZMA = 3, |
210 | | RANS = 4, RANS0 = RANS, |
211 | | |
212 | | // CRAM 3.1 onwards |
213 | | RANSPR = 5, RANS_PR0 = RANSPR, |
214 | | ARITH = 6, ARITH_PR0 = ARITH, |
215 | | FQZ = 7, |
216 | | TOK3 = 8, |
217 | | // BSC = 9, ZSTD = 10 |
218 | | |
219 | | // Methods not externalised, but used in metrics. |
220 | | // Externally they become one of the above methods. |
221 | | GZIP_RLE = 11, |
222 | | GZIP_1, // Z_DEFAULT_STRATEGY level 1, NB: not externalised in CRAM |
223 | | |
224 | | FQZ_b, FQZ_c, FQZ_d, // Various preset FQZ methods |
225 | | |
226 | | //RANS0, // Order 0 |
227 | | RANS1, |
228 | | |
229 | | //RANS_PR0, // Order 0 |
230 | | RANS_PR1, // Order 1 |
231 | | RANS_PR64, // O0 + RLE |
232 | | RANS_PR9, // O1 + X4 |
233 | | RANS_PR128, // O0 + Pack |
234 | | RANS_PR129, // O1 + Pack |
235 | | RANS_PR192, // O0 + RLE + pack |
236 | | RANS_PR193, // O1 + RLE + pack |
237 | | |
238 | | //TOK3, // tok+rans |
239 | | TOKA, // tok+arith |
240 | | |
241 | | //ARITH_PR0, // Order 0 |
242 | | ARITH_PR1, // Order 1 |
243 | | ARITH_PR64, // O0 + RLE |
244 | | ARITH_PR9, // O1 + X4 |
245 | | ARITH_PR128, // O0 + Pack |
246 | | ARITH_PR129, // O1 + Pack |
247 | | ARITH_PR192, // O0 + RLE + pack |
248 | | ARITH_PR193, // O1 + RLE + pack |
249 | | |
250 | | // NB: must end on no more than 31 unless we change to a |
251 | | // 64-bit method type. |
252 | | }; |
253 | | |
254 | | /* Now in htslib/cram.h |
255 | | enum cram_content_type { |
256 | | CT_ERROR = -1, |
257 | | FILE_HEADER = 0, |
258 | | COMPRESSION_HEADER = 1, |
259 | | MAPPED_SLICE = 2, |
260 | | UNMAPPED_SLICE = 3, // CRAM V1.0 only |
261 | | EXTERNAL = 4, |
262 | | CORE = 5, |
263 | | }; |
264 | | */ |
265 | | |
266 | | /* Maximum simultaneous codecs allowed, 1 per bit */ |
267 | 7.86M | #define CRAM_MAX_METHOD 32 |
268 | | |
269 | | /* Compression metrics */ |
270 | | struct cram_metrics { |
271 | | // number of trials and time to next trial |
272 | | int trial; |
273 | | int next_trial; |
274 | | int consistency; |
275 | | |
276 | | // aggregate sizes during trials |
277 | | int sz[CRAM_MAX_METHOD]; |
278 | | int input_avg_sz, input_avg_delta; |
279 | | |
280 | | // resultant method from trials |
281 | | int method, revised_method; |
282 | | int strat; |
283 | | |
284 | | // Revisions of method, to allow culling of continually failing ones. |
285 | | int cnt[CRAM_MAX_METHOD]; |
286 | | |
287 | | double extra[CRAM_MAX_METHOD]; |
288 | | |
289 | | // Not amenable to rANS bit-packing techniques; cardinality > 16 |
290 | | int unpackable; |
291 | | }; |
292 | | |
293 | | // Hash aux key (XX:i) to cram_metrics |
294 | 0 | KHASH_MAP_INIT_INT(m_metrics, cram_metrics*) |
295 | 0 |
|
296 | 0 |
|
297 | 0 | /* Block */ |
298 | 0 | struct cram_block { |
299 | 0 | enum cram_block_method_int method, orig_method; |
300 | 0 | enum cram_content_type content_type; |
301 | 0 | int32_t content_id; |
302 | 0 | int32_t comp_size; |
303 | 0 | int32_t uncomp_size; |
304 | 0 | uint32_t crc32; |
305 | 0 | int32_t idx; /* offset into data */ |
306 | 0 | unsigned char *data; |
307 | 0 |
|
308 | 0 | // For bit I/O |
309 | 0 | size_t alloc; |
310 | 0 | size_t byte; |
311 | 0 | int bit; |
312 | 0 |
|
313 | 0 | // To aid compression |
314 | 0 | cram_metrics *m; // used to track aux block compression only |
315 | 0 |
|
316 | 0 | int crc32_checked; |
317 | 0 | uint32_t crc_part; |
318 | 0 | }; |
319 | 0 |
|
320 | 0 | struct cram_codec; /* defined in cram_codecs.h */ |
321 | 0 | struct cram_map; |
322 | 0 |
|
323 | 3.41M | #define CRAM_MAP_HASH 32 |
324 | 45.7k | #define CRAM_MAP(a,b) (((a)*3+(b))&(CRAM_MAP_HASH-1)) |
325 | | |
326 | | /* Compression header block */ |
327 | | struct cram_block_compression_hdr { |
328 | | int32_t ref_seq_id; |
329 | | int64_t ref_seq_start; |
330 | | int64_t ref_seq_span; |
331 | | int32_t num_records; |
332 | | int32_t num_landmarks; |
333 | | int32_t *landmark; |
334 | | |
335 | | /* Flags from preservation map */ |
336 | | int read_names_included; |
337 | | int AP_delta; |
338 | | // indexed by ref-base and subst. code |
339 | | char substitution_matrix[5][4]; |
340 | | int no_ref; |
341 | | int qs_seq_orient; // 1 => same as seq. 0 => original orientation |
342 | | |
343 | | // TD Dictionary as a concatenated block |
344 | | cram_block *TD_blk; // Tag Dictionary |
345 | | int nTL; // number of TL entries in TD |
346 | | unsigned char **TL; // array of size nTL, pointer into TD_blk. |
347 | | khash_t(m_s2i) *TD_hash; // Keyed on TD strings, map to TL[] indices |
348 | | string_alloc_t *TD_keys; // Pooled keys for TD hash. |
349 | | |
350 | | khash_t(map) *preservation_map; |
351 | | struct cram_map *rec_encoding_map[CRAM_MAP_HASH]; |
352 | | struct cram_map *tag_encoding_map[CRAM_MAP_HASH]; |
353 | | |
354 | | struct cram_codec *codecs[DS_END]; |
355 | | |
356 | | char *uncomp; // A single block of uncompressed data |
357 | | size_t uncomp_size, uncomp_alloc; |
358 | | |
359 | | // Total codec count, used for index to block_by_id for transforms |
360 | | int ncodecs; |
361 | | }; |
362 | | |
363 | | typedef struct cram_map { |
364 | | int key; /* 0xe0 + 3 bytes */ |
365 | | enum cram_encoding encoding; |
366 | | int offset; /* Offset into a single block of memory */ |
367 | | int size; /* Size */ |
368 | | struct cram_codec *codec; |
369 | | struct cram_map *next; // for noddy internal hash |
370 | | } cram_map; |
371 | | |
372 | | typedef struct cram_tag_map { |
373 | | struct cram_codec *codec; |
374 | | cram_block *blk; |
375 | | cram_block *blk2; |
376 | | cram_metrics *m; |
377 | | } cram_tag_map; |
378 | | |
379 | | // Hash aux key (XX:i) to cram_tag_map |
380 | 0 | KHASH_MAP_INIT_INT(m_tagmap, cram_tag_map*) |
381 | 0 |
|
382 | 0 | /* Mapped or unmapped slice header block */ |
383 | 0 | struct cram_block_slice_hdr { |
384 | 0 | enum cram_content_type content_type; |
385 | 0 | int32_t ref_seq_id; /* if content_type == MAPPED_SLICE */ |
386 | 0 | int64_t ref_seq_start; /* if content_type == MAPPED_SLICE */ |
387 | 0 | int64_t ref_seq_span; /* if content_type == MAPPED_SLICE */ |
388 | 0 | int32_t num_records; |
389 | 0 | int64_t record_counter; |
390 | 0 | int32_t num_blocks; |
391 | 0 | int32_t num_content_ids; |
392 | 0 | int32_t *block_content_ids; |
393 | 0 | int32_t ref_base_id; /* if content_type == MAPPED_SLICE */ |
394 | 0 | unsigned char md5[16]; |
395 | 0 | }; |
396 | 0 |
|
397 | 0 | struct ref_entry; |
398 | 0 |
|
399 | 0 | /* |
400 | 0 | * Container. |
401 | 0 | * |
402 | 0 | * Conceptually a container is split into slices, and slices into blocks. |
403 | 0 | * However on disk it's just a list of blocks and we need to query the |
404 | 0 | * block types to identify the start/end points of the slices. |
405 | 0 | * |
406 | 0 | * OR... are landmarks the start/end points of slices? |
407 | 0 | */ |
408 | 0 | struct cram_container { |
409 | 0 | int32_t length; |
410 | 0 | int32_t ref_seq_id; |
411 | 0 | int64_t ref_seq_start; |
412 | 0 | int64_t ref_seq_span; |
413 | 0 | int64_t record_counter; |
414 | 0 | int64_t num_bases; |
415 | 0 | int32_t num_records; |
416 | 0 | int32_t num_blocks; |
417 | 0 | int32_t num_landmarks; |
418 | 0 | int32_t *landmark; |
419 | 0 |
|
420 | 0 | /* Size of container header above */ |
421 | 0 | size_t offset; |
422 | 0 |
|
423 | 0 | /* Compression header is always the first block? */ |
424 | 0 | cram_block_compression_hdr *comp_hdr; |
425 | 0 | cram_block *comp_hdr_block; |
426 | 0 |
|
427 | 0 | /* For construction purposes */ |
428 | 0 | int max_slice, curr_slice; // maximum number of slices |
429 | 0 | int curr_slice_mt; // Curr_slice when reading ahead (via threads) |
430 | 0 | int max_rec, curr_rec; // current and max recs per slice |
431 | 0 | int max_c_rec, curr_c_rec; // current and max recs per container |
432 | 0 | int slice_rec; // rec no. for start of this slice |
433 | 0 | int curr_ref; // current ref ID. -2 for no previous |
434 | 0 | int64_t last_pos; // last record position |
435 | 0 | struct cram_slice **slices, *slice; |
436 | 0 | int pos_sorted; // boolean, 1=>position sorted data |
437 | 0 | int64_t max_apos; // maximum position, used if pos_sorted==0 |
438 | 0 | int last_slice; // number of reads in last slice (0 for 1st) |
439 | 0 | int multi_seq; // true if packing multi seqs per cont/slice |
440 | 0 | int unsorted; // true is AP_delta is 0. |
441 | 0 | int qs_seq_orient; // 1 => same as seq. 0 => original orientation |
442 | 0 |
|
443 | 0 | /* Copied from fd before encoding, to allow multi-threading */ |
444 | 0 | int ref_id; |
445 | 0 | hts_pos_t ref_start, first_base, last_base, ref_end; |
446 | 0 | char *ref; |
447 | 0 | int embed_ref; // 1 if embedding ref, 2 if embedding cons |
448 | 0 | int no_ref; // true if referenceless |
449 | 0 | //struct ref_entry *ref; |
450 | 0 |
|
451 | 0 | /* For multi-threading */ |
452 | 0 | bam_seq_t *bams; |
453 | 0 | int nbams; // size of associated bams array |
454 | 0 |
|
455 | 0 | /* Statistics for encoding */ |
456 | 0 | cram_stats *stats[DS_END]; |
457 | 0 |
|
458 | 0 | khash_t(m_tagmap) *tags_used; // set of tag types in use, for tag encoding map |
459 | 0 | int *refs_used; // array of frequency of ref seq IDs |
460 | 0 |
|
461 | 0 | uint32_t crc32; // CRC32 |
462 | 0 |
|
463 | 0 | uint64_t s_num_bases; // number of bases in this slice |
464 | 0 | uint64_t s_aux_bytes; // number of bytes of aux in BAM |
465 | 0 |
|
466 | 0 | uint32_t n_mapped; // Number of mapped reads |
467 | 0 | int ref_free; // whether 'ref' is owned by us and must be freed. |
468 | 0 | }; |
469 | 0 |
|
470 | 0 | /* |
471 | 0 | * A single cram record |
472 | 0 | */ |
473 | 0 | typedef struct cram_record { |
474 | 0 | struct cram_slice *s; // Filled out by cram_decode only |
475 | 0 |
|
476 | 0 | int32_t ref_id; // fixed for all recs in slice? |
477 | 0 | int32_t flags; // BF |
478 | 0 | int32_t cram_flags; // CF |
479 | 0 | int32_t len; // RL |
480 | 0 | int64_t apos; // AP |
481 | 0 | int32_t rg; // RG |
482 | 0 | int32_t name; // RN; idx to s->names_blk |
483 | 0 | int32_t name_len; |
484 | 0 | int32_t mate_line; // index to another cram_record |
485 | 0 | int32_t mate_ref_id; |
486 | 0 | int64_t mate_pos; // NP |
487 | 0 | int64_t tlen; // TS |
488 | 0 | int64_t explicit_tlen;// TS, but PNEXT/RNEXT still need auto-computing |
489 | 0 |
|
490 | 0 | // Auxiliary data |
491 | 0 | int32_t ntags; // TC |
492 | 0 | uint32_t aux; // idx to s->aux_blk |
493 | 0 | uint32_t aux_size; // total size of packed ntags in aux_blk |
494 | 0 | #ifndef TN_external |
495 | 0 | int32_t TN_idx; // TN; idx to s->TN; |
496 | 0 | #else |
497 | 0 | int32_t tn; // idx to s->tn_blk |
498 | 0 | #endif |
499 | 0 | int TL; |
500 | 0 |
|
501 | 0 | uint32_t seq; // idx to s->seqs_blk |
502 | 0 | uint32_t qual; // idx to s->qual_blk |
503 | 0 | uint32_t cigar; // idx to s->cigar |
504 | 0 | int32_t ncigar; |
505 | 0 | int64_t aend; // alignment end |
506 | 0 | int32_t mqual; // MQ |
507 | 0 |
|
508 | 0 | uint32_t feature; // idx to s->feature |
509 | 0 | uint32_t nfeature; // number of features |
510 | 0 | int32_t mate_flags; // MF |
511 | 0 |
|
512 | 0 | int has_CG; // used to avoid bam_tag2cigar call |
513 | 0 | } cram_record; |
514 | 0 |
|
515 | 0 | // Accessor macros as an analogue of the bam ones |
516 | 0 | #define cram_qname(c) (&(c)->s->name_blk->data[(c)->name]) |
517 | 0 | #define cram_seq(c) (&(c)->s->seqs_blk->data[(c)->seq]) |
518 | 0 | #define cram_qual(c) (&(c)->s->qual_blk->data[(c)->qual]) |
519 | 0 | #define cram_aux(c) (&(c)->s->aux_blk->data[(c)->aux]) |
520 | 0 | #define cram_seqi(c,i) (cram_seq((c))[(i)]) |
521 | 0 | #define cram_name_len(c) ((c)->name_len) |
522 | 0 | #define cram_strand(c) (((c)->flags & BAM_FREVERSE) != 0) |
523 | 0 | #define cram_mstrand(c) (((c)->flags & BAM_FMREVERSE) != 0) |
524 | 0 | #define cram_cigar(c) (&((cr)->s->cigar)[(c)->cigar]) |
525 | 0 |
|
526 | 0 | /* |
527 | 0 | * A feature is a base difference, used for the sequence reference encoding. |
528 | 0 | * (We generate these internally when writing CRAM.) |
529 | 0 | */ |
530 | 0 | typedef union cram_feature { |
531 | 0 | struct { |
532 | 0 | int pos; |
533 | 0 | int code; |
534 | 0 | int base; // substitution code |
535 | 0 | } X; |
536 | 0 | struct { |
537 | 0 | int pos; |
538 | 0 | int code; |
539 | 0 | int base; // actual base & qual |
540 | 0 | int qual; |
541 | 0 | } B; |
542 | 0 | struct { |
543 | 0 | int pos; |
544 | 0 | int code; |
545 | 0 | int seq_idx; // index to s->seqs_blk |
546 | 0 | int len; |
547 | 0 | } b; |
548 | 0 | struct { |
549 | 0 | int pos; |
550 | 0 | int code; |
551 | 0 | int qual; |
552 | 0 | } Q; |
553 | 0 | struct { |
554 | 0 | int pos; |
555 | 0 | int code; |
556 | 0 | int len; |
557 | 0 | int seq_idx; // soft-clip multiple bases |
558 | 0 | } S; |
559 | 0 | struct { |
560 | 0 | int pos; |
561 | 0 | int code; |
562 | 0 | int len; |
563 | 0 | int seq_idx; // insertion multiple bases |
564 | 0 | } I; |
565 | 0 | struct { |
566 | 0 | int pos; |
567 | 0 | int code; |
568 | 0 | int base; // insertion single base |
569 | 0 | } i; |
570 | 0 | struct { |
571 | 0 | int pos; |
572 | 0 | int code; |
573 | 0 | int len; |
574 | 0 | } D; |
575 | 0 | struct { |
576 | 0 | int pos; |
577 | 0 | int code; |
578 | 0 | int len; |
579 | 0 | } N; |
580 | 0 | struct { |
581 | 0 | int pos; |
582 | 0 | int code; |
583 | 0 | int len; |
584 | 0 | } P; |
585 | 0 | struct { |
586 | 0 | int pos; |
587 | 0 | int code; |
588 | 0 | int len; |
589 | 0 | } H; |
590 | 0 | } cram_feature; |
591 | 0 |
|
592 | 0 | typedef struct bam_list { |
593 | 0 | bam_seq_t *bams; |
594 | 0 | struct bam_list *next; |
595 | 0 | int nbams; |
596 | 0 | } bam_list; |
597 | 0 |
|
598 | 0 | /* |
599 | 0 | * A slice is really just a set of blocks, but it |
600 | 0 | * is the logical unit for decoding a number of |
601 | 0 | * sequences. |
602 | 0 | */ |
603 | 0 | struct cram_slice { |
604 | 0 | cram_block_slice_hdr *hdr; |
605 | 0 | cram_block *hdr_block; |
606 | 0 | cram_block **block; |
607 | 0 | cram_block **block_by_id; |
608 | 0 |
|
609 | 0 | /* State used during encoding/decoding */ |
610 | 0 | int64_t last_apos, max_apos; |
611 | 0 |
|
612 | 0 | /* Array of decoded cram records */ |
613 | 0 | cram_record *crecs; |
614 | 0 |
|
615 | 0 | /* An dynamically growing buffers for data pointed |
616 | 0 | * to by crecs[] array. |
617 | 0 | */ |
618 | 0 | uint32_t *cigar; |
619 | 0 | uint32_t cigar_alloc; |
620 | 0 | uint32_t ncigar; |
621 | 0 |
|
622 | 0 | cram_feature *features; |
623 | 0 | uint32_t nfeatures; |
624 | 0 | uint32_t afeatures; // allocated size of features |
625 | 0 |
|
626 | 0 | #ifndef TN_external |
627 | 0 | // TN field (Tag Name) |
628 | 0 | uint32_t *TN; |
629 | 0 | int nTN, aTN; // used and allocated size for TN[] |
630 | 0 | #else |
631 | 0 | cram_block *tn_blk; |
632 | 0 | int tn_id; |
633 | 0 | #endif |
634 | 0 |
|
635 | 0 | // For variable sized elements which are always external blocks. |
636 | 0 | cram_block *name_blk; |
637 | 0 | cram_block *seqs_blk; |
638 | 0 | cram_block *qual_blk; |
639 | 0 | cram_block *base_blk; |
640 | 0 | cram_block *soft_blk; |
641 | 0 | cram_block *aux_blk; // BAM aux block, created while decoding CRAM |
642 | 0 |
|
643 | 0 | string_alloc_t *pair_keys; // Pooled keys for pair hash. |
644 | 0 | khash_t(m_s2i) *pair[2]; // for identifying read-pairs in this slice. |
645 | 0 |
|
646 | 0 | char *ref; // slice of current reference |
647 | 0 | hts_pos_t ref_start; // start position of current reference; |
648 | 0 | hts_pos_t ref_end; // end position of current reference; |
649 | 0 | int ref_id; |
650 | 0 |
|
651 | 0 | // For going from BAM to CRAM; an array of auxiliary blocks per type |
652 | 0 | int naux_block; |
653 | 0 | cram_block **aux_block; |
654 | 0 |
|
655 | 0 | unsigned int data_series; // See cram_fields enum |
656 | 0 | int decode_md; |
657 | 0 |
|
658 | 0 | int max_rec, curr_rec; // current and max recs per slice |
659 | 0 | int slice_num; // To be copied into c->curr_slice in decode |
660 | 0 |
|
661 | 0 | // Cache of converted BAM structs |
662 | 0 | bam_list *bl; |
663 | 0 | }; |
664 | 0 |
|
665 | 0 | /*----------------------------------------------------------------------------- |
666 | 0 | * Consider moving reference handling to cram_refs.[ch] |
667 | 0 | */ |
668 | 0 | // from fa.fai / samtools faidx files |
669 | 0 | typedef struct ref_entry { |
670 | 0 | char *name; |
671 | 0 | char *fn; |
672 | 0 | int64_t length; // if 0 this indicates we haven't loaded it yet |
673 | 0 | int64_t LN_length; // @SQ LN length, used to trim consensus ref |
674 | 0 | int64_t offset; |
675 | 0 | int bases_per_line; |
676 | 0 | int line_length; |
677 | 0 | int64_t count; // for shared references so we know to dealloc seq |
678 | 0 | char *seq; |
679 | 0 | mFILE *mf; |
680 | 0 | int is_md5; // Reference comes from a raw seq found by MD5 |
681 | 0 | int validated_md5; |
682 | 0 | } ref_entry; |
683 | 0 |
|
684 | 0 | KHASH_MAP_INIT_STR(refs, ref_entry*) |
685 | 0 |
|
686 | 0 | // References structure. |
687 | 0 | struct refs_t { |
688 | 0 | string_alloc_t *pool; // String pool for holding filenames and SN vals |
689 | 0 |
|
690 | 0 | khash_t(refs) *h_meta; // ref_entry*, index by name |
691 | 0 | ref_entry **ref_id; // ref_entry*, index by ID |
692 | 0 | int nref; // number of ref_entry |
693 | 0 |
|
694 | 0 | char *fn; // current file opened |
695 | 0 | BGZF *fp; // and the hFILE* to go with it. |
696 | 0 |
|
697 | 0 | int count; // how many cram_fd sharing this refs struct |
698 | 0 |
|
699 | 0 | pthread_mutex_t lock; // Mutex for multi-threaded updating |
700 | 0 | ref_entry *last; // Last queried sequence |
701 | 0 | int last_id; // Used in cram_ref_decr_locked to delay free |
702 | 0 | }; |
703 | 0 |
|
704 | 0 | /*----------------------------------------------------------------------------- |
705 | 0 | * CRAM index |
706 | 0 | * |
707 | 0 | * Detect format by number of entries per line. |
708 | 0 | * 5 => 1.0 (refid, start, nseq, C offset, slice) |
709 | 0 | * 6 => 1.1 (refid, start, span, C offset, S offset, S size) |
710 | 0 | * |
711 | 0 | * Indices are stored in a nested containment list, which is trivial to set |
712 | 0 | * up as the indices are on sorted data so we're appending to the nclist |
713 | 0 | * in sorted order. Basically if a slice entirely fits within a previous |
714 | 0 | * slice then we append to that slices list. This is done recursively. |
715 | 0 | * |
716 | 0 | * Lists are sorted on two dimensions: ref id + slice coords. |
717 | 0 | */ |
718 | 0 | typedef struct cram_index { |
719 | 0 | int nslice, nalloc; // total number of slices |
720 | 0 | struct cram_index *e; // array of size nslice |
721 | 0 |
|
722 | 0 | int refid; // 1.0 1.1 |
723 | 0 | int start; // 1.0 1.1 |
724 | 0 | int end; // 1.1 |
725 | 0 | int nseq; // 1.0 - undocumented |
726 | 0 | int slice; // 1.0 landmark index, 1.1 landmark value |
727 | 0 | int len; // 1.1 - size of slice in bytes |
728 | 0 | int64_t offset; // 1.0 1.1 |
729 | 0 |
|
730 | 0 | // Linked list of cram_index entries. Used to convert recursive |
731 | 0 | // NCList back to a linear list. |
732 | 0 | struct cram_index *e_next; |
733 | 0 | } cram_index; |
734 | 0 |
|
735 | 0 | typedef struct { |
736 | 0 | int refid; |
737 | 0 | int64_t start; |
738 | 0 | int64_t end; |
739 | 0 | } cram_range; |
740 | 0 |
|
741 | 0 | /*----------------------------------------------------------------------------- |
742 | 0 | */ |
743 | 0 | /* CRAM File handle */ |
744 | 0 |
|
745 | 0 | struct cram_fd; |
746 | 0 | typedef struct varint_vec { |
747 | 0 | // Returns number of bytes decoded from fd, 0 on error |
748 | 0 | int (*varint_decode32_crc)(struct cram_fd *fd, int32_t *val_p, uint32_t *crc); |
749 | 0 | int (*varint_decode32s_crc)(struct cram_fd *fd, int32_t *val_p, uint32_t *crc); |
750 | 0 | int (*varint_decode64_crc)(struct cram_fd *fd, int64_t *val_p, uint32_t *crc); |
751 | 0 |
|
752 | 0 | // Returns the value and increments *cp. Sets err to 1 iff an error occurs. |
753 | 0 | // NOTE: Does not set err to 0 on success. |
754 | 0 | int64_t (*varint_get32) (char **cp, const char *endp, int *err); |
755 | 0 | int64_t (*varint_get32s)(char **cp, const char *endp, int *err); |
756 | 0 | int64_t (*varint_get64) (char **cp, const char *endp, int *err); |
757 | 0 | int64_t (*varint_get64s)(char **cp, const char *endp, int *err); |
758 | 0 |
|
759 | 0 | // Returns the number of bytes written, <= 0 on error. |
760 | 0 | int (*varint_put32) (char *cp, char *endp, int32_t val_p); |
761 | 0 | int (*varint_put32s)(char *cp, char *endp, int32_t val_p); |
762 | 0 | int (*varint_put64) (char *cp, char *endp, int64_t val_p); |
763 | 0 | int (*varint_put64s)(char *cp, char *endp, int64_t val_p); |
764 | 0 |
|
765 | 0 | // Returns the number of bytes written, <= 0 on error. |
766 | 0 | int (*varint_put32_blk) (cram_block *blk, int32_t val_p); |
767 | 0 | int (*varint_put32s_blk)(cram_block *blk, int32_t val_p); |
768 | 0 | int (*varint_put64_blk) (cram_block *blk, int64_t val_p); |
769 | 0 | int (*varint_put64s_blk)(cram_block *blk, int64_t val_p); |
770 | 0 |
|
771 | 0 | // Returns number of bytes needed to encode 'val' |
772 | 0 | int (*varint_size)(int64_t val); |
773 | 0 | } varint_vec; |
774 | 0 |
|
775 | 0 | struct cram_fd { |
776 | 0 | struct hFILE *fp; |
777 | 0 | int mode; // 'r' or 'w' |
778 | 0 | int version; |
779 | 0 | cram_file_def *file_def; |
780 | 0 | sam_hdr_t *header; |
781 | 0 |
|
782 | 0 | char *prefix; |
783 | 0 | int64_t record_counter; |
784 | 0 | int err; |
785 | 0 |
|
786 | 0 | // Most recent compression header decoded |
787 | 0 | //cram_block_compression_hdr *comp_hdr; |
788 | 0 | //cram_block_slice_hdr *slice_hdr; |
789 | 0 |
|
790 | 0 | // Current container being processed |
791 | 0 | cram_container *ctr; |
792 | 0 |
|
793 | 0 | // Current container used for decoder threads |
794 | 0 | cram_container *ctr_mt; |
795 | 0 |
|
796 | 0 | // positions for encoding or decoding |
797 | 0 | int first_base, last_base; // copied to container |
798 | 0 |
|
799 | 0 | // cached reference portion |
800 | 0 | refs_t *refs; // ref meta-data structure |
801 | 0 | char *ref, *ref_free; // current portion held in memory |
802 | 0 | int ref_id; // copied to container |
803 | 0 | hts_pos_t ref_start; // copied to container |
804 | 0 | hts_pos_t ref_end; // copied to container |
805 | 0 | char *ref_fn; // reference fasta filename |
806 | 0 |
|
807 | 0 | // compression level and metrics |
808 | 0 | int level; |
809 | 0 | cram_metrics *m[DS_END]; |
810 | 0 | khash_t(m_metrics) *tags_used; // cram_metrics[], per tag types in use. |
811 | 0 |
|
812 | 0 | // options |
813 | 0 | int decode_md; // Whether to export MD and NM tags |
814 | 0 | int seqs_per_slice; |
815 | 0 | int bases_per_slice; |
816 | 0 | int slices_per_container; |
817 | 0 | int embed_ref; // copied to container |
818 | 0 | int no_ref; // copied to container |
819 | 0 | int no_ref_counter; // decide if permanent switch |
820 | 0 | int ignore_md5; |
821 | 0 | int use_bz2; |
822 | 0 | int use_rans; |
823 | 0 | int use_lzma; |
824 | 0 | int use_fqz; |
825 | 0 | int use_tok; |
826 | 0 | int use_arith; |
827 | 0 | int shared_ref; |
828 | 0 | unsigned int required_fields; |
829 | 0 | int store_md; |
830 | 0 | int store_nm; |
831 | 0 | int remove_ur; |
832 | 0 | cram_range range; |
833 | 0 |
|
834 | 0 | // lookup tables, stored here so we can be trivially multi-threaded |
835 | 0 | unsigned int bam_flag_swap[0x1000]; // cram -> bam flags |
836 | 0 | unsigned int cram_flag_swap[0x1000];// bam -> cram flags |
837 | 0 | unsigned char L1[256]; // ACGT{*} ->0123{4} |
838 | 0 | unsigned char L2[256]; // ACGTN{*}->01234{5} |
839 | 0 | char cram_sub_matrix[32][32]; // base substitution codes |
840 | 0 |
|
841 | 0 | int index_sz; |
842 | 0 | cram_index *index; // array, sizeof index_sz |
843 | 0 | off_t first_container; |
844 | 0 | off_t curr_position; |
845 | 0 | int eof; |
846 | 0 | int last_slice; // number of recs encoded in last slice |
847 | 0 | int last_RI_count; // number of references encoded in last container |
848 | 0 | int multi_seq; // -1 is auto, 0 is one ref per container, 1 is multi... |
849 | 0 | int multi_seq_user; // Original user setting (CRAM_OPT_MULTI_SEQ_PER_SLICE) |
850 | 0 | int unsorted; |
851 | 0 | int last_mapped; // number of mapped reads in last container |
852 | 0 | int empty_container; // Marker for EOF block |
853 | 0 |
|
854 | 0 | // thread pool |
855 | 0 | int own_pool; |
856 | 0 | hts_tpool *pool; |
857 | 0 | hts_tpool_process *rqueue; |
858 | 0 | pthread_mutex_t metrics_lock; |
859 | 0 | pthread_mutex_t ref_lock; |
860 | 0 | pthread_mutex_t range_lock; |
861 | 0 | bam_list *bl; // linked list of arrays of spare bam records |
862 | 0 | pthread_mutex_t bam_list_lock; |
863 | 0 | void *job_pending; |
864 | 0 | int ooc; // out of containers. |
865 | 0 |
|
866 | 0 | int lossy_read_names; // boolean |
867 | 0 | int tlen_approx; // max TLEN calculation offset. |
868 | 0 | int tlen_zero; // If true, permit tlen 0 (=> tlen calculated) |
869 | 0 |
|
870 | 0 | BGZF *idxfp; // File pointer for on-the-fly index creation |
871 | 0 |
|
872 | 0 | // Variable integer decoding callbacks. |
873 | 0 | // This changed in CRAM4.0 to a data-size agnostic encoding, |
874 | 0 | // but isn't supported in this htslib release. |
875 | 0 | varint_vec vv; |
876 | 0 |
|
877 | 0 | // Force AP delta even on non positional sorted data. |
878 | 0 | // This can be beneficial for pairs where pairs are nearby each other. |
879 | 0 | // We suffer with delta to unrelated things (previous pair), but gain |
880 | 0 | // in delta between them. (Ideal would be a per read setting.) |
881 | 0 | int ap_delta; |
882 | 0 | }; |
883 | 0 |
|
884 | 0 | // Translation of required fields to cram data series |
885 | 0 | enum cram_fields { |
886 | 0 | CRAM_BF = 0x00000001, |
887 | 0 | CRAM_AP = 0x00000002, |
888 | 0 | CRAM_FP = 0x00000004, |
889 | 0 | CRAM_RL = 0x00000008, |
890 | 0 | CRAM_DL = 0x00000010, |
891 | 0 | CRAM_NF = 0x00000020, |
892 | 0 | CRAM_BA = 0x00000040, |
893 | 0 | CRAM_QS = 0x00000080, |
894 | 0 | CRAM_FC = 0x00000100, |
895 | 0 | CRAM_FN = 0x00000200, |
896 | 0 | CRAM_BS = 0x00000400, |
897 | 0 | CRAM_IN = 0x00000800, |
898 | 0 | CRAM_RG = 0x00001000, |
899 | 0 | CRAM_MQ = 0x00002000, |
900 | 0 | CRAM_TL = 0x00004000, |
901 | 0 | CRAM_RN = 0x00008000, |
902 | 0 | CRAM_NS = 0x00010000, |
903 | 0 | CRAM_NP = 0x00020000, |
904 | 0 | CRAM_TS = 0x00040000, |
905 | 0 | CRAM_MF = 0x00080000, |
906 | 0 | CRAM_CF = 0x00100000, |
907 | 0 | CRAM_RI = 0x00200000, |
908 | 0 | CRAM_RS = 0x00400000, |
909 | 0 | CRAM_PD = 0x00800000, |
910 | 0 | CRAM_HC = 0x01000000, |
911 | 0 | CRAM_SC = 0x02000000, |
912 | 0 | CRAM_BB = 0x04000000, |
913 | 0 | CRAM_BB_len = 0x08000000, |
914 | 0 | CRAM_QQ = 0x10000000, |
915 | 0 | CRAM_QQ_len = 0x20000000, |
916 | 0 | CRAM_aux= 0x40000000, |
917 | 0 | CRAM_ALL= 0x7fffffff, |
918 | 0 | }; |
919 | 0 |
|
920 | 0 | // A CIGAR opcode, but not necessarily the implications of it. Eg FC/FP may |
921 | 0 | // encode a base difference, but we don't need to know what it is for CIGAR. |
922 | 0 | // If we have a soft-clip or insertion, we do need SC/IN though to know how |
923 | 0 | // long that array is. |
924 | 0 | #define CRAM_CIGAR (CRAM_FN | CRAM_FP | CRAM_FC | CRAM_DL | CRAM_IN | \ |
925 | 0 | CRAM_SC | CRAM_HC | CRAM_PD | CRAM_RS | CRAM_RL | CRAM_BF) |
926 | | |
927 | 0 | #define CRAM_SEQ (CRAM_CIGAR | CRAM_BA | CRAM_BS | \ |
928 | 0 | CRAM_RL | CRAM_AP | CRAM_BB) |
929 | | |
930 | 0 | #define CRAM_QUAL (CRAM_CIGAR | CRAM_RL | CRAM_AP | CRAM_QS | CRAM_QQ) |
931 | | |
932 | | /* BF bitfields */ |
933 | | /* Corrected in 1.1. Use bam_flag_swap[bf] and BAM_* macros for 1.0 & 1.1 */ |
934 | 19.9M | #define CRAM_FPAIRED 256 |
935 | 19.9M | #define CRAM_FPROPER_PAIR 128 |
936 | 19.9M | #define CRAM_FUNMAP 64 |
937 | 19.9M | #define CRAM_FREVERSE 32 |
938 | 19.9M | #define CRAM_FREAD1 16 |
939 | 19.9M | #define CRAM_FREAD2 8 |
940 | 19.9M | #define CRAM_FSECONDARY 4 |
941 | 19.9M | #define CRAM_FQCFAIL 2 |
942 | 19.9M | #define CRAM_FDUP 1 |
943 | | |
944 | | #define DS_aux_S "\001" |
945 | | #define DS_aux_OQ_S "\002" |
946 | | #define DS_aux_BQ_S "\003" |
947 | | #define DS_aux_BD_S "\004" |
948 | | #define DS_aux_BI_S "\005" |
949 | | #define DS_aux_FZ_S "\006" |
950 | | #define DS_aux_oq_S "\007" |
951 | | #define DS_aux_os_S "\010" |
952 | | #define DS_aux_oz_S "\011" |
953 | | |
954 | 21.3k | #define CRAM_M_REVERSE 1 |
955 | 234k | #define CRAM_M_UNMAP 2 |
956 | | |
957 | | |
958 | | /* CF bitfields */ |
959 | 16.5M | #define CRAM_FLAG_PRESERVE_QUAL_SCORES (1<<0) |
960 | 16.5M | #define CRAM_FLAG_DETACHED (1<<1) |
961 | 27 | #define CRAM_FLAG_MATE_DOWNSTREAM (1<<2) |
962 | 5.18M | #define CRAM_FLAG_NO_SEQ (1<<3) |
963 | 9 | #define CRAM_FLAG_EXPLICIT_TLEN (1<<4) |
964 | 11.0M | #define CRAM_FLAG_MASK ((1<<5)-1) |
965 | | |
966 | | /* Internal only */ |
967 | 5.52M | #define CRAM_FLAG_STATS_ADDED (1<<30) |
968 | 0 | #define CRAM_FLAG_DISCARD_NAME (1U<<31) |
969 | | |
970 | | #ifdef __cplusplus |
971 | | } |
972 | | #endif |
973 | | |
974 | | #endif /* HTSLIB_CRAM_STRUCTS_H */ |