bio-bigwig 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,747 @@
1
+ #include "bigwigext.h"
2
+
3
+ #define SIZEOF_INT32 4
4
+ #define SIZEOF_INT64 8
5
+
6
+ #if SIZEOF_SHORT == SIZEOF_INT32
7
+ #define NUM2UINT32 NUM2USHORT
8
+ #define NUM2INT32 NUM2SHORT
9
+ #define UINT32_2NUM USHORT2NUM
10
+ #define INT32_2NUM SHORT2NUM
11
+ #elif SIZEOF_INT == SIZEOF_INT32
12
+ #define NUM2UINT32 NUM2UINT
13
+ #define NUM2INT32 NUM2INT
14
+ #define UINT32_2NUM UINT2NUM
15
+ #define INT32_2NUM INT2NUM
16
+ #elif SIZEOF_LONG == SIZEOF_INT32
17
+ #define NUM2UINT32 NUM2ULONG
18
+ #define NUM2INT32 NUM2LONG
19
+ #define UINT32_2NUM ULONG2NUM
20
+ #define INT32_2NUM LONG2NUM
21
+ #else
22
+ #error "Neither int, long, nor short is the same size as int32_t"
23
+ #endif
24
+
25
+ #if SIZEOF_INT == SIZEOF_INT64
26
+ #define NUM2UINT64 NUM2UINT
27
+ #define NUM2INT64 NUM2INT
28
+ #define UINT64_2NUM UINT2NUM
29
+ #define INT64_2NUM INT2NUM
30
+ #elif SIZEOF_LONG == SIZEOF_INT64
31
+ #define NUM2UINT64 NUM2ULONG
32
+ #define NUM2INT64 NUM2LONG
33
+ #define UINT64_2NUM ULONG2NUM
34
+ #define INT64_2NUM LONG2NUM
35
+ #elif SIZEOF_LONGLONG == SIZEOF_INT64
36
+ #define NUM2UINT64 NUM2ULL
37
+ #define NUM2INT64 NUM2LL
38
+ #define UINT64_2NUM ULL2NUM
39
+ #define INT64_2NUM LL2NUM
40
+ #else
41
+ #error "Neither int, long, nor short is the same size as int64_t"
42
+ #endif
43
+
44
+ VALUE rb_Bio;
45
+ VALUE rb_BigWig;
46
+
47
+ static void BigWig_free(void *ptr);
48
+ static size_t BigWig_memsize(const void *ptr);
49
+
50
+ static const rb_data_type_t BigWig_type = {
51
+ "BigWig",
52
+ {
53
+ 0,
54
+ BigWig_free,
55
+ BigWig_memsize,
56
+ },
57
+ 0,
58
+ 0,
59
+ RUBY_TYPED_FREE_IMMEDIATELY};
60
+
61
+ static void
62
+ BigWig_free(void *ptr)
63
+ {
64
+ if (ptr)
65
+ {
66
+ bwClose((bigWigFile_t *)ptr);
67
+ }
68
+ }
69
+
70
+ static size_t BigWig_memsize(const void *ptr)
71
+ {
72
+ const bigWigFile_t *data = ptr;
73
+
74
+ return data ? sizeof(*data) : 0;
75
+ }
76
+
77
+ static bigWigFile_t *get_bigWigFile(VALUE obj)
78
+ {
79
+ bigWigFile_t *data;
80
+ TypedData_Get_Struct(obj, bigWigFile_t, &BigWig_type, data);
81
+ return data;
82
+ }
83
+
84
+ static VALUE
85
+ bigwig_allocate(VALUE klass)
86
+ {
87
+ bigWigFile_t *bw = NULL;
88
+
89
+ return TypedData_Wrap_Struct(klass, &BigWig_type, bw);
90
+ }
91
+
92
+ //Return 1 if there are any entries at all
93
+ int hasEntries(bigWigFile_t *bw)
94
+ {
95
+ if (bw->hdr->indexOffset != 0)
96
+ return 1; // No index, no entries pyBigWig issue #111
97
+ //if(bw->hdr->nBasesCovered > 0) return 1; // Sometimes headers are broken
98
+ return 0;
99
+ }
100
+
101
+ static VALUE
102
+ bigwig_init(VALUE self, VALUE rb_fname, VALUE rb_mode)
103
+ {
104
+ char *fname = NULL;
105
+ char *mode = "r";
106
+ bigWigFile_t *bw = NULL;
107
+
108
+ fname = StringValueCStr(rb_fname);
109
+ mode = StringValueCStr(rb_mode);
110
+
111
+ //Open the local/remote file
112
+ if (strchr(mode, 'w') != NULL || bwIsBigWig(fname, NULL))
113
+ {
114
+ bw = bwOpen(fname, NULL, mode);
115
+ }
116
+ else
117
+ {
118
+ bw = bbOpen(fname, NULL);
119
+ }
120
+
121
+ if (!bw)
122
+ {
123
+ fprintf(stderr, "bw is NULL!\n");
124
+ goto error;
125
+ }
126
+
127
+ if (!mode || !strchr(mode, 'w'))
128
+ {
129
+ if (!bw->cl)
130
+ goto error;
131
+ }
132
+
133
+ //Set the data pointer
134
+ DATA_PTR(self) = bw;
135
+
136
+ rb_ivar_set(self, rb_intern("@last_tid"), INT2NUM(-1));
137
+ rb_ivar_set(self, rb_intern("@last_type"), INT2NUM(-1));
138
+ rb_ivar_set(self, rb_intern("@last_span"), INT2NUM(-1));
139
+ rb_ivar_set(self, rb_intern("@last_step"), INT2NUM(-1));
140
+ rb_ivar_set(self, rb_intern("@last_start"), INT2NUM(-1));
141
+
142
+ return self;
143
+
144
+ error:
145
+ if (bw)
146
+ bwClose(bw);
147
+ rb_raise(rb_eRuntimeError, "Received an error during file opening!");
148
+ return Qnil;
149
+ }
150
+
151
+ static VALUE
152
+ bigwig_close(VALUE self)
153
+ {
154
+ bigWigFile_t *bw = get_bigWigFile(self);
155
+
156
+ if (bw)
157
+ {
158
+ bwClose(bw);
159
+ DATA_PTR(self) = NULL;
160
+ }
161
+
162
+ return Qnil;
163
+ }
164
+
165
+ static VALUE
166
+ bw_get_header(VALUE self)
167
+ {
168
+ bigWigFile_t *bw = get_bigWigFile(self);
169
+ VALUE rb_header;
170
+
171
+ if (!bw)
172
+ {
173
+ rb_raise(rb_eRuntimeError, "The bigWig file handle is not opened!");
174
+ return Qnil;
175
+ }
176
+
177
+ if (bw->isWrite == 1)
178
+ {
179
+ rb_raise(rb_eRuntimeError, "The header cannot be accessed in files opened for writing!");
180
+ return Qnil;
181
+ }
182
+
183
+ rb_header = rb_hash_new();
184
+
185
+ // FIXME return int or double?
186
+ rb_hash_aset(rb_header, ID2SYM(rb_intern("version")), ULONG2NUM(bw->hdr->version));
187
+ rb_hash_aset(rb_header, ID2SYM(rb_intern("levels")), ULONG2NUM(bw->hdr->nLevels));
188
+ rb_hash_aset(rb_header, ID2SYM(rb_intern("bases_covered")), ULL2NUM(bw->hdr->nBasesCovered));
189
+ rb_hash_aset(rb_header, ID2SYM(rb_intern("min_val")), INT2NUM((int)bw->hdr->minVal));
190
+ rb_hash_aset(rb_header, ID2SYM(rb_intern("max_val")), INT2NUM((int)bw->hdr->maxVal));
191
+ rb_hash_aset(rb_header, ID2SYM(rb_intern("sum_data")), INT2NUM((int)bw->hdr->sumData));
192
+ rb_hash_aset(rb_header, ID2SYM(rb_intern("sum_squared")), INT2NUM((int)bw->hdr->sumSquared));
193
+
194
+ return rb_header;
195
+
196
+ error:
197
+ rb_raise(rb_eRuntimeError, "Received an error while getting the bigWig header!");
198
+ return Qnil;
199
+ }
200
+
201
+ static VALUE
202
+ bw_get_chroms(int argc, VALUE *argv, VALUE self)
203
+ {
204
+ bigWigFile_t *bw = get_bigWigFile(self);
205
+ VALUE rb_chrom, val, ret;
206
+ char *chrom = NULL;
207
+ uint32_t i;
208
+
209
+ ret = Qnil; // return nil if no chrom is found
210
+
211
+ if (!bw)
212
+ {
213
+ rb_raise(rb_eRuntimeError, "The bigWig file handle is not opened!");
214
+ return Qnil;
215
+ }
216
+
217
+ if (bw->isWrite == 1)
218
+ {
219
+ rb_raise(rb_eRuntimeError, "Chromosomes cannot be accessed in files opened for writing!");
220
+ return Qnil;
221
+ }
222
+
223
+ rb_scan_args(argc, argv, "01", &rb_chrom);
224
+
225
+ if (argc == 0)
226
+ {
227
+ ret = rb_hash_new();
228
+ for (i = 0; i < bw->cl->nKeys; i++)
229
+ {
230
+ val = ULONG2NUM(bw->cl->len[i]);
231
+ rb_hash_aset(ret, rb_str_new2(bw->cl->chrom[i]), val);
232
+ }
233
+ }
234
+ else
235
+ {
236
+ chrom = StringValueCStr(rb_chrom);
237
+ for (i = 0; i < bw->cl->nKeys; i++)
238
+ {
239
+ if (strcmp(bw->cl->chrom[i], chrom) == 0)
240
+ {
241
+ ret = ULONG2NUM(bw->cl->len[i]);
242
+ break;
243
+ }
244
+ }
245
+ }
246
+
247
+ return ret;
248
+ }
249
+
250
+ enum bwStatsType char2enum(char *s)
251
+ {
252
+ if (strcmp(s, "mean") == 0)
253
+ return mean;
254
+ if (strcmp(s, "std") == 0)
255
+ return stdev;
256
+ if (strcmp(s, "dev") == 0)
257
+ return dev;
258
+ if (strcmp(s, "max") == 0)
259
+ return max;
260
+ if (strcmp(s, "min") == 0)
261
+ return min;
262
+ if (strcmp(s, "cov") == 0)
263
+ return cov;
264
+ if (strcmp(s, "coverage") == 0)
265
+ return cov;
266
+ if (strcmp(s, "sum") == 0)
267
+ return sum;
268
+ return -1;
269
+ };
270
+
271
+ // double *bwStats (bigWigFile_t *fp, char *chrom, uint32_t start, uint32_t end, uint32_t nBins, enum bwStatsType type);
272
+ // double *bwStatsFromFull(bigWigFile_t *fp, char *chrom, uint32_t start, uint32_t end, uint32_t nBins, enum bwStatsType type);
273
+
274
+ static VALUE
275
+ bw_get_stats(VALUE self, VALUE rb_chrom, VALUE rb_start, VALUE rb_end, VALUE rb_nBins, VALUE rb_type, VALUE rb_exact)
276
+ {
277
+ bigWigFile_t *bw = get_bigWigFile(self);
278
+ double *val;
279
+ unsigned long startl = 0, endl = -1;
280
+ uint32_t start, end = -1, tid;
281
+ int nBins = 1, i;
282
+ char *chrom = NULL, *type = "mean";
283
+ VALUE ret;
284
+
285
+ if (!bw)
286
+ {
287
+ rb_raise(rb_eRuntimeError, "The bigWig file handle is not opened!");
288
+ return Qnil;
289
+ }
290
+
291
+ if (bw->isWrite == 1)
292
+ {
293
+ rb_raise(rb_eRuntimeError, "Statistics cannot be accessed in files opened for writing!");
294
+ return Qnil;
295
+ }
296
+
297
+ if (bw->type == 1)
298
+ {
299
+ rb_raise(rb_eRuntimeError, "bigBed files have no statistics!");
300
+ return Qnil;
301
+ }
302
+
303
+ if (rb_chrom != Qnil)
304
+ {
305
+ chrom = StringValueCStr(rb_chrom);
306
+ }
307
+
308
+ if (rb_start != Qnil)
309
+ startl = NUM2LONG(rb_start);
310
+
311
+ if (rb_end != Qnil)
312
+ endl = NUM2LONG(rb_end);
313
+
314
+ if (rb_nBins != Qnil)
315
+ nBins = NUM2INT(rb_nBins);
316
+
317
+ if (rb_type != Qnil)
318
+ type = StringValueCStr(rb_type);
319
+
320
+ if (rb_exact != Qnil)
321
+ {
322
+ if (RTEST(rb_exact) == 1)
323
+ endl = startl + nBins - 1;
324
+ }
325
+
326
+ tid = bwGetTid(bw, chrom);
327
+
328
+ if (endl == (unsigned long)-1 && tid != (uint32_t)-1)
329
+ endl = bw->cl->len[tid];
330
+
331
+ if (tid == (uint32_t)-1 || startl > end || endl > end)
332
+ {
333
+ rb_raise(rb_eRuntimeError, "Invalid interval bounds!");
334
+ return Qnil;
335
+ }
336
+
337
+ start = (uint32_t)startl;
338
+ end = (uint32_t)endl;
339
+
340
+ if (end <= start || end > bw->cl->len[tid] || start >= end)
341
+ {
342
+ rb_raise(rb_eRuntimeError, "Invalid interval bounds!");
343
+ return Qnil;
344
+ }
345
+
346
+ if (char2enum(type) == doesNotExist)
347
+ {
348
+ rb_raise(rb_eRuntimeError, "Invalid type! : %s", type);
349
+ return Qnil;
350
+ }
351
+
352
+ if (!hasEntries(bw))
353
+ {
354
+ ret = rb_ary_new2(nBins);
355
+ for (i = 0; i < nBins; i++)
356
+ {
357
+ rb_ary_store(ret, i, Qnil);
358
+ }
359
+ return ret;
360
+ }
361
+
362
+ if (RTEST(rb_exact))
363
+ {
364
+ val = bwStatsFromFull(bw, chrom, start, end, nBins, char2enum(type));
365
+ }
366
+ else
367
+ {
368
+ val = bwStats(bw, chrom, start, end, nBins, char2enum(type));
369
+ }
370
+
371
+ if (!val)
372
+ {
373
+ rb_raise(rb_eRuntimeError, "Error getting statistics!An error was encountered while fetching statistics.");
374
+ return Qnil;
375
+ }
376
+
377
+ ret = rb_ary_new2(nBins);
378
+ for (i = 0; i < nBins; i++)
379
+ {
380
+ rb_ary_store(ret, i, rb_float_new(val[i]));
381
+ }
382
+ free(val);
383
+
384
+ return ret;
385
+ }
386
+
387
+ static VALUE
388
+ bw_get_values(VALUE self, VALUE rb_chrom, VALUE rb_start, VALUE rb_end)
389
+ {
390
+ bigWigFile_t *bw = get_bigWigFile(self);
391
+ int i;
392
+ uint32_t start, end = -1, tid;
393
+ unsigned long startl = 0, endl = -1;
394
+ char *chrom = NULL;
395
+ VALUE ret;
396
+ bwOverlappingIntervals_t *o;
397
+
398
+ if (!bw)
399
+ {
400
+ rb_raise(rb_eRuntimeError, "The bigWig file handle is not opened!");
401
+ return Qnil;
402
+ }
403
+
404
+ if (bw->type == 1)
405
+ {
406
+ rb_raise(rb_eRuntimeError, "bigBed files have no values! Use 'entries' instead.");
407
+ return Qnil;
408
+ }
409
+
410
+ if (rb_chrom != Qnil)
411
+ {
412
+ chrom = StringValueCStr(rb_chrom);
413
+ }
414
+
415
+ if (rb_start != Qnil)
416
+ startl = NUM2LONG(rb_start);
417
+
418
+ if (rb_end != Qnil)
419
+ endl = NUM2LONG(rb_end);
420
+
421
+ tid = bwGetTid(bw, chrom);
422
+
423
+ if (endl == (unsigned long)-1 && tid != (uint32_t)-1)
424
+ endl = bw->cl->len[tid];
425
+ if (tid == (uint32_t)-1 || startl > end || endl > end)
426
+ {
427
+ rb_raise(rb_eRuntimeError, "Invalid interval bounds!");
428
+ return Qnil;
429
+ }
430
+
431
+ start = (uint32_t)startl;
432
+ end = (uint32_t)endl;
433
+
434
+ if (end <= start || end > bw->cl->len[tid] || start >= end)
435
+ {
436
+ rb_raise(rb_eRuntimeError, "Invalid interval bounds!");
437
+ return Qnil;
438
+ }
439
+
440
+ if (!hasEntries(bw))
441
+ {
442
+ return rb_ary_new2(0);
443
+ }
444
+
445
+ o = bwGetValues(bw, chrom, start, end, 1);
446
+ if (!o)
447
+ {
448
+ rb_raise(rb_eRuntimeError, "An error occurred while fetching values!");
449
+ return Qnil;
450
+ }
451
+
452
+ ret = rb_ary_new2(end - start);
453
+ for (i = 0; i < (int)o->l; i++)
454
+ rb_ary_store(ret, i, DBL2NUM(o->value[i]));
455
+ bwDestroyOverlappingIntervals(o);
456
+
457
+ return ret;
458
+ }
459
+
460
+ static VALUE
461
+ bw_get_intervals(VALUE self, VALUE rb_chrom, VALUE rb_start, VALUE rb_end)
462
+ {
463
+ bigWigFile_t *bw = get_bigWigFile(self);
464
+ uint32_t start, end = -1, tid, i;
465
+ unsigned long startl = 0, endl = -1;
466
+ bwOverlappingIntervals_t *intervals = NULL;
467
+ char *chrom;
468
+ VALUE ret;
469
+
470
+ if (!bw)
471
+ {
472
+ rb_raise(rb_eRuntimeError, "The bigWig file handle is not opened!");
473
+ return Qnil;
474
+ }
475
+
476
+ if (bw->isWrite == 1)
477
+ {
478
+ rb_raise(rb_eRuntimeError, "Intervals cannot be accessed in files opened for writing!");
479
+ return Qnil;
480
+ }
481
+
482
+ if (bw->type == 1)
483
+ {
484
+ rb_raise(rb_eRuntimeError, "bigBed files have no intervals! Use 'entries' instead.");
485
+ return Qnil;
486
+ }
487
+
488
+ if (rb_chrom != Qnil)
489
+ {
490
+ chrom = StringValueCStr(rb_chrom);
491
+ }
492
+
493
+ if (rb_start != Qnil)
494
+ startl = NUM2LONG(rb_start);
495
+
496
+ if (rb_end != Qnil)
497
+ endl = NUM2LONG(rb_end);
498
+
499
+ tid = bwGetTid(bw, chrom);
500
+
501
+ //Sanity check
502
+ if (endl == (unsigned long)-1 && tid != (uint32_t)-1)
503
+ endl = bw->cl->len[tid];
504
+
505
+ if (tid == (uint32_t)-1 || startl > end || endl > end)
506
+ {
507
+ rb_raise(rb_eRuntimeError, "Invalid interval bounds!");
508
+ return Qnil;
509
+ }
510
+
511
+ start = (uint32_t)startl;
512
+ end = (uint32_t)endl;
513
+
514
+ if (end <= start || end > bw->cl->len[tid] || start >= end)
515
+ {
516
+ rb_raise(rb_eRuntimeError, "Invalid interval bounds!");
517
+ return Qnil;
518
+ }
519
+
520
+ if (!hasEntries(bw))
521
+ {
522
+ return rb_ary_new2(0);
523
+ }
524
+
525
+ //Get the intervals
526
+ intervals = bwGetOverlappingIntervals(bw, chrom, start, end);
527
+ if (!intervals)
528
+ {
529
+ rb_raise(rb_eRuntimeError, "An error occurred while fetching the overlapping intervals!");
530
+ return Qnil;
531
+ }
532
+ if (!intervals->l)
533
+ {
534
+ return rb_ary_new2(0);
535
+ }
536
+
537
+ ret = rb_ary_new2(intervals->l);
538
+ for (i = 0; i < intervals->l; i++)
539
+ {
540
+ VALUE tupl = rb_ary_new3(3, UINT32_2NUM(intervals->start[i]), UINT32_2NUM(intervals->end[i]), DBL2NUM(intervals->value[i]));
541
+ rb_ary_store(ret, i, tupl);
542
+ }
543
+ bwDestroyOverlappingIntervals(intervals);
544
+
545
+ return ret;
546
+ }
547
+
548
+ static VALUE
549
+ bb_get_entries(VALUE self, VALUE rb_chrom, VALUE rb_start, VALUE rb_end, VALUE rb_with_string)
550
+ {
551
+ bigWigFile_t *bw = get_bigWigFile(self);
552
+ uint32_t start, end = -1, tid, i;
553
+ unsigned long startl, endl;
554
+ char *chrom;
555
+ VALUE ret, t;
556
+ int withString = 1;
557
+ bbOverlappingEntries_t *o;
558
+
559
+ if (!bw)
560
+ {
561
+ rb_raise(rb_eRuntimeError, "The bigBed file handle is not opened!");
562
+ return Qnil;
563
+ }
564
+
565
+ if (bw->type == 0)
566
+ {
567
+ rb_raise(rb_eRuntimeError, "bigWig files have no entries! Use 'values' or 'intervals' instead.");
568
+ return Qnil;
569
+ }
570
+
571
+ if (rb_chrom != Qnil)
572
+ {
573
+ chrom = StringValueCStr(rb_chrom);
574
+ }
575
+
576
+ if (rb_start != Qnil)
577
+ startl = NUM2LONG(rb_start);
578
+
579
+ if (rb_end != Qnil)
580
+ endl = NUM2LONG(rb_end);
581
+
582
+ if (rb_with_string != Qnil)
583
+ {
584
+ if (RTEST(rb_with_string))
585
+ withString = 1;
586
+ else
587
+ withString = 0;
588
+ }
589
+
590
+ tid = bwGetTid(bw, chrom);
591
+
592
+ //Sanity check
593
+ if (endl == (unsigned long)-1 && tid != (uint32_t)-1)
594
+ endl = bw->cl->len[tid];
595
+ if (tid == (uint32_t)-1 || startl > end || endl > end)
596
+ {
597
+ rb_raise(rb_eRuntimeError, "Invalid interval bounds!");
598
+ return Qnil;
599
+ }
600
+
601
+ start = (uint32_t)startl;
602
+ end = (uint32_t)endl;
603
+
604
+ if (end <= start || end > bw->cl->len[tid] || start >= end)
605
+ {
606
+ rb_raise(rb_eRuntimeError, "Invalid interval bounds!");
607
+ return Qnil;
608
+ }
609
+
610
+ o = bbGetOverlappingEntries(bw, chrom, start, end, withString);
611
+ if (!o)
612
+ {
613
+ rb_raise(rb_eRuntimeError, "An error occurred while fetching the overlapping entries!\n");
614
+ return Qnil;
615
+ }
616
+ if (!o->l)
617
+ {
618
+ return rb_ary_new2(0);
619
+ }
620
+
621
+ ret = rb_ary_new2(o->l);
622
+ if (!ret)
623
+ goto error;
624
+
625
+ for (i = 0; i < o->l; i++)
626
+ {
627
+ if (withString)
628
+ {
629
+ t = rb_ary_new3(3, UINT32_2NUM(o->start[i]), UINT32_2NUM(o->end[i]), rb_str_new2(o->str[i]));
630
+ }
631
+ else
632
+ {
633
+ t = rb_ary_new3(2, UINT32_2NUM(o->start[i]), UINT32_2NUM(o->end[i]));
634
+ }
635
+ if (!t)
636
+ goto error;
637
+ rb_ary_store(ret, i, t);
638
+ }
639
+
640
+ bbDestroyOverlappingEntries(o);
641
+ return ret;
642
+
643
+ error:
644
+ bbDestroyOverlappingEntries(o);
645
+ rb_raise(rb_eRuntimeError, "An error occurred while constructing the output!\n");
646
+ return Qnil;
647
+ }
648
+
649
+ static VALUE
650
+ bb_get_sql(VALUE self)
651
+ {
652
+ bigWigFile_t *bw = get_bigWigFile(self);
653
+ VALUE ret;
654
+ char *str;
655
+
656
+ if (!bw)
657
+ {
658
+ rb_raise(rb_eRuntimeError, "The bigBed file handle is not opened!");
659
+ return Qnil;
660
+ }
661
+
662
+ if (bw->type == 0)
663
+ {
664
+ rb_raise(rb_eRuntimeError, "bigWig files have no entries!");
665
+ return Qnil;
666
+ }
667
+
668
+ str = bbGetSQL(bw);
669
+ if (!str)
670
+ {
671
+ return Qnil;
672
+ }
673
+
674
+ ret = rb_str_new2(str);
675
+ if (str)
676
+ free(str);
677
+
678
+ return ret;
679
+ }
680
+
681
+ static VALUE
682
+ bw_get_file_type(VALUE self)
683
+ {
684
+ bigWigFile_t *bw = get_bigWigFile(self);
685
+
686
+ if (bw->type == 0)
687
+ {
688
+ return rb_str_new2("BigWig");
689
+ }
690
+ else if (bw->type == 1)
691
+ {
692
+ return rb_str_new2("BigBed");
693
+ }
694
+
695
+ return rb_str_new2("Unknown");
696
+ }
697
+
698
+ static VALUE
699
+ bw_is_bigwig_q(VALUE self)
700
+ {
701
+ bigWigFile_t *bw = get_bigWigFile(self);
702
+
703
+ if (bw->type == 0)
704
+ {
705
+ return Qtrue;
706
+ }
707
+ else
708
+ {
709
+ return Qfalse;
710
+ }
711
+ }
712
+
713
+ static VALUE
714
+ bw_is_bigbed_q(VALUE self)
715
+ {
716
+ bigWigFile_t *bw = get_bigWigFile(self);
717
+
718
+ if (bw->type == 1)
719
+ {
720
+ return Qtrue;
721
+ }
722
+ else
723
+ {
724
+ return Qfalse;
725
+ }
726
+ }
727
+
728
+ void Init_bigwigext()
729
+ {
730
+ rb_Bio = rb_define_module("Bio");
731
+ rb_BigWig = rb_define_class_under(rb_Bio, "BigWig", rb_cObject);
732
+
733
+ rb_define_alloc_func(rb_BigWig, bigwig_allocate);
734
+
735
+ rb_define_private_method(rb_BigWig, "initialize_raw", bigwig_init, 2);
736
+ rb_define_method(rb_BigWig, "close", bigwig_close, 0);
737
+ rb_define_method(rb_BigWig, "header", bw_get_header, 0);
738
+ rb_define_method(rb_BigWig, "chroms", bw_get_chroms, -1);
739
+ rb_define_private_method(rb_BigWig, "stats_raw", bw_get_stats, 6);
740
+ rb_define_private_method(rb_BigWig, "values_raw", bw_get_values, 3);
741
+ rb_define_private_method(rb_BigWig, "intervals_raw", bw_get_intervals, 3);
742
+ rb_define_private_method(rb_BigWig, "entries_raw", bb_get_entries, 4);
743
+ rb_define_method(rb_BigWig, "sql", bb_get_sql, 0);
744
+ rb_define_method(rb_BigWig, "file_type", bw_get_file_type, 0);
745
+ rb_define_method(rb_BigWig, "is_bigwig?", bw_is_bigwig_q, 0);
746
+ rb_define_method(rb_BigWig, "is_bigbed?", bw_is_bigbed_q, 0);
747
+ }