Skip to content

Commit 6c85e81

Browse files
authored
Merge pull request #55 from deeptools/fix54
Fix BigWig creation with numpy
2 parents 06b7232 + ed075e9 commit 6c85e81

File tree

5 files changed

+47
-18
lines changed

5 files changed

+47
-18
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ python:
66
- "3.4"
77
- "3.5"
88
- "3.6"
9-
install: python ./setup.py install
9+
install: pip install numpy && python ./setup.py install
1010
script: nosetests -sv

pyBigWig.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ float getNumpyF(PyArrayObject *obj, Py_ssize_t i) {
119119
return 0;
120120
}
121121

122+
//The calling function needs to free the result
122123
char *getNumpyStr(PyArrayObject *obj, Py_ssize_t i) {
123124
char *p , *o = NULL;
124125
npy_intp stride, j;
@@ -137,7 +138,7 @@ char *getNumpyStr(PyArrayObject *obj, Py_ssize_t i) {
137138
return o;
138139
case NPY_UNICODE:
139140
o = calloc(1, stride/4 + 1);
140-
for(j=0; j<stride/4; j++) o[j] = (char) ((uint32_t*)p)[4*j];
141+
for(j=0; j<stride/4; j++) o[j] = (char) ((uint32_t*)p)[j];
141142
return o;
142143
default:
143144
PyErr_SetString(PyExc_RuntimeError, "Received unknown data type!\n");
@@ -908,6 +909,7 @@ int canAppend(pyBigWigFile_t *self, int desiredType, PyObject *chroms, PyObject
908909
PyObject *tmp;
909910
#ifdef WITHNUMPY
910911
void *foo;
912+
char *chrom;
911913
#endif
912914

913915
if(self->lastType == -1) return 0;
@@ -925,10 +927,9 @@ int canAppend(pyBigWigFile_t *self, int desiredType, PyObject *chroms, PyObject
925927
for(i=0; i<sz; i++) {
926928
#ifdef WITHNUMPY
927929
if(PyArray_Check(chroms)) {
928-
foo = PyArray_GETPTR1((PyArrayObject*)chroms, i);
929-
tmp = PyArray_GETITEM((PyArrayObject*)chroms, foo);
930-
tid = bwGetTid(bw, PyString_AsString(tmp));
931-
Py_DECREF(tmp);
930+
chrom = getNumpyStr((PyArrayObject*)chroms, i);
931+
tid = bwGetTid(bw, chrom);
932+
free(chrom);
932933
} else {
933934
#endif
934935
tmp = PyList_GetItem(chroms, i);
@@ -1021,10 +1022,7 @@ int PyAddIntervals(pyBigWigFile_t *self, PyObject *chroms, PyObject *starts, PyO
10211022
cchroms[i] = PyString_AsString(PyList_GetItem(chroms, i));
10221023
#ifdef WITHNUMPY
10231024
} else {
1024-
foo = PyArray_GETPTR1((PyArrayObject*)chroms, i);
1025-
tmp = PyArray_GETITEM((PyArrayObject*)chroms, foo);
1026-
cchroms[i] = PyString_AsString(tmp);
1027-
Py_DECREF(tmp);
1025+
cchroms[i] = getNumpyStr((PyArrayObject*)chroms, i);
10281026
#endif
10291027
}
10301028
if(PyList_Check(starts)) {
@@ -1058,6 +1056,9 @@ int PyAddIntervals(pyBigWigFile_t *self, PyObject *chroms, PyObject *starts, PyO
10581056
self->lastTid = bwGetTid(bw, cchroms[n-1]);
10591057
self->lastStart = uends[n-1];
10601058
}
1059+
if(!PyList_Check(chroms)) {
1060+
for(i=0; i<n; i++) free(cchroms[i]);
1061+
}
10611062
free(cchroms);
10621063
free(ustarts);
10631064
free(uends);

pyBigWig.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include <structmember.h>
33
#include "bigWig.h"
44

5-
#define pyBigWigVersion "0.3.9"
5+
#define pyBigWigVersion "0.3.10"
66

77
typedef struct {
88
PyObject_HEAD

pyBigWigTest/test.py

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,18 +157,46 @@ def doWriteEmpty(self):
157157
#Clean up
158158
os.remove(oname)
159159

160+
def doWriteNumpy(self):
161+
import numpy as np
162+
ofile = tempfile.NamedTemporaryFile(delete=False)
163+
oname = ofile.name
164+
ofile.close()
165+
bw = pyBigWig.open(oname, "w")
166+
bw.addHeader([("chr1", 100), ("chr2", 150), ("chr3", 200), ("chr4", 250)])
167+
chroms = np.array(["chr1"] * 2 + ["chr2"] * 2 + ["chr3"] * 2 + ["chr4"] * 2)
168+
starts = np.array([0, 10, 40, 50, 60, 70, 80, 90], dtype=np.int64)
169+
ends = np.array([5, 15, 45, 55, 65, 75, 85, 95], dtype=np.int64)
170+
values0 = np.array(np.random.random_sample(8), dtype=np.float64)
171+
bw.addEntries(chroms, starts, ends=ends, values=values0)
172+
bw.close()
173+
174+
vals = [(x, y, z) for x, y, z in zip(starts, ends, values0)]
175+
bw = pyBigWig.open(oname)
176+
assert(bw.chroms() == {'chr1': 100, 'chr2': 150, 'chr3': 200, 'chr4': 250})
177+
for idx1, chrom in enumerate(["chr1", "chr2", "chr3", "chr4"]):
178+
for idx2, tup in enumerate(bw.intervals(chrom)):
179+
assert(tup[0] == starts[2 * idx1 + idx2])
180+
assert(tup[1] == ends[2 * idx1 + idx2])
181+
assert(np.isclose(tup[2], values0[2 * idx1 + idx2]))
182+
bw.close()
183+
184+
#Clean up
185+
os.remove(oname)
186+
160187
def testAll(self):
161188
bw = self.doOpen()
162189
self.doChroms(bw)
163-
self.doHeader(bw)
164-
self.doStats(bw)
165-
self.doValues(bw)
166-
self.doIntervals(bw)
167-
self.doWrite(bw)
168190
if not self.fname.startswith("http"):
191+
self.doHeader(bw)
192+
self.doStats(bw)
193+
self.doValues(bw)
194+
self.doIntervals(bw)
195+
self.doWrite(bw)
169196
self.doOpenWith()
170197
self.doWrite2()
171198
self.doWriteEmpty()
199+
self.doWriteNumpy()
172200
bw.close()
173201

174202
class TestLocal():

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@
5858
include_dirs = include_dirs)
5959

6060
setup(name = 'pyBigWig',
61-
version = '0.3.9',
61+
version = '0.3.10',
6262
description = 'A package for accessing bigWig files using libBigWig',
6363
author = "Devon P. Ryan",
6464
author_email = "[email protected]",
6565
url = "https://github.com/dpryan79/pyBigWig",
66-
download_url = "https://github.com/dpryan79/pyBigWig/tarball/0.3.9",
66+
download_url = "https://github.com/dpryan79/pyBigWig/tarball/0.3.10",
6767
keywords = ["bioinformatics", "bigWig", "bigBed"],
6868
classifier = ["Development Status :: 5 - Production/Stable",
6969
"Intended Audience :: Developers",

0 commit comments

Comments
 (0)