4 * Copyright (c) 2011 Seoul National University.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * Contact: Hyeshik Chang <hyeshik@snu.ac.kr>
31 #define PY_SSIZE_T_CLEAN
35 static PyObject *TabixError;
47 } TabixIteratorObject;
49 static PyTypeObject Tabix_Type, TabixIterator_Type;
51 /* --- TabixIterator --------------------------------------------------- */
54 tabixiter_create(TabixObject *parentidx, ti_iter_t iter)
56 TabixIteratorObject *self;
58 self = PyObject_New(TabixIteratorObject, &TabixIterator_Type);
63 self->tbobj = parentidx;
66 return (PyObject *)self;
70 tabixiter_dealloc(TabixIteratorObject *self)
72 ti_iter_destroy(self->iter);
73 Py_DECREF(self->tbobj);
78 tabixiter_iter(PyObject *self)
84 #if PY_MAJOR_VERSION < 3
85 # define PYOBJECT_FROM_STRING_AND_SIZE PyString_FromStringAndSize
87 # define PYOBJECT_FROM_STRING_AND_SIZE PyUnicode_FromStringAndSize
91 tabixiter_iternext(TabixIteratorObject *self)
96 chunk = ti_read(self->tbobj->tb, self->iter, &len);
98 PyObject *ret, *column;
100 const char *ptr, *begin;
108 for (i = len; i > 0; i--, ptr++)
110 column = PYOBJECT_FROM_STRING_AND_SIZE(begin,
111 (Py_ssize_t)(ptr - begin));
112 if (column == NULL || PyList_Append(ret, column) == -1) {
122 column = PYOBJECT_FROM_STRING_AND_SIZE(begin, (Py_ssize_t)(ptr - begin));
123 if (column == NULL || PyList_Append(ret, column) == -1) {
135 static PyMethodDef tabixiter_methods[] = {
136 {NULL, NULL} /* sentinel */
139 static PyTypeObject TabixIterator_Type = {
140 PyVarObject_HEAD_INIT(NULL, 0)
141 "tabix.TabixIterator", /*tp_name*/
142 sizeof(TabixIteratorObject), /*tp_basicsize*/
145 (destructor)tabixiter_dealloc, /*tp_dealloc*/
152 0, /*tp_as_sequence*/
160 Py_TPFLAGS_DEFAULT, /*tp_flags*/
164 0, /*tp_richcompare*/
165 0, /*tp_weaklistoffset*/
166 tabixiter_iter, /*tp_iter*/
167 (iternextfunc)tabixiter_iternext, /*tp_iternext*/
168 tabixiter_methods, /*tp_methods*/
184 /* --- Tabix ----------------------------------------------------------- */
187 tabix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
190 const char *fn, *fnidx=NULL;
191 static char *kwnames[]={"fn", "fnidx", NULL};
194 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|z:Tabix",
195 kwnames, &fn, &fnidx))
198 tb = ti_open(fn, fnidx);
200 PyErr_SetString(TabixError, "Can't open the index file.");
204 self = (TabixObject *)type->tp_alloc(type, 0);
209 self->fn = strdup(fn);
211 return (PyObject *)self;
215 tabix_dealloc(TabixObject *self)
223 tabix_query(TabixObject *self, PyObject *args)
229 if (!PyArg_ParseTuple(args, "sii:query", &name, &begin, &end))
232 result = ti_query(self->tb, name, begin, end);
233 if (result == NULL) {
234 PyErr_SetString(TabixError, "query failed");
238 return tabixiter_create(self, result);
242 tabix_queryi(TabixObject *self, PyObject *args)
247 if (!PyArg_ParseTuple(args, "iii:queryi", &tid, &begin, &end))
250 result = ti_queryi(self->tb, tid, begin, end);
251 if (result == NULL) {
252 PyErr_SetString(TabixError, "query failed");
256 return tabixiter_create(self, result);
260 tabix_querys(TabixObject *self, PyObject *args)
265 if (!PyArg_ParseTuple(args, "s:querys", ®))
268 result = ti_querys(self->tb, reg);
269 if (result == NULL) {
270 PyErr_SetString(TabixError, "query failed");
274 return tabixiter_create(self, result);
278 tabix_repr(TabixObject *self)
280 #if PY_MAJOR_VERSION < 3
281 return PyString_FromFormat("<Tabix fn=\"%s\">", self->fn);
283 return PyUnicode_FromFormat("<Tabix fn=\"%s\">", self->fn);
287 static PyMethodDef tabix_methods[] = {
288 {"query", (PyCFunction)tabix_query, METH_VARARGS,
289 PyDoc_STR("T.query(name, begin, end) -> iterator")},
290 {"queryi", (PyCFunction)tabix_queryi, METH_VARARGS,
291 PyDoc_STR("T.queryi(tid, begin, id) -> iterator")},
292 {"querys", (PyCFunction)tabix_querys, METH_VARARGS,
293 PyDoc_STR("T.querys(region) -> iterator")},
294 {NULL, NULL} /* sentinel */
297 static PyTypeObject Tabix_Type = {
298 /* The ob_type field must be initialized in the module init function
299 * to be portable to Windows without using C++. */
300 PyVarObject_HEAD_INIT(NULL, 0)
301 "tabix.Tabix", /*tp_name*/
302 sizeof(TabixObject), /*tp_basicsize*/
305 (destructor)tabix_dealloc, /*tp_dealloc*/
310 (reprfunc)tabix_repr, /*tp_repr*/
312 0, /*tp_as_sequence*/
320 Py_TPFLAGS_DEFAULT, /*tp_flags*/
324 0, /*tp_richcompare*/
325 0, /*tp_weaklistoffset*/
328 tabix_methods, /*tp_methods*/
338 (newfunc)tabix_new, /*tp_new*/
342 /* --------------------------------------------------------------------- */
344 static PyMethodDef tabix_functions[] = {
345 {NULL, NULL} /* sentinel */
348 PyDoc_STRVAR(module_doc,
349 "Python interface to tabix, Heng Li's generic indexer for TAB-delimited "
350 "genome position filesThis is a template module just for instruction.");
352 #if PY_MAJOR_VERSION >= 3
353 static struct PyModuleDef tabixmodule = {
354 PyModuleDef_HEAD_INIT,
366 #if PY_MAJOR_VERSION < 3
367 PyMODINIT_FUNC inittabix(void)
369 PyMODINIT_FUNC PyInit_tabix(void)
374 if (PyType_Ready(&Tabix_Type) < 0)
376 if (PyType_Ready(&TabixIterator_Type) < 0)
379 #if PY_MAJOR_VERSION < 3
380 m = Py_InitModule3("tabix", tabix_functions, module_doc);
382 m = PyModule_Create(&tabixmodule);
387 if (TabixError == NULL) {
388 TabixError = PyErr_NewException("tabix.error", NULL, NULL);
389 if (TabixError == NULL)
392 Py_INCREF(TabixError);
393 PyModule_AddObject(m, "error", TabixError);
395 PyModule_AddObject(m, "Tabix", (PyObject *)&Tabix_Type);
396 PyModule_AddObject(m, "TabixIterator", (PyObject *)&TabixIterator_Type);
398 #if PY_MAJOR_VERSION >= 3
403 #if PY_MAJOR_VERSION < 3