1 #include <Python.h>
2 #include <inttypes.h>
3 #include "pyBigWig.h"
4
5 #ifdef WITHNUMPY
6 #include <float.h>
7 #include "numpy/npy_common.h"
8 #include "numpy/halffloat.h"
9 #include "numpy/ndarrayobject.h"
10 #include "numpy/arrayscalars.h"
11
12 int lsize = NPY_SIZEOF_LONG;
13
14 //Raises an exception on error, which should be checked
getNumpyU32(PyArrayObject * obj,Py_ssize_t i)15 uint32_t getNumpyU32(PyArrayObject *obj, Py_ssize_t i) {
16 int dtype;
17 char *p;
18 uint32_t o = 0;
19 npy_intp stride;
20
21 //Get the dtype
22 dtype = PyArray_TYPE(obj);
23 //Get the stride
24 stride = PyArray_STRIDE(obj, 0);
25 p = PyArray_BYTES(obj) + i*stride;
26
27 switch(dtype) {
28 case NPY_INT8:
29 if(((int8_t *) p)[0] < 0) {
30 PyErr_SetString(PyExc_RuntimeError, "Received an integer < 0!\n");
31 goto error;
32 }
33 o += ((int8_t *) p)[0];
34 break;
35 case NPY_INT16:
36 if(((int16_t *) p)[0] < 0) {
37 PyErr_SetString(PyExc_RuntimeError, "Received an integer < 0!\n");
38 goto error;
39 }
40 o += ((int16_t *) p)[0];
41 break;
42 case NPY_INT32:
43 if(((int32_t *) p)[0] < 0) {
44 PyErr_SetString(PyExc_RuntimeError, "Received an integer < 0!\n");
45 goto error;
46 }
47 o += ((int32_t *) p)[0];
48 break;
49 case NPY_INT64:
50 if(((int64_t *) p)[0] < 0) {
51 PyErr_SetString(PyExc_RuntimeError, "Received an integer < 0!\n");
52 goto error;
53 }
54 o += ((int64_t *) p)[0];
55 break;
56 case NPY_UINT8:
57 o += ((uint8_t *) p)[0];
58 break;
59 case NPY_UINT16:
60 o += ((uint16_t *) p)[0];
61 break;
62 case NPY_UINT32:
63 o += ((uint32_t *) p)[0];
64 break;
65 case NPY_UINT64:
66 if(((uint64_t *) p)[0] > (uint32_t) -1) {
67 PyErr_SetString(PyExc_RuntimeError, "Received an integer larger than possible for a 32bit unsigned integer!\n");
68 goto error;
69 }
70 o += ((uint64_t *) p)[0];
71 break;
72 default:
73 PyErr_SetString(PyExc_RuntimeError, "Received unknown data type for conversion to uint32_t!\n");
74 goto error;
75 break;
76 }
77 return o;
78
79 error:
80 return 0;
81 };
82
getNumpyL(PyObject * obj)83 long getNumpyL(PyObject *obj) {
84 short s;
85 int i;
86 long l;
87 long long ll;
88 unsigned short us;
89 unsigned int ui;
90 unsigned long ul;
91 unsigned long long ull;
92
93 if(!PyArray_IsIntegerScalar(obj)) {
94 PyErr_SetString(PyExc_RuntimeError, "Received non-Integer scalar type for conversion to long!\n");
95 return 0;
96 }
97
98 if(PyArray_IsScalar(obj, Short)) {
99 s = ((PyShortScalarObject *)obj)->obval;
100 l = s;
101 } else if(PyArray_IsScalar(obj, Int)) {
102 i = ((PyLongScalarObject *)obj)->obval;
103 l = i;
104 } else if(PyArray_IsScalar(obj, Long)) {
105 l = ((PyLongScalarObject *)obj)->obval;
106 } else if(PyArray_IsScalar(obj, LongLong)) {
107 ll = ((PyLongScalarObject *)obj)->obval;
108 l = ll;
109 } else if(PyArray_IsScalar(obj, UShort)) {
110 us = ((PyLongScalarObject *)obj)->obval;
111 l = us;
112 } else if(PyArray_IsScalar(obj, UInt)) {
113 ui = ((PyLongScalarObject *)obj)->obval;
114 l = ui;
115 } else if(PyArray_IsScalar(obj, ULong)) {
116 ul = ((PyLongScalarObject *)obj)->obval;
117 l = ul;
118 } else if(PyArray_IsScalar(obj, ULongLong)) {
119 ull = ((PyLongScalarObject *)obj)->obval;
120 l = ull;
121 } else {
122 PyErr_SetString(PyExc_RuntimeError, "Received unknown scalar type for conversion to long!\n");
123 return 0;
124 }
125
126 return l;
127 }
128
129 //Raises an exception on error, which should be checked
getNumpyF(PyArrayObject * obj,Py_ssize_t i)130 float getNumpyF(PyArrayObject *obj, Py_ssize_t i) {
131 int dtype;
132 char *p;
133 float o = 0.0;
134 npy_intp stride;
135
136 //Get the dtype
137 dtype = PyArray_TYPE(obj);
138 //Get the stride
139 stride = PyArray_STRIDE(obj, 0);
140 p = PyArray_BYTES(obj) + i*stride;
141
142 switch(dtype) {
143 case NPY_FLOAT16:
144 return npy_half_to_float(((npy_half*)p)[0]);
145 case NPY_FLOAT32:
146 return ((float*)p)[0];
147 case NPY_FLOAT64:
148 if(((double*)p)[0] > FLT_MAX) {
149 PyErr_SetString(PyExc_RuntimeError, "Received a floating point value greater than possible for a 32-bit float!\n");
150 goto error;
151 }
152 if(((double*)p)[0] < -FLT_MAX) {
153 PyErr_SetString(PyExc_RuntimeError, "Received a floating point value less than possible for a 32-bit float!\n");
154 goto error;
155 }
156 o += ((double*)p)[0];
157 return o;
158 default:
159 PyErr_SetString(PyExc_RuntimeError, "Received unknown data type for conversion to float!\n");
160 goto error;
161 break;
162 }
163 return o;
164
165 error:
166 return 0;
167 }
168
169 //The calling function needs to free the result
getNumpyStr(PyArrayObject * obj,Py_ssize_t i)170 char *getNumpyStr(PyArrayObject *obj, Py_ssize_t i) {
171 char *p , *o = NULL;
172 npy_intp stride, j;
173 int dtype;
174
175 //Get the dtype
176 dtype = PyArray_TYPE(obj);
177 //Get the stride
178 stride = PyArray_STRIDE(obj, 0);
179 p = PyArray_BYTES(obj) + i*stride;
180
181 switch(dtype) {
182 case NPY_STRING:
183 o = calloc(1, stride + 1);
184 strncpy(o, p, stride);
185 return o;
186 case NPY_UNICODE:
187 o = calloc(1, stride/4 + 1);
188 for(j=0; j<stride/4; j++) o[j] = (char) ((uint32_t*)p)[j];
189 return o;
190 default:
191 PyErr_SetString(PyExc_RuntimeError, "Received unknown data type!\n");
192 break;
193 }
194 return NULL;
195 }
196 #endif
197
198 //Return 1 if there are any entries at all
hasEntries(bigWigFile_t * bw)199 int hasEntries(bigWigFile_t *bw) {
200 if(bw->hdr->indexOffset != 0) return 1; // No index, no entries pyBigWig issue #111
201 //if(bw->hdr->nBasesCovered > 0) return 1; // Sometimes headers are broken
202 return 0;
203 }
204
pyBwEnter(pyBigWigFile_t * self,PyObject * args)205 PyObject* pyBwEnter(pyBigWigFile_t*self, PyObject *args) {
206 bigWigFile_t *bw = self->bw;
207
208 if(!bw) {
209 PyErr_SetString(PyExc_RuntimeError, "The bigWig file handle is not opened!");
210 return NULL;
211 }
212
213 Py_INCREF(self);
214
215 return (PyObject*) self;
216 }
217
pyBwOpen(PyObject * self,PyObject * pyFname)218 PyObject* pyBwOpen(PyObject *self, PyObject *pyFname) {
219 char *fname = NULL;
220 char *mode = "r";
221 pyBigWigFile_t *pybw;
222 bigWigFile_t *bw = NULL;
223
224 if(!PyArg_ParseTuple(pyFname, "s|s", &fname, &mode)) goto error;
225
226 //Open the local/remote file
227 if(strchr(mode, 'w') != NULL || bwIsBigWig(fname, NULL)) {
228 bw = bwOpen(fname, NULL, mode);
229 } else {
230 bw = bbOpen(fname, NULL);
231 }
232 if(!bw) {
233 fprintf(stderr, "[pyBwOpen] bw is NULL!\n");
234 goto error;
235 }
236 if(!mode || !strchr(mode, 'w')) {
237 if(!bw->cl) goto error;
238 }
239
240 pybw = PyObject_New(pyBigWigFile_t, &bigWigFile);
241 if(!pybw) {
242 fprintf(stderr, "[pyBwOpen] PyObject_New() returned NULL (out of memory?)!\n");
243 goto error;
244 }
245 pybw->bw = bw;
246 pybw->lastTid = -1;
247 pybw->lastType = -1;
248 pybw->lastSpan = (uint32_t) -1;
249 pybw->lastStep = (uint32_t) -1;
250 pybw->lastStart = (uint32_t) -1;
251 return (PyObject*) pybw;
252
253 error:
254 if(bw) bwClose(bw);
255 PyErr_SetString(PyExc_RuntimeError, "Received an error during file opening!");
256 return NULL;
257 }
258
pyBwDealloc(pyBigWigFile_t * self)259 static void pyBwDealloc(pyBigWigFile_t *self) {
260 if(self->bw) bwClose(self->bw);
261 PyObject_DEL(self);
262 }
263
pyBwClose(pyBigWigFile_t * self,PyObject * args)264 static PyObject *pyBwClose(pyBigWigFile_t *self, PyObject *args) {
265 bwClose(self->bw);
266 self->bw = NULL;
267 Py_INCREF(Py_None);
268 return Py_None;
269 }
270
271 //Accessor for the header (version, nLevels, nBasesCovered, minVal, maxVal, sumData, sumSquared
pyBwGetHeader(pyBigWigFile_t * self,PyObject * args)272 static PyObject *pyBwGetHeader(pyBigWigFile_t *self, PyObject *args) {
273 bigWigFile_t *bw = self->bw;
274 PyObject *ret, *val;
275
276 if(!bw) {
277 PyErr_SetString(PyExc_RuntimeError, "The bigWig file handle is not opened!");
278 return NULL;
279 }
280 if(bw->isWrite == 1) {
281 PyErr_SetString(PyExc_RuntimeError, "The header cannot be accessed in files opened for writing!");
282 return NULL;
283 }
284
285 ret = PyDict_New();
286 val = PyLong_FromUnsignedLong(bw->hdr->version);
287 if(PyDict_SetItemString(ret, "version", val) == -1) goto error;
288 Py_DECREF(val);
289 val = PyLong_FromUnsignedLong(bw->hdr->nLevels);
290 if(PyDict_SetItemString(ret, "nLevels", val) == -1) goto error;
291 Py_DECREF(val);
292 val = PyLong_FromUnsignedLongLong(bw->hdr->nBasesCovered);
293 if(PyDict_SetItemString(ret, "nBasesCovered", val) == -1) goto error;
294 Py_DECREF(val);
295 val = PyLong_FromDouble(bw->hdr->minVal);
296 if(PyDict_SetItemString(ret, "minVal", val) == -1) goto error;
297 Py_DECREF(val);
298 val = PyLong_FromDouble(bw->hdr->maxVal);
299 if(PyDict_SetItemString(ret, "maxVal", val) == -1) goto error;
300 Py_DECREF(val);
301 val = PyLong_FromDouble(bw->hdr->sumData);
302 if(PyDict_SetItemString(ret, "sumData", val) == -1) goto error;
303 Py_DECREF(val);
304 val = PyLong_FromDouble(bw->hdr->sumSquared);
305 if(PyDict_SetItemString(ret, "sumSquared", val) == -1) goto error;
306 Py_DECREF(val);
307
308 return ret;
309
310 error :
311 Py_XDECREF(val);
312 Py_XDECREF(ret);
313 PyErr_SetString(PyExc_RuntimeError, "Received an error while getting the bigWig header!");
314 return NULL;
315 }
316
317 //Accessor for the chroms, args is optional
pyBwGetChroms(pyBigWigFile_t * self,PyObject * args)318 static PyObject *pyBwGetChroms(pyBigWigFile_t *self, PyObject *args) {
319 PyObject *ret = NULL, *val;
320 bigWigFile_t *bw = self->bw;
321 char *chrom = NULL;
322 uint32_t i;
323
324 if(!bw) {
325 PyErr_SetString(PyExc_RuntimeError, "The bigWig file handle is not opened!");
326 return NULL;
327 }
328
329 if(bw->isWrite == 1) {
330 PyErr_SetString(PyExc_RuntimeError, "Chromosomes cannot be accessed in files opened for writing!");
331 return NULL;
332 }
333
334 if(!(PyArg_ParseTuple(args, "|s", &chrom)) || !chrom) {
335 ret = PyDict_New();
336 for(i=0; i<bw->cl->nKeys; i++) {
337 val = PyLong_FromUnsignedLong(bw->cl->len[i]);
338 if(PyDict_SetItemString(ret, bw->cl->chrom[i], val) == -1) goto error;
339 Py_DECREF(val);
340 }
341 } else {
342 for(i=0; i<bw->cl->nKeys; i++) {
343 if(strcmp(bw->cl->chrom[i],chrom) == 0) {
344 ret = PyLong_FromUnsignedLong(bw->cl->len[i]);
345 break;
346 }
347 }
348 }
349
350 if(!ret) {
351 Py_INCREF(Py_None);
352 ret = Py_None;
353 }
354
355 return ret;
356
357 error :
358 Py_XDECREF(val);
359 Py_XDECREF(ret);
360 PyErr_SetString(PyExc_RuntimeError, "Received an error while adding an item to the output dictionary!");
361 return NULL;
362 }
363
char2enum(char * s)364 enum bwStatsType char2enum(char *s) {
365 if(strcmp(s, "mean") == 0) return mean;
366 if(strcmp(s, "std") == 0) return stdev;
367 if(strcmp(s, "dev") == 0) return dev;
368 if(strcmp(s, "max") == 0) return max;
369 if(strcmp(s, "min") == 0) return min;
370 if(strcmp(s, "cov") == 0) return cov;
371 if(strcmp(s, "coverage") == 0) return cov;
372 if(strcmp(s, "sum") == 0) return sum;
373 return -1;
374 };
375
376 //Fetch summary statistics, default is the mean of the entire chromosome.
pyBwGetStats(pyBigWigFile_t * self,PyObject * args,PyObject * kwds)377 static PyObject *pyBwGetStats(pyBigWigFile_t *self, PyObject *args, PyObject *kwds) {
378 bigWigFile_t *bw = self->bw;
379 double *val;
380 uint32_t start, end = -1, tid;
381 unsigned long startl = 0, endl = -1;
382 static char *kwd_list[] = {"chrom", "start", "end", "type", "nBins", "exact", "numpy", NULL};
383 char *chrom, *type = "mean";
384 PyObject *ret, *exact = Py_False, *starto = NULL, *endo = NULL;
385 PyObject *outputNumpy = Py_False;
386 int i, nBins = 1;
387 errno = 0; //In the off-chance that something elsewhere got an error and didn't clear it...
388
389 if(!bw) {
390 PyErr_SetString(PyExc_RuntimeError, "The bigWig file handle is not open!");
391 return NULL;
392 }
393
394 if(bw->isWrite == 1) {
395 PyErr_SetString(PyExc_RuntimeError, "Statistics cannot be accessed in files opened for writing!");
396 return NULL;
397 }
398
399 if(bw->type == 1) {
400 PyErr_SetString(PyExc_RuntimeError, "bigBed files have no statistics!");
401 return NULL;
402 }
403
404 if(!PyArg_ParseTupleAndKeywords(args, kwds, "s|OOsiOO", kwd_list, &chrom, &starto, &endo, &type, &nBins, &exact, &outputNumpy)) {
405 PyErr_SetString(PyExc_RuntimeError, "You must supply at least a chromosome!");
406 return NULL;
407 }
408
409 //Check inputs, reset to defaults if nothing was input
410 if(!nBins) nBins = 1; //For some reason, not specifying this overrides the default!
411 if(!type) type = "mean";
412 tid = bwGetTid(bw, chrom);
413
414 if(starto) {
415 #ifdef WITHNUMPY
416 if(PyArray_IsScalar(starto, Integer)) {
417 startl = (long) getNumpyL(starto);
418 } else
419 #endif
420 if(PyLong_Check(starto)) {
421 startl = PyLong_AsLong(starto);
422 #if PY_MAJOR_VERSION < 3
423 } else if(PyInt_Check(starto)) {
424 startl = PyInt_AsLong(starto);
425 #endif
426 } else {
427 PyErr_SetString(PyExc_RuntimeError, "The start coordinate must be a number!");
428 return NULL;
429 }
430 }
431
432 if(endo) {
433 #ifdef WITHNUMPY
434 if(PyArray_IsScalar(endo, Integer)) {
435 endl = (long) getNumpyL(endo);
436 } else
437 #endif
438 if(PyLong_Check(endo)) {
439 endl = PyLong_AsLong(endo);
440 #if PY_MAJOR_VERSION < 3
441 } else if(PyInt_Check(endo)) {
442 endl = PyInt_AsLong(endo);
443 #endif
444 } else {
445 PyErr_SetString(PyExc_RuntimeError, "The end coordinate must be a number!");
446 return NULL;
447 }
448 }
449
450 if(endl == (unsigned long) -1 && tid != (uint32_t) -1) endl = bw->cl->len[tid];
451 if(tid == (uint32_t) -1 || startl > end || endl > end) {
452 PyErr_SetString(PyExc_RuntimeError, "Invalid interval bounds!");
453 return NULL;
454 }
455 start = (uint32_t) startl;
456 end = (uint32_t) endl;
457 if(end <= start || end > bw->cl->len[tid] || start >= end) {
458 PyErr_SetString(PyExc_RuntimeError, "Invalid interval bounds!");
459 return NULL;
460 }
461
462 if(char2enum(type) == doesNotExist) {
463 PyErr_SetString(PyExc_RuntimeError, "Invalid type!");
464 return NULL;
465 }
466
467 //Return a list of None if there are no entries at all
468 if(!hasEntries(bw)) {
469 #ifdef WITHNUMPY
470 if(outputNumpy == Py_True) {
471 val = malloc(sizeof(double)*nBins);
472 for(i=0; i<nBins; i++) {
473 val[i] = NPY_NAN;
474 }
475 npy_intp len = nBins;
476 ret = PyArray_SimpleNewFromData(1, &len, NPY_FLOAT64, (void *) val);
477 //This will break if numpy ever stops using malloc!
478 PyArray_ENABLEFLAGS((PyArrayObject*) ret, NPY_ARRAY_OWNDATA);
479 } else {
480 #endif
481 ret = PyList_New(nBins);
482 for(i=0; i<nBins; i++) {
483 Py_INCREF(Py_None);
484 PyList_SetItem(ret, i, Py_None);
485 }
486 #ifdef WITHNUMPY
487 }
488 #endif
489 return ret;
490 }
491
492 //Get the actual statistics
493 if(exact == Py_True) {
494 val = bwStatsFromFull(bw, chrom, start, end, nBins, char2enum(type));
495 } else {
496 val = bwStats(bw, chrom, start, end, nBins, char2enum(type));
497 }
498
499 if(!val) {
500 PyErr_SetString(PyExc_RuntimeError, "An error was encountered while fetching statistics.");
501 return NULL;
502 }
503
504 #ifdef WITHNUMPY
505 if(outputNumpy == Py_True) {
506 npy_intp len = nBins;
507 ret = PyArray_SimpleNewFromData(1, &len, NPY_FLOAT64, (void *) val);
508 //This will break if numpy ever stops using malloc!
509 PyArray_ENABLEFLAGS((PyArrayObject*) ret, NPY_ARRAY_OWNDATA);
510 } else {
511 #endif
512 ret = PyList_New(nBins);
513 for(i=0; i<nBins; i++) {
514 if(isnan(val[i])) {
515 Py_INCREF(Py_None);
516 PyList_SetItem(ret, i, Py_None);
517 } else {
518 PyList_SetItem(ret, i, PyFloat_FromDouble(val[i]));
519 }
520 }
521 free(val);
522 #ifdef WITHNUMPY
523 }
524 #endif
525 return ret;
526 }
527
528 //Fetch a list of individual values
529 //For bases with no coverage, the value should be None
530 #ifdef WITHNUMPY
pyBwGetValues(pyBigWigFile_t * self,PyObject * args,PyObject * kwds)531 static PyObject *pyBwGetValues(pyBigWigFile_t *self, PyObject *args, PyObject *kwds) {
532 #else
533 static PyObject *pyBwGetValues(pyBigWigFile_t *self, PyObject *args) {
534 #endif
535 bigWigFile_t *bw = self->bw;
536 int i;
537 uint32_t start, end = -1, tid;
538 unsigned long startl, endl;
539 char *chrom;
540 PyObject *ret, *starto = NULL, *endo = NULL;
541 bwOverlappingIntervals_t *o;
542
543 if(!bw) {
544 PyErr_SetString(PyExc_RuntimeError, "The bigWig file handle is not open!");
545 return NULL;
546 }
547
548 if(bw->type == 1) {
549 PyErr_SetString(PyExc_RuntimeError, "bigBed files have no values! Use 'entries' instead.");
550 return NULL;
551 }
552
553 #ifdef WITHNUMPY
554 static char *kwd_list[] = {"chrom", "start", "end", "numpy", NULL};
555 PyObject *outputNumpy = Py_False;
556
557 if(!PyArg_ParseTupleAndKeywords(args, kwds, "sOO|O", kwd_list, &chrom, &starto, &endo, &outputNumpy)) {
558 #else
559 if(!PyArg_ParseTuple(args, "sOO", &chrom, &starto, &endo)) {
560 #endif
561 PyErr_SetString(PyExc_RuntimeError, "You must supply a chromosome, start and end position.\n");
562 return NULL;
563 }
564
565 tid = bwGetTid(bw, chrom);
566
567 #ifdef WITHNUMPY
568 if(PyArray_IsScalar(starto, Integer)) {
569 startl = (long) getNumpyL(starto);
570 } else
571 #endif
572 if(PyLong_Check(starto)) {
573 startl = PyLong_AsLong(starto);
574 #if PY_MAJOR_VERSION < 3
575 } else if(PyInt_Check(starto)) {
576 startl = PyInt_AsLong(starto);
577 #endif
578 } else {
579 PyErr_SetString(PyExc_RuntimeError, "The start coordinate must be a number!");
580 return NULL;
581 }
582
583 #ifdef WITHNUMPY
584 if(PyArray_IsScalar(endo, Integer)) {
585 endl = (long) getNumpyL(endo);
586 } else
587 #endif
588 if(PyLong_Check(endo)) {
589 endl = PyLong_AsLong(endo);
590 #if PY_MAJOR_VERSION < 3
591 } else if(PyInt_Check(endo)) {
592 endl = PyInt_AsLong(endo);
593 #endif
594 } else {
595 PyErr_SetString(PyExc_RuntimeError, "The end coordinate must be a number!");
596 return NULL;
597 }
598
599 if(endl == (unsigned long) -1 && tid != (uint32_t) -1) endl = bw->cl->len[tid];
600 if(tid == (uint32_t) -1 || startl > end || endl > end) {
601 PyErr_SetString(PyExc_RuntimeError, "Invalid interval bounds!");
602 return NULL;
603 }
604
605 start = (uint32_t) startl;
606 end = (uint32_t) endl;
607 if(end <= start || end > bw->cl->len[tid] || start >= end) {
608 PyErr_SetString(PyExc_RuntimeError, "Invalid interval bounds!");
609 return NULL;
610 }
611
612 if(!hasEntries(self->bw)) {
613 #ifdef WITHNUMPY
614 if(outputNumpy == Py_True) {
615 return PyArray_SimpleNew(0, NULL, NPY_FLOAT);
616 } else {
617 #endif
618 return PyList_New(0);
619 #ifdef WITHNUMPY
620 }
621 #endif
622 }
623
624 o = bwGetValues(self->bw, chrom, start, end, 1);
625 if(!o) {
626 PyErr_SetString(PyExc_RuntimeError, "An error occurred while fetching values!");
627 return NULL;
628 }
629
630 #ifdef WITHNUMPY
631 if(outputNumpy == Py_True) {
632 npy_intp len = end - start;
633 ret = PyArray_SimpleNewFromData(1, &len, NPY_FLOAT, (void *) o->value);
634 //This will break if numpy ever stops using malloc!
635 PyArray_ENABLEFLAGS((PyArrayObject*) ret, NPY_ARRAY_OWNDATA);
636 free(o->start);
637 free(o->end);
638 free(o);
639 } else {
640 #endif
641 ret = PyList_New(end-start);
642 for(i=0; i<(int) o->l; i++) PyList_SetItem(ret, i, PyFloat_FromDouble(o->value[i]));
643 bwDestroyOverlappingIntervals(o);
644 #ifdef WITHNUMPY
645 }
646 #endif
647
648 return ret;
649 }
650
651 static PyObject *pyBwGetIntervals(pyBigWigFile_t *self, PyObject *args, PyObject *kwds) {
652 bigWigFile_t *bw = self->bw;
653 uint32_t start, end = -1, tid, i;
654 unsigned long startl = 0, endl = -1;
655 static char *kwd_list[] = {"chrom", "start", "end", NULL};
656 bwOverlappingIntervals_t *intervals = NULL;
657 char *chrom;
658 PyObject *ret, *starto = NULL, *endo = NULL;
659
660 if(!bw) {
661 PyErr_SetString(PyExc_RuntimeError, "The bigWig file handle is not opened!");
662 return NULL;
663 }
664
665 if(bw->isWrite == 1) {
666 PyErr_SetString(PyExc_RuntimeError, "Intervals cannot be accessed in files opened for writing!");
667 return NULL;
668 }
669
670 if(bw->type == 1) {
671 PyErr_SetString(PyExc_RuntimeError, "bigBed files have no intervals! Use 'entries()' instead.");
672 return NULL;
673 }
674
675 if(!PyArg_ParseTupleAndKeywords(args, kwds, "s|OO", kwd_list, &chrom, &starto, &endo)) {
676 PyErr_SetString(PyExc_RuntimeError, "You must supply at least a chromosome.\n");
677 return NULL;
678 }
679
680 //Sanity check
681 tid = bwGetTid(bw, chrom);
682 if(endl == (unsigned long) -1 && tid != (uint32_t) -1) endl = bw->cl->len[tid];
683 if(tid == (uint32_t) -1 || startl > end || endl > end) {
684 PyErr_SetString(PyExc_RuntimeError, "Invalid interval bounds!");
685 return NULL;
686 }
687
688 if(starto) {
689 #ifdef WITHNUMPY
690 if(PyArray_IsScalar(starto, Integer)) {
691 startl = (long) getNumpyL(starto);
692 } else
693 #endif
694 if(PyLong_Check(starto)) {
695 startl = PyLong_AsLong(starto);
696 #if PY_MAJOR_VERSION < 3
697 } else if(PyInt_Check(starto)) {
698 startl = PyInt_AsLong(starto);
699 #endif
700 } else {
701 PyErr_SetString(PyExc_RuntimeError, "The start coordinate must be a number!");
702 return NULL;
703 }
704 }
705
706 if(endo) {
707 #ifdef WITHNUMPY
708 if(PyArray_IsScalar(endo, Integer)) {
709 endl = (long) getNumpyL(endo);
710 } else
711 #endif
712 if(PyLong_Check(endo)) {
713 endl = PyLong_AsLong(endo);
714 #if PY_MAJOR_VERSION < 3
715 } else if(PyInt_Check(endo)) {
716 endl = PyInt_AsLong(endo);
717 #endif
718 } else {
719 PyErr_SetString(PyExc_RuntimeError, "The end coordinate must be a number!");
720 return NULL;
721 }
722 }
723
724 start = (uint32_t) startl;
725 end = (uint32_t) endl;
726 if(end <= start || end > bw->cl->len[tid] || start >= end) {
727 PyErr_SetString(PyExc_RuntimeError, "Invalid interval bounds!");
728 return NULL;
729 }
730
731 //Check for empty files
732 if(!hasEntries(bw)) {
733 Py_INCREF(Py_None);
734 return Py_None;
735 }
736
737 //Get the intervals
738 intervals = bwGetOverlappingIntervals(bw, chrom, start, end);
739 if(!intervals) {
740 PyErr_SetString(PyExc_RuntimeError, "An error occurred while fetching the overlapping intervals!");
741 return NULL;
742 }
743 if(!intervals->l) {
744 Py_INCREF(Py_None);
745 return Py_None;
746 }
747
748 ret = PyTuple_New(intervals->l);
749 for(i=0; i<intervals->l; i++) {
750 if(PyTuple_SetItem(ret, i, Py_BuildValue("(iif)", intervals->start[i], intervals->end[i], intervals->value[i]))) {
751 Py_DECREF(ret);
752 bwDestroyOverlappingIntervals(intervals);
753 PyErr_SetString(PyExc_RuntimeError, "An error occurred while constructing the output tuple!");
754 return NULL;
755 }
756 }
757
758 bwDestroyOverlappingIntervals(intervals);
759 return ret;
760 }
761
762 #if PY_MAJOR_VERSION >= 3
763 //Return 1 iff obj is a ready unicode type
764 int PyString_Check(PyObject *obj) {
765 if(PyUnicode_Check(obj)) {
766 return PyUnicode_READY(obj)+1;
767 }
768 return 0;
769 }
770
771 //I don't know what happens if PyBytes_AsString(NULL) is used...
772 char *PyString_AsString(PyObject *obj) {
773 return PyUnicode_AsUTF8(obj);
774 }
775 #endif
776
777 //Will return 1 for long or int types currently
778 int isNumeric(PyObject *obj) {
779 #ifdef WITHNUMPY
780 if(PyArray_IsScalar(obj, Integer)) return 1;
781 #endif
782 #if PY_MAJOR_VERSION < 3
783 if(PyInt_Check(obj)) return 1;
784 #endif
785 return PyLong_Check(obj);
786 }
787
788 //On error, throws a runtime error, so use PyErr_Occurred() after this
789 uint32_t Numeric2Uint(PyObject *obj) {
790 long l;
791 #if PY_MAJOR_VERSION < 3
792 if(PyInt_Check(obj)) {
793 return (uint32_t) PyInt_AsLong(obj);
794 }
795 #endif
796 l = PyLong_AsLong(obj);
797 //Check bounds
798 if(l > 0xFFFFFFFF) {
799 PyErr_SetString(PyExc_RuntimeError, "Length out of bounds for a bigWig file!");
800 return (uint32_t) -1;
801 }
802 return (uint32_t) l;
803 }
804
805 //This runs bwCreateHdr, bwCreateChromList, and bwWriteHdr
806 PyObject *pyBwAddHeader(pyBigWigFile_t *self, PyObject *args, PyObject *kwds) {
807 bigWigFile_t *bw = self->bw;
808 char **chroms = NULL;
809 int64_t n;
810 uint32_t *lengths = NULL, len;
811 int32_t maxZooms = 10;
812 long zoomTmp = 10;
813 static char *kwd_list[] = {"cl", "maxZooms", NULL};
814 PyObject *InputTuple = NULL, *tmpObject, *tmpObject2;
815 Py_ssize_t i, pyLen;
816
817 if(!bw) {
818 PyErr_SetString(PyExc_RuntimeError, "The bigWig file handle is not open!");
819 return NULL;
820 }
821
822 if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|k", kwd_list, &InputTuple, &zoomTmp)) {
823 PyErr_SetString(PyExc_RuntimeError, "Illegal arguments");
824 return NULL;
825 }
826 maxZooms = zoomTmp;
827
828 //Ensure that we received a list
829 if(!PyList_Check(InputTuple)) {
830 PyErr_SetString(PyExc_RuntimeError, "You MUST input a list of tuples (e.g., [('chr1', 1000), ('chr2', 2000)]!");
831 goto error;
832 }
833 pyLen = PyList_Size(InputTuple);
834 if(pyLen < 1) {
835 PyErr_SetString(PyExc_RuntimeError, "You input an empty list!");
836 goto error;
837 }
838 n = pyLen;
839
840 lengths = calloc(n, sizeof(uint32_t));
841 chroms = calloc(n, sizeof(char*));
842 if(!lengths || !chroms) {
843 PyErr_SetString(PyExc_RuntimeError, "Couldn't allocate lengths or chroms!");
844 goto error;
845 }
846
847 //Convert the tuple into something more useful in C
848 for(i=0; i<pyLen; i++) {
849 tmpObject = PyList_GetItem(InputTuple, i);
850 if(!tmpObject) {
851 PyErr_SetString(PyExc_RuntimeError, "Couldn't get a tuple!");
852 goto error;
853 }
854 if(!PyTuple_Check(tmpObject)) {
855 PyErr_SetString(PyExc_RuntimeError, "The input list is not made up of tuples!");
856 goto error;
857 }
858 if(PyTuple_Size(tmpObject) != 2) {
859 PyErr_SetString(PyExc_RuntimeError, "One tuple does not contain exactly 2 members!");
860 goto error;
861 }
862
863 //Chromosome
864 tmpObject2 = PyTuple_GetItem(tmpObject, 0); //This returns NULL in python3?!?
865 if(!PyString_Check(tmpObject2)) {
866 PyErr_SetString(PyExc_RuntimeError, "The first element of each tuple MUST be a string!");
867 goto error;
868 }
869 chroms[i] = PyString_AsString(tmpObject2);
870 if(!chroms[i]) {
871 PyErr_SetString(PyExc_RuntimeError, "Received something other than a string for a chromosome name!");
872 goto error;
873 }
874
875 //Length
876 tmpObject2 = PyTuple_GetItem(tmpObject, 1);
877 if(!isNumeric(tmpObject2)) {
878 PyErr_SetString(PyExc_RuntimeError, "The second element of each tuple MUST be an integer!");
879 goto error;
880 }
881 len = Numeric2Uint(tmpObject2);
882 if(PyErr_Occurred()) goto error;
883 if(zoomTmp > 0xFFFFFFFF) {
884 PyErr_SetString(PyExc_RuntimeError, "A requested length is longer than what can be stored in a bigWig file!");
885 goto error;
886 }
887 lengths[i] = len;
888 }
889
890 //Create the header
891 if(bwCreateHdr(bw, maxZooms)) {
892 PyErr_SetString(PyExc_RuntimeError, "Received an error in bwCreateHdr");
893 goto error;
894 }
895
896 //Create the chromosome list
897 bw->cl = bwCreateChromList(chroms, lengths, n);
898 if(!bw->cl) {
899 PyErr_SetString(PyExc_RuntimeError, "Received an error in bwCreateChromList");
900 goto error;
901 }
902
903 //Write the header
904 if(bwWriteHdr(bw)) {
905 PyErr_SetString(PyExc_RuntimeError, "Received an error while writing the bigWig header");
906 goto error;
907 }
908
909 if(lengths) free(lengths);
910 if(chroms) free(chroms);
911
912 Py_INCREF(Py_None);
913 return Py_None;
914
915 error:
916 if(lengths) free(lengths);
917 if(chroms) free(chroms);
918 return NULL;
919 }
920
921 //1 on true, 0 on false
922 int isType0(PyObject *chroms, PyObject *starts, PyObject *ends, PyObject *values) {
923 int rv = 0;
924 Py_ssize_t i, sz = 0;
925 PyObject *tmp;
926
927 if(!PyList_Check(chroms)
928 #ifdef WITHNUMPY
929 && !PyArray_Check(chroms)
930 #endif
931 ) return rv;
932 if(!PyList_Check(starts)
933 #ifdef WITHNUMPY
934 && !PyArray_Check(starts)
935 #endif
936 ) return rv;
937 if(!PyList_Check(ends)
938 #ifdef WITHNUMPY
939 && !PyArray_Check(ends)
940 #endif
941 ) return rv;
942 if(!PyList_Check(values)
943 #ifdef WITHNUMPY
944 && !PyArray_Check(values)
945 #endif
946 ) return rv;
947 if(PyList_Check(chroms)) sz = PyList_Size(chroms);
948 #ifdef WITHNUMPY
949 if(PyArray_Check(chroms)) sz += PyArray_Size(chroms);
950 #endif
951
952 if(PyList_Check(starts)) {
953 if(sz != PyList_Size(starts)) return rv;
954 #ifdef WITHNUMPY
955 } else {
956 if(sz != PyArray_Size(starts)) return rv;
957 #endif
958 }
959 if(PyList_Check(ends)) {
960 if(sz != PyList_Size(ends)) return rv;
961 #ifdef WITHNUMPY
962 } else {
963 if(sz != PyArray_Size(ends)) return rv;
964 #endif
965 }
966 if(PyList_Check(values)) {
967 if(sz != PyList_Size(values)) return rv;
968 #ifdef WITHNUMPY
969 } else {
970 if(sz != PyArray_Size(values)) return rv;
971 #endif
972 }
973
974 //Ensure chroms contains strings, etc.
975 if(PyList_Check(chroms)) {
976 for(i=0; i<sz; i++) {
977 tmp = PyList_GetItem(chroms, i);
978 if(!PyString_Check(tmp)) return rv;
979 }
980 #ifdef WITHNUMPY
981 } else {
982 if(!PyArray_ISSTRING( (PyArrayObject*) chroms)) return rv;
983 #endif
984 }
985 if(PyList_Check(starts)) {
986 for(i=0; i<sz; i++) {
987 tmp = PyList_GetItem(starts, i);
988 if(!isNumeric(tmp)) return rv;
989 }
990 #ifdef WITHNUMPY
991 } else {
992 if(!PyArray_ISINTEGER( (PyArrayObject*) starts)) return rv;
993 #endif
994 }
995 if(PyList_Check(ends)) {
996 for(i=0; i<sz; i++) {
997 tmp = PyList_GetItem(ends, i);
998 if(!isNumeric(tmp)) return rv;
999 }
1000 #ifdef WITHNUMPY
1001 } else {
1002 if(!PyArray_ISINTEGER( (PyArrayObject*) ends)) return rv;
1003 #endif
1004 }
1005 if(PyList_Check(values)) {
1006 for(i=0; i<sz; i++) {
1007 tmp = PyList_GetItem(values, i);
1008 if(!PyFloat_Check(tmp)) return rv;
1009 }
1010 #ifdef WITHNUMPY
1011 } else {
1012 if(!PyArray_ISFLOAT((PyArrayObject*) values)) return rv;
1013 #endif
1014 }
1015 return 1;
1016 }
1017
1018 //single chrom, multiple starts, single span
1019 int isType1(PyObject *chroms, PyObject *starts, PyObject *values, PyObject *span) {
1020 int rv = 0;
1021 Py_ssize_t i, sz = 0;
1022 PyObject *tmp;
1023
1024 if(!PyString_Check(chroms)) return rv;
1025 if(!PyList_Check(starts)
1026 #ifdef WITHNUMPY
1027 && !PyArray_Check(starts)
1028 #endif
1029 ) return rv;
1030 if(!PyList_Check(values)
1031 #ifdef WITHNUMPY
1032 && !PyArray_Check(values)
1033 #endif
1034 ) return rv;
1035 if(!isNumeric(span)) return rv;
1036
1037 if(PyList_Check(starts)) sz = PyList_Size(starts);
1038 #ifdef WITHNUMPY
1039 if(PyArray_Check(starts)) sz += PyArray_Size(starts);
1040 #endif
1041
1042 if(PyList_Check(values)) if(sz != PyList_Size(values)) return rv;
1043 #ifdef WITHNUMPY
1044 if(PyArray_Check(values)) if(sz != PyArray_Size(values)) return rv;
1045 #endif
1046
1047 if(PyList_Check(starts)) {
1048 for(i=0; i<sz; i++) {
1049 tmp = PyList_GetItem(starts, i);
1050 if(!isNumeric(tmp)) return rv;
1051 }
1052 #ifdef WITHNUMPY
1053 } else {
1054 if(!PyArray_ISINTEGER( (PyArrayObject*) starts)) return rv;
1055 #endif
1056 }
1057 if(PyList_Check(values)) {
1058 for(i=0; i<sz; i++) {
1059 tmp = PyList_GetItem(values, i);
1060 if(!PyFloat_Check(tmp)) return rv;
1061 }
1062 #ifdef WITHNUMPY
1063 } else {
1064 if(!PyArray_ISFLOAT( (PyArrayObject*) values)) return rv;
1065 #endif
1066 }
1067 return 1;
1068 }
1069
1070 //Single chrom, single start, single span, single step, multiple values
1071 int isType2(PyObject *chroms, PyObject *starts, PyObject *values, PyObject *span, PyObject *step) {
1072 int rv = 0;
1073 Py_ssize_t i, sz;
1074 PyObject *tmp;
1075
1076 if(!isNumeric(span)) return rv;
1077 if(!isNumeric(step)) return rv;
1078 if(!PyString_Check(chroms)) return rv;
1079 if(!isNumeric(starts)) return rv;
1080
1081 if(PyList_Check(values)) {
1082 sz = PyList_Size(values);
1083 for(i=0; i<sz; i++) {
1084 tmp = PyList_GetItem(values, i);
1085 if(!PyFloat_Check(tmp)) return rv;
1086 }
1087 #ifdef WITHNUMPY
1088 } else {
1089 if(!PyArray_ISFLOAT( (PyArrayObject*) values)) return rv;
1090 #endif
1091 }
1092 rv = 1;
1093 return rv;
1094 }
1095
1096 int getType(PyObject *chroms, PyObject *starts, PyObject *ends, PyObject *values, PyObject *span, PyObject *step) {
1097 if(!chroms) return -1;
1098 if(!starts) return -1;
1099 if(!values) return -1;
1100 if(chroms && starts && ends && values && isType0(chroms, starts, ends, values)) return 0;
1101 if(chroms && starts && span && values && isType1(chroms, starts, values, span)) return 1;
1102 if(chroms && starts && values && span && step && isType2(chroms, starts, values, span, step)) return 2;
1103 return -1;
1104 }
1105
1106 //1: Can use a bwAppend* function. 0: must use a bwAdd* function
1107 int canAppend(pyBigWigFile_t *self, int desiredType, PyObject *chroms, PyObject *starts, PyObject *span, PyObject *step) {
1108 bigWigFile_t *bw = self->bw;
1109 Py_ssize_t i, sz = 0;
1110 uint32_t tid, uspan, ustep, ustart;
1111 PyObject *tmp;
1112 #ifdef WITHNUMPY
1113 char *chrom;
1114 #endif
1115
1116 if(self->lastType == -1) return 0;
1117 if(self->lastTid == -1) return 0;
1118 if(self->lastType != desiredType) return 0;
1119
1120 //We can only append if (A) we have the same type or (B) the same chromosome (and compatible span/step/starts
1121 if(desiredType == 0) {
1122 //We need (A) chrom == lastTid and (B) all chroms to be the same
1123 if(PyList_Check(chroms)) sz = PyList_Size(chroms);
1124 #ifdef WITHNUMPY
1125 if(PyArray_Check(chroms)) sz = PyArray_Size(chroms);
1126 #endif
1127
1128 for(i=0; i<sz; i++) {
1129 #ifdef WITHNUMPY
1130 if(PyArray_Check(chroms)) {
1131 chrom = getNumpyStr((PyArrayObject*)chroms, i);
1132 tid = bwGetTid(bw, chrom);
1133 free(chrom);
1134 } else {
1135 #endif
1136 tmp = PyList_GetItem(chroms, i);
1137 tid = bwGetTid(bw, PyString_AsString(tmp));
1138 #ifdef WITHNUMPY
1139 }
1140 #endif
1141 if(tid != (uint32_t) self->lastTid) return 0;
1142 }
1143
1144 #ifdef WITHNUMPY
1145 if(PyArray_Check(starts)) {
1146 ustart = getNumpyU32((PyArrayObject*)starts, 0);
1147 } else {
1148 #endif
1149 ustart = Numeric2Uint(PyList_GetItem(starts, 0));
1150 #ifdef WITHNUMPY
1151 }
1152 #endif
1153 if(PyErr_Occurred()) return 0;
1154 if(ustart < self->lastStart) return 0;
1155 return 1;
1156 } else if(desiredType == 1) {
1157 //We need (A) chrom == lastTid, (B) all chroms to be the same, and (C) equal spans
1158 uspan = Numeric2Uint(span);
1159 if(PyErr_Occurred()) return 0;
1160 if(uspan != self->lastSpan) return 0;
1161 if(!PyString_Check(chroms)) return 0;
1162 tid = bwGetTid(bw, PyString_AsString(chroms));
1163 if(tid != (uint32_t) self->lastTid) return 0;
1164
1165 #ifdef WITHNUMPY
1166 if(PyList_Check(starts)) ustart = Numeric2Uint(PyList_GetItem(starts, 0));
1167 else ustart = getNumpyU32((PyArrayObject*) starts, 0);
1168 #else
1169 ustart = Numeric2Uint(PyList_GetItem(starts, 0));
1170 #endif
1171 if(PyErr_Occurred()) return 0;
1172 if(ustart < self->lastStart) return 0;
1173 return 1;
1174 } else if(desiredType == 2) {
1175 //We need (A) chrom == lastTid, (B) span/step to be equal and (C) compatible starts
1176 tid = bwGetTid(bw, PyString_AsString(chroms));
1177 if(tid != (uint32_t) self->lastTid) return 0;
1178 uspan = Numeric2Uint(span);
1179 if(PyErr_Occurred()) return 0;
1180 if(uspan != self->lastSpan) return 0;
1181 ustep = Numeric2Uint(step);
1182 if(PyErr_Occurred()) return 0;
1183 if(ustep != self->lastStep) return 0;
1184
1185 //But is the start position compatible?
1186 ustart = Numeric2Uint(starts);
1187 if(PyErr_Occurred()) return 0;
1188 if(ustart != self->lastStart) return 0;
1189 return 1;
1190 }
1191
1192 return 0;
1193 }
1194
1195 //Returns 0 on success, 1 on error. Sets self->lastTid && self->lastStart (unless there was an error)
1196 int PyAddIntervals(pyBigWigFile_t *self, PyObject *chroms, PyObject *starts, PyObject *ends, PyObject *values) {
1197 bigWigFile_t *bw = self->bw;
1198 Py_ssize_t i, sz = 0;
1199 char **cchroms = NULL;
1200 uint32_t n, *ustarts = NULL, *uends = NULL;
1201 float *fvalues = NULL;
1202 int rv;
1203
1204 if(PyList_Check(starts)) sz = PyList_Size(starts);
1205 #ifdef WITHNUMPY
1206 if(PyArray_Check(starts)) sz += PyArray_Size(starts);
1207 #endif
1208 n = (uint32_t) sz;
1209
1210 //Allocate space
1211 cchroms = calloc(n, sizeof(char*));
1212 ustarts = calloc(n, sizeof(uint32_t));
1213 uends = calloc(n, sizeof(uint32_t));
1214 fvalues = calloc(n, sizeof(float));
1215 if(!cchroms || !ustarts || !uends || !fvalues) goto error;
1216
1217 for(i=0; i<sz; i++) {
1218 if(PyList_Check(chroms)) {
1219 cchroms[i] = PyString_AsString(PyList_GetItem(chroms, i));
1220 #ifdef WITHNUMPY
1221 } else {
1222 cchroms[i] = getNumpyStr((PyArrayObject*)chroms, i);
1223 #endif
1224 }
1225 if(PyList_Check(starts)) {
1226 ustarts[i] = (uint32_t) PyLong_AsLong(PyList_GetItem(starts, i));
1227 #ifdef WITHNUMPY
1228 } else {
1229 ustarts[i] = getNumpyU32((PyArrayObject*)starts, i);
1230 #endif
1231 }
1232 if(PyErr_Occurred()) goto error;
1233 if(PyList_Check(ends)) {
1234 uends[i] = (uint32_t) PyLong_AsLong(PyList_GetItem(ends, i));
1235 #ifdef WITHNUMPY
1236 } else {
1237 uends[i] = getNumpyU32((PyArrayObject*)ends, i);
1238 #endif
1239 }
1240 if(PyErr_Occurred()) goto error;
1241 if(PyList_Check(values)) {
1242 fvalues[i] = (float) PyFloat_AsDouble(PyList_GetItem(values, i));
1243 #ifdef WITHNUMPY
1244 } else {
1245 fvalues[i] = getNumpyF((PyArrayObject*)values, i);
1246 #endif
1247 }
1248 if(PyErr_Occurred()) goto error;
1249 }
1250
1251 rv = bwAddIntervals(bw, cchroms, ustarts, uends, fvalues, n);
1252 if(!rv) {
1253 self->lastTid = bwGetTid(bw, cchroms[n-1]);
1254 self->lastStart = uends[n-1];
1255 }
1256 if(!PyList_Check(chroms)) {
1257 for(i=0; i<n; i++) free(cchroms[i]);
1258 }
1259 free(cchroms);
1260 free(ustarts);
1261 free(uends);
1262 free(fvalues);
1263 return rv;
1264
1265 error:
1266 if(cchroms) free(cchroms);
1267 if(ustarts) free(ustarts);
1268 if(uends) free(uends);
1269 if(fvalues) free(fvalues);
1270 return 1;
1271 }
1272
1273 //Returns 0 on success, 1 on error. Update self->lastStart
1274 int PyAppendIntervals(pyBigWigFile_t *self, PyObject *starts, PyObject *ends, PyObject *values) {
1275 bigWigFile_t *bw = self->bw;
1276 Py_ssize_t i, sz = 0;
1277 uint32_t n, *ustarts = NULL, *uends = NULL;
1278 float *fvalues = NULL;
1279 int rv;
1280
1281 if(PyList_Check(starts)) sz = PyList_Size(starts);
1282 #ifdef WITHNUMPY
1283 if(PyArray_Check(starts)) sz += PyArray_Size(starts);
1284 #endif
1285 n = (uint32_t) sz;
1286
1287 //Allocate space
1288 ustarts = calloc(n, sizeof(uint32_t));
1289 uends = calloc(n, sizeof(uint32_t));
1290 fvalues = calloc(n, sizeof(float));
1291 if(!ustarts || !uends || !fvalues) goto error;
1292
1293 for(i=0; i<sz; i++) {
1294 if(PyList_Check(starts)) {
1295 ustarts[i] = (uint32_t) PyLong_AsLong(PyList_GetItem(starts, i));
1296 #ifdef WITHNUMPY
1297 } else {
1298 ustarts[i] = getNumpyU32((PyArrayObject*) starts, i);
1299 #endif
1300 }
1301 if(PyErr_Occurred()) goto error;
1302 if(PyList_Check(ends)) {
1303 uends[i] = (uint32_t) PyLong_AsLong(PyList_GetItem(ends, i));
1304 #ifdef WITHNUMPY
1305 } else {
1306 uends[i] = getNumpyU32((PyArrayObject*) ends, i);
1307 #endif
1308 }
1309 if(PyErr_Occurred()) goto error;
1310 if(PyList_Check(values)) {
1311 fvalues[i] = (float) PyFloat_AsDouble(PyList_GetItem(values, i));
1312 #ifdef WITHNUMPY
1313 } else {
1314 fvalues[i] = getNumpyF((PyArrayObject*) values, i);
1315 #endif
1316 }
1317 if(PyErr_Occurred()) goto error;
1318 }
1319 rv = bwAppendIntervals(bw, ustarts, uends, fvalues, n);
1320 if(rv) self->lastStart = uends[n-1];
1321 free(ustarts);
1322 free(uends);
1323 free(fvalues);
1324 return rv;
1325
1326 error:
1327 if(ustarts) free(ustarts);
1328 if(uends) free(uends);
1329 if(fvalues) free(fvalues);
1330 return 1;
1331 }
1332
1333 //Returns 0 on success, 1 on error. Sets self->lastTid/lastStart/lastSpan (unless there was an error)
1334 int PyAddIntervalSpans(pyBigWigFile_t *self, PyObject *chroms, PyObject *starts, PyObject *values, PyObject *span) {
1335 bigWigFile_t *bw = self->bw;
1336 Py_ssize_t i, sz = 0;
1337 char *cchroms = NULL;
1338 uint32_t n, *ustarts = NULL, uspan;
1339 float *fvalues = NULL;
1340 int rv;
1341
1342 if(PyList_Check(starts)) sz = PyList_Size(starts);
1343 #ifdef WITHNUMPY
1344 else if(PyArray_Check(starts)) sz += PyArray_Size(starts);
1345 #endif
1346 n = (uint32_t) sz;
1347
1348 //Allocate space
1349 ustarts = calloc(n, sizeof(uint32_t));
1350 fvalues = calloc(n, sizeof(float));
1351 if(!ustarts || !fvalues) goto error;
1352 uspan = (uint32_t) PyLong_AsLong(span);
1353 cchroms = PyString_AsString(chroms);
1354
1355 if(PyList_Check(starts)) {
1356 for(i=0; i<sz; i++) {
1357 ustarts[i] = (uint32_t) PyLong_AsLong(PyList_GetItem(starts, i));
1358 if(PyErr_Occurred()) goto error;
1359 }
1360 #ifdef WITHNUMPY
1361 } else {
1362 for(i=0; i<sz; i++) {
1363 ustarts[i] = getNumpyU32((PyArrayObject*) starts, i);
1364 if(PyErr_Occurred()) goto error;
1365 }
1366 #endif
1367 }
1368 if(PyList_Check(values)) {
1369 for(i=0; i<sz; i++) {
1370 fvalues[i] = (float) PyFloat_AsDouble(PyList_GetItem(values, i));
1371 if(PyErr_Occurred()) goto error;
1372 }
1373 #ifdef WITHNUMPY
1374 } else {
1375 for(i=0; i<sz; i++) {
1376 fvalues[i] = getNumpyF((PyArrayObject*) values, i);
1377 if(PyErr_Occurred()) goto error;
1378 }
1379 #endif
1380 }
1381
1382 rv = bwAddIntervalSpans(bw, cchroms, ustarts, uspan, fvalues, n);
1383 if(!rv) {
1384 self->lastTid = bwGetTid(bw, cchroms);
1385 self->lastSpan = uspan;
1386 self->lastStart = ustarts[n-1]+uspan;
1387 }
1388 free(ustarts);
1389 free(fvalues);
1390 return rv;
1391
1392 error:
1393 if(ustarts) free(ustarts);
1394 if(fvalues) free(fvalues);
1395 return 1;
1396 }
1397
1398 //Returns 0 on success, 1 on error. Updates self->lastStart
1399 int PyAppendIntervalSpans(pyBigWigFile_t *self, PyObject *starts, PyObject *values) {
1400 bigWigFile_t *bw = self->bw;
1401 Py_ssize_t i, sz = 0;
1402 uint32_t n, *ustarts = NULL;
1403 float *fvalues = NULL;
1404 int rv;
1405
1406 if(PyList_Check(starts)) sz = PyList_Size(starts);
1407 #ifdef WITHNUMPY
1408 else if(PyArray_Check(starts)) sz += PyArray_Size(starts);
1409 #endif
1410 n = (uint32_t) sz;
1411
1412 //Allocate space
1413 ustarts = calloc(n, sizeof(uint32_t));
1414 fvalues = calloc(n, sizeof(float));
1415 if(!ustarts || !fvalues) goto error;
1416
1417 if(PyList_Check(starts)) {
1418 for(i=0; i<sz; i++) {
1419 ustarts[i] = (uint32_t) PyLong_AsLong(PyList_GetItem(starts, i));
1420 if(PyErr_Occurred()) goto error;
1421 }
1422 #ifdef WITHNUMPY
1423 } else {
1424 for(i=0; i<sz; i++) {
1425 ustarts[i] = getNumpyU32((PyArrayObject*) starts, i);
1426 if(PyErr_Occurred()) goto error;
1427 }
1428 #endif
1429 }
1430 if(PyList_Check(values)) {
1431 for(i=0; i<sz; i++) {
1432 fvalues[i] = (float) PyFloat_AsDouble(PyList_GetItem(values, i));
1433 if(PyErr_Occurred()) goto error;
1434 }
1435 #ifdef WITHNUMPY
1436 } else {
1437 for(i=0; i<sz; i++) {
1438 fvalues[i] = getNumpyF((PyArrayObject*) values, i);
1439 if(PyErr_Occurred()) goto error;
1440 }
1441 #endif
1442 }
1443
1444 rv = bwAppendIntervalSpans(bw, ustarts, fvalues, n);
1445 if(rv) self->lastStart = ustarts[n-1] + self->lastSpan;
1446 free(ustarts);
1447 free(fvalues);
1448 return rv;
1449
1450 error:
1451 if(ustarts) free(ustarts);
1452 if(fvalues) free(fvalues);
1453 return 1;
1454 }
1455
1456 //Returns 0 on success, 1 on error. Sets self->lastTid/self->lastSpan/lastStep/lastStart (unless there was an error)
1457 int PyAddIntervalSpanSteps(pyBigWigFile_t *self, PyObject *chroms, PyObject *starts, PyObject *values, PyObject *span, PyObject *step) {
1458 bigWigFile_t *bw = self->bw;
1459 Py_ssize_t i, sz = 0;
1460 char *cchrom = NULL;
1461 uint32_t n, ustarts, uspan, ustep;
1462 float *fvalues = NULL;
1463 int rv;
1464
1465 if(PyList_Check(values)) sz = PyList_Size(values);
1466 #ifdef WITHNUMPY
1467 else if(PyArray_Check(values)) sz += PyArray_Size(values);
1468 #endif
1469 n = (uint32_t) sz;
1470
1471 //Allocate space
1472 fvalues = calloc(n, sizeof(float));
1473 if(!fvalues) goto error;
1474 uspan = (uint32_t) PyLong_AsLong(span);
1475 ustep = (uint32_t) PyLong_AsLong(step);
1476 ustarts = (uint32_t) PyLong_AsLong(starts);
1477 cchrom = PyString_AsString(chroms);
1478
1479 if(PyList_Check(values)) {
1480 for(i=0; i<sz; i++) fvalues[i] = (float) PyFloat_AsDouble(PyList_GetItem(values, i));
1481 #ifdef WITHNUMPY
1482 } else {
1483 for(i=0; i<sz; i++) {
1484 fvalues[i] = getNumpyF((PyArrayObject*) values, i);
1485 if(PyErr_Occurred()) goto error;
1486 }
1487 #endif
1488 }
1489
1490 rv = bwAddIntervalSpanSteps(bw, cchrom, ustarts, uspan, ustep, fvalues, n);
1491 if(!rv) {
1492 self->lastTid = bwGetTid(bw, cchrom);
1493 self->lastSpan = uspan;
1494 self->lastStep = ustep;
1495 self->lastStart = ustarts + ustep*n;
1496 }
1497 free(fvalues);
1498 return rv;
1499
1500 error:
1501 if(fvalues) free(fvalues);
1502 return 1;
1503 }
1504
1505 //Returns 0 on success, 1 on error. Sets self->lastStart
1506 int PyAppendIntervalSpanSteps(pyBigWigFile_t *self, PyObject *values) {
1507 bigWigFile_t *bw = self->bw;
1508 Py_ssize_t i, sz = 0;
1509 uint32_t n;
1510 float *fvalues = NULL;
1511 int rv;
1512
1513 if(PyList_Check(values)) sz = PyList_Size(values);
1514 #ifdef WITHNUMPY
1515 else if(PyArray_Check(values)) sz += PyArray_Size(values);
1516 #endif
1517 n = (uint32_t) sz;
1518
1519 //Allocate space
1520 fvalues = calloc(n, sizeof(float));
1521 if(!fvalues) goto error;
1522
1523 if(PyList_Check(values)) {
1524 for(i=0; i<sz; i++) fvalues[i] = (float) PyFloat_AsDouble(PyList_GetItem(values, i));
1525 #ifdef WITHNUMPY
1526 } else {
1527 for(i=0; i<sz; i++) {
1528 fvalues[i] = getNumpyF((PyArrayObject*) values, i);
1529 if(PyErr_Occurred()) goto error;
1530 }
1531 #endif
1532 }
1533
1534 rv = bwAppendIntervalSpanSteps(bw, fvalues, n);
1535 if(!rv) self->lastStart += self->lastStep * n;
1536 free(fvalues);
1537 return rv;
1538
1539 error:
1540 if(fvalues) free(fvalues);
1541 return 1;
1542 }
1543
1544 //Checks and ensures that (A) the entries are sorted correctly and don't overlap and (B) that the come after things that have already been added.
1545 //Returns 1 on correct input, 0 on incorrect input
1546 int addEntriesInputOK(pyBigWigFile_t *self, PyObject *chroms, PyObject *starts, PyObject *ends, PyObject *span, PyObject *step, int type) {
1547 uint32_t lastTid = self->lastTid;
1548 uint32_t lastEnd = self->lastStart;
1549 uint32_t cTid, ustart, uend, uspan, ustep;
1550 Py_ssize_t i, sz = 0;
1551 PyObject *tmp;
1552 #ifdef WITHNUMPY
1553 char *tmpStr;
1554 #endif
1555
1556 if(type == 0) {
1557 //Each chrom:start-end needs to be properly formed and come after prior entries
1558 if(PyList_Check(starts)) sz = PyList_Size(starts);
1559 #ifdef WITHNUMPY
1560 if(PyArray_Check(starts)) sz += PyArray_Size(starts);
1561 #endif
1562 if(sz == 0) return 0;
1563 for(i=0; i<sz; i++) {
1564 #ifdef WITHNUMPY
1565 if(PyArray_Check(chroms)) {
1566 tmpStr = getNumpyStr((PyArrayObject*)chroms, i);
1567 cTid = bwGetTid(self->bw, tmpStr);
1568 free(tmpStr);
1569 } else {
1570 #endif
1571 tmp = PyList_GetItem(chroms, i);
1572 cTid = bwGetTid(self->bw, PyString_AsString(tmp));
1573 #ifdef WITHNUMPY
1574 }
1575 #endif
1576 if(PyErr_Occurred()) return 0;
1577 if(cTid == (uint32_t) -1) return 0;
1578
1579 #ifdef WITHNUMPY
1580 if(PyArray_Check(starts)) {
1581 ustart = getNumpyU32((PyArrayObject*)starts, i);
1582 } else {
1583 #endif
1584 ustart = Numeric2Uint(PyList_GetItem(starts, i));
1585 #ifdef WITHNUMPY
1586 }
1587 #endif
1588 if(PyErr_Occurred()) return 0;
1589 #ifdef WITHNUMPY
1590 if(PyArray_Check(ends)) {
1591 uend = getNumpyU32((PyArrayObject*) ends, i);
1592 } else {
1593 #endif
1594 uend = Numeric2Uint(PyList_GetItem(ends, i));
1595 #ifdef WITHNUMPY
1596 }
1597 #endif
1598 if(PyErr_Occurred()) return 0;
1599
1600 if(ustart >= uend) return 0;
1601 if(lastTid != (uint32_t) -1) {
1602 if(lastTid > cTid) return 0;
1603 if(lastTid == cTid) {
1604 if(ustart < lastEnd) return 0;
1605 }
1606 }
1607 lastTid = cTid;
1608 lastEnd = uend;
1609 }
1610 return 1;
1611 } else if(type == 1) {
1612 //each chrom:start-(start+span) needs to be properly formed and come after prior entries
1613 if(!PyList_Check(starts)
1614 #ifdef WITHNUMPY
1615 && !PyArray_Check(starts)
1616 #endif
1617 ) return 0;
1618 if(PyList_Check(starts)) sz = PyList_Size(starts);
1619 #ifdef WITHNUMPY
1620 else if(PyArray_Check(starts)) sz += PyArray_Size(starts);
1621 #endif
1622 uspan = Numeric2Uint(span);
1623 if(PyErr_Occurred()) return 0;
1624 if(uspan < 1) return 0;
1625 if(sz == 0) return 0;
1626 cTid = bwGetTid(self->bw, PyString_AsString(chroms));
1627 if(cTid == (uint32_t) -1) return 0;
1628 if(lastTid != (uint32_t) -1) {
1629 if(lastTid > cTid) return 0;
1630 }
1631 for(i=0; i<sz; i++) {
1632 #ifdef WITHNUMPY
1633 if(PyArray_Check(starts)) {
1634 ustart = getNumpyU32((PyArrayObject*)starts, i);
1635 } else {
1636 #endif
1637 ustart = Numeric2Uint(PyList_GetItem(starts, i));
1638 #ifdef WITHNUMPY
1639 }
1640 #endif
1641 if(PyErr_Occurred()) return 0;
1642 uend = ustart + uspan;
1643
1644 if(lastTid == cTid) {
1645 if(ustart < lastEnd) return 0;
1646 }
1647 lastTid = cTid;
1648 lastEnd = uend;
1649 }
1650 return 1;
1651 } else if(type == 2) {
1652 //The chrom and start need to be appropriate
1653 cTid = bwGetTid(self->bw, PyString_AsString(chroms));
1654 if(cTid == (uint32_t) -1) return 0;
1655 ustart = Numeric2Uint(starts);
1656 if(PyErr_Occurred()) return 0;
1657 uspan = Numeric2Uint(span);
1658 if(PyErr_Occurred()) return 0;
1659 if(uspan < 1) return 0;
1660 ustep = Numeric2Uint(step);
1661 if(PyErr_Occurred()) return 0;
1662 if(ustep < 1) return 0;
1663 if(lastTid != (uint32_t) -1) {
1664 if(lastTid > cTid) return 0;
1665 if(lastTid == cTid) {
1666 if(ustart < lastEnd) return 0;
1667 }
1668 }
1669 return 1;
1670 }
1671 return 0;
1672 }
1673
1674 PyObject *pyBwAddEntries(pyBigWigFile_t *self, PyObject *args, PyObject *kwds) {
1675 static char *kwd_list[] = {"chroms", "starts", "ends", "values", "span", "step", "validate", NULL};
1676 PyObject *chroms = NULL, *starts = NULL, *ends = NULL, *values = NULL, *span = NULL, *step = NULL;
1677 PyObject *validate = Py_True;
1678 int desiredType;
1679
1680 if(!self->bw) {
1681 PyErr_SetString(PyExc_RuntimeError, "The bigWig file handle is not open!");
1682 return NULL;
1683 }
1684
1685 if(!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOOO", kwd_list, &chroms, &starts, &ends, &values, &span, &step, &validate)) {
1686 PyErr_SetString(PyExc_RuntimeError, "Illegal arguments");
1687 return NULL;
1688 }
1689
1690 desiredType = getType(chroms, starts, ends, values, span, step);
1691 if(desiredType == -1) {
1692 PyErr_SetString(PyExc_RuntimeError, "You must provide a valid set of entries. These can be comprised of any of the following: \n"
1693 "1. A list of each of chromosomes, start positions, end positions and values.\n"
1694 "2. A list of each of start positions and values. Also, a chromosome and span must be specified.\n"
1695 "3. A list values, in which case a single chromosome, start position, span and step must be specified.\n");
1696 return NULL;
1697 }
1698
1699 if(validate == Py_True && !addEntriesInputOK(self, chroms, starts, ends, span, step, desiredType)) {
1700 PyErr_SetString(PyExc_RuntimeError, "The entries you tried to add are out of order, precede already added entries, or otherwise use illegal values.\n"
1701 " Please correct this and try again.\n");
1702 return NULL;
1703 }
1704
1705 if(canAppend(self, desiredType, chroms, starts, span, step)) {
1706 switch(desiredType) {
1707 case 0:
1708 if(PyAppendIntervals(self, starts, ends, values)) goto error;
1709 break;
1710 case 1:
1711 if(PyAppendIntervalSpans(self, starts, values)) goto error;
1712 break;
1713 case 2:
1714 if(PyAppendIntervalSpanSteps(self, values)) goto error;
1715 break;
1716 }
1717 } else {
1718 switch(desiredType) {
1719 case 0:
1720 if(PyAddIntervals(self, chroms, starts, ends, values)) goto error;
1721 break;
1722 case 1:
1723 if(PyAddIntervalSpans(self, chroms, starts, values, span)) goto error;
1724 break;
1725 case 2:
1726 if(PyAddIntervalSpanSteps(self, chroms, starts, values, span, step)) goto error;
1727 break;
1728 }
1729 }
1730 self->lastType = desiredType;
1731
1732 Py_INCREF(Py_None);
1733 return Py_None;
1734
1735 error:
1736 return NULL;
1737 }
1738
1739 /**************************************************************
1740 *
1741 * BigBed functions, added in 0.3.0
1742 *
1743 **************************************************************/
1744
1745 static PyObject *pyBBGetEntries(pyBigWigFile_t *self, PyObject *args, PyObject *kwds) {
1746 bigWigFile_t *bw = self->bw;
1747 uint32_t i;
1748 uint32_t start, end = -1, tid;
1749 unsigned long startl, endl;
1750 char *chrom;
1751 static char *kwd_list[] = {"chrom", "start", "end", "withString", NULL};
1752 PyObject *ret, *t, *starto = NULL, *endo = NULL;
1753 PyObject *withStringPy = Py_True;
1754 int withString = 1;
1755 bbOverlappingEntries_t *o;
1756
1757 if(!bw) {
1758 PyErr_SetString(PyExc_RuntimeError, "The bigBed file handle is not open!");
1759 return NULL;
1760 }
1761
1762 if(bw->type == 0) {
1763 PyErr_SetString(PyExc_RuntimeError, "bigWig files have no entries! Use 'intervals' or 'values' instead.");
1764 return NULL;
1765 }
1766
1767 if(!PyArg_ParseTupleAndKeywords(args, kwds, "sOO|O", kwd_list, &chrom, &starto, &endo, &withStringPy)) {
1768 PyErr_SetString(PyExc_RuntimeError, "You must supply a chromosome, start and end position.\n");
1769 return NULL;
1770 }
1771
1772 tid = bwGetTid(bw, chrom);
1773
1774 #ifdef WITHNUMPY
1775 if(PyArray_IsScalar(starto, Integer)) {
1776 startl = (long) getNumpyL(starto);
1777 } else
1778 #endif
1779 if(PyLong_Check(starto)) {
1780 startl = PyLong_AsLong(starto);
1781 #if PY_MAJOR_VERSION < 3
1782 } else if(PyInt_Check(starto)) {
1783 startl = PyInt_AsLong(starto);
1784 #endif
1785 } else {
1786 PyErr_SetString(PyExc_RuntimeError, "The start coordinate must be a number!");
1787 return NULL;
1788 }
1789
1790 #ifdef WITHNUMPY
1791 if(PyArray_IsScalar(endo, Integer)) {
1792 endl = (long) getNumpyL(endo);
1793 } else
1794 #endif
1795 if(PyLong_Check(endo)) {
1796 endl = PyLong_AsLong(endo);
1797 #if PY_MAJOR_VERSION < 3
1798 } else if(PyInt_Check(endo)) {
1799 endl = PyInt_AsLong(endo);
1800 #endif
1801 } else {
1802 PyErr_SetString(PyExc_RuntimeError, "The end coordinate must be a number!");
1803 return NULL;
1804 }
1805
1806 if(endl == (unsigned long) -1 && tid != (uint32_t) -1) endl = bw->cl->len[tid];
1807 if(tid == (uint32_t) -1 || startl > end || endl > end) {
1808 PyErr_SetString(PyExc_RuntimeError, "Invalid interval bounds!");
1809 return NULL;
1810 }
1811 start = (uint32_t) startl;
1812 end = (uint32_t) endl;
1813 if(end <= start || end > bw->cl->len[tid] || start >= end) {
1814 PyErr_SetString(PyExc_RuntimeError, "Invalid interval bounds!");
1815 return NULL;
1816 }
1817
1818 if(withStringPy == Py_False) withString = 0;
1819
1820 o = bbGetOverlappingEntries(bw, chrom, start, end, withString);
1821 if(!o) {
1822 PyErr_SetString(PyExc_RuntimeError, "An error occurred while fetching the overlapping entries!\n");
1823 return NULL;
1824 }
1825 if(!o->l) {
1826 Py_INCREF(Py_None);
1827 return Py_None;
1828 }
1829
1830 ret = PyList_New(o->l);
1831 if(!ret) goto error;
1832
1833 for(i=0; i<o->l; i++) {
1834 if(withString) {
1835 t = Py_BuildValue("(iis)", o->start[i], o->end[i], o->str[i]);
1836 } else {
1837 t = Py_BuildValue("(ii)", o->start[i], o->end[i]);
1838 }
1839 if(!t) goto error;
1840 PyList_SetItem(ret, i, t);
1841 }
1842
1843 bbDestroyOverlappingEntries(o);
1844 return ret;
1845
1846 error:
1847 Py_DECREF(ret);
1848 bbDestroyOverlappingEntries(o);
1849 PyErr_SetString(PyExc_RuntimeError, "An error occurred while constructing the output list and tuple!");
1850 return NULL;
1851 }
1852
1853 static PyObject *pyBBGetSQL(pyBigWigFile_t *self, PyObject *args) {
1854 bigWigFile_t *bw = self->bw;
1855 char *str = bbGetSQL(bw);
1856 size_t len = 0;
1857 PyObject *o = NULL;
1858
1859 if(!bw) {
1860 PyErr_SetString(PyExc_RuntimeError, "The bigBed file handle is not open!");
1861 return NULL;
1862 }
1863
1864 if(!str) {
1865 Py_INCREF(Py_None);
1866 return Py_None;
1867 }
1868 len = strlen(str);
1869
1870 #if PY_MAJOR_VERSION >= 3
1871 o = PyBytes_FromStringAndSize(str, len);
1872 #else
1873 o = PyString_FromStringAndSize(str, len);
1874 #endif
1875 if(str) free(str);
1876
1877 return o;
1878 }
1879
1880 static PyObject *pyIsBigWig(pyBigWigFile_t *self, PyObject *args) {
1881 bigWigFile_t *bw = self->bw;
1882 if(bw->type == 0) {
1883 Py_INCREF(Py_True);
1884 return Py_True;
1885 }
1886
1887 Py_INCREF(Py_False);
1888 return Py_False;
1889 }
1890
1891 static PyObject *pyIsBigBed(pyBigWigFile_t *self, PyObject *args) {
1892 bigWigFile_t *bw = self->bw;
1893
1894 if(!bw) {
1895 PyErr_SetString(PyExc_RuntimeError, "The bigBed file handle is not open!");
1896 return NULL;
1897 }
1898
1899 if(bw->type == 1) {
1900 Py_INCREF(Py_True);
1901 return Py_True;
1902 }
1903
1904 Py_INCREF(Py_False);
1905 return Py_False;
1906 }
1907
1908 /**************************************************************
1909 *
1910 * End of bigBed functions
1911 *
1912 **************************************************************/
1913
1914 #if PY_MAJOR_VERSION >= 3
1915 PyMODINIT_FUNC PyInit_pyBigWig(void) {
1916 #else
1917 PyMODINIT_FUNC initpyBigWig(void) {
1918 #endif
1919 PyObject *res;
1920 errno = 0; //just in case
1921
1922 #if PY_MAJOR_VERSION >= 3
1923 if(Py_AtExit(bwCleanup)) return NULL;
1924 if(PyType_Ready(&bigWigFile) < 0) return NULL;
1925 if(bwInit(128000)) return NULL;
1926 res = PyModule_Create(&pyBigWigmodule);
1927 if(!res) return NULL;
1928 #else
1929 if(Py_AtExit(bwCleanup)) return;
1930 if(PyType_Ready(&bigWigFile) < 0) return;
1931 if(bwInit(128000)) return;
1932 res = Py_InitModule3("pyBigWig", bwMethods, "A module for handling bigWig files");
1933 #endif
1934
1935 Py_INCREF(&bigWigFile);
1936 PyModule_AddObject(res, "pyBigWig", (PyObject *) &bigWigFile);
1937
1938 #ifdef WITHNUMPY
1939 //Add the numpy constant
1940 import_array(); //Needed for numpy stuff to work
1941 PyModule_AddIntConstant(res, "numpy", 1);
1942 #else
1943 PyModule_AddIntConstant(res, "numpy", 0);
1944 #endif
1945 #ifdef NOCURL
1946 PyModule_AddIntConstant(res, "remote", 0);
1947 #else
1948 PyModule_AddIntConstant(res, "remote", 1);
1949 #endif
1950 PyModule_AddStringConstant(res, "__version__", pyBigWigVersion);
1951
1952 #if PY_MAJOR_VERSION >= 3
1953 return res;
1954 #endif
1955 }
1956