@@ -356,6 +356,7 @@ static PyObject *py2bitHardMaskedBlocks(pyTwoBit_t *self, PyObject *args, PyObje
356
356
// Form the output
357
357
ret = PyList_New (totalBlocks );
358
358
if (!ret ) goto error ;
359
+ if (totalBlocks == 0 ) return ret ;
359
360
for (i = 0 , j = 0 ; i < tb -> idx -> nBlockCount [tid ]; i ++ ) {
360
361
blockStart = tb -> idx -> nBlockStart [tid ][i ];
361
362
blockEnd = blockStart + tb -> idx -> nBlockSizes [tid ][i ];
@@ -375,6 +376,80 @@ static PyObject *py2bitHardMaskedBlocks(pyTwoBit_t *self, PyObject *args, PyObje
375
376
return NULL ;
376
377
}
377
378
379
+ static PyObject * py2bitSoftMaskedBlocks (pyTwoBit_t * self , PyObject * args , PyObject * kwds ) {
380
+ PyObject * ret = NULL , * tup = NULL ;
381
+ TwoBit * tb = self -> tb ;
382
+ char * chrom ;
383
+ unsigned long startl = 0 , endl = 0 , totalBlocks = 0 , tid ;
384
+ uint32_t start , end , len , blockStart , blockEnd , i , j ;
385
+ static char * kwd_list [] = {"chrom" , "start" , "end" , NULL };
386
+
387
+ if (!tb ) {
388
+ PyErr_SetString (PyExc_RuntimeError , "The 2bit file handle is not open!" );
389
+ return NULL ;
390
+ }
391
+
392
+ if (!PyArg_ParseTupleAndKeywords (args , kwds , "s|kk" , kwd_list , & chrom , & startl , & endl )) {
393
+ PyErr_SetString (PyExc_RuntimeError , "You must supply at least a chromosome!" );
394
+ return NULL ;
395
+ }
396
+
397
+ //Get the chromosome ID
398
+ for (i = 0 ; i < tb -> hdr -> nChroms ; i ++ ) {
399
+ if (strcmp (tb -> cl -> chrom [i ], chrom ) == 0 ) {
400
+ tid = i ;
401
+ break ;
402
+ }
403
+ }
404
+
405
+ len = twobitChromLen (tb , chrom );
406
+ if (len == 0 ) {
407
+ PyErr_SetString (PyExc_RuntimeError , "The specified chromosome doesn't exist in the 2bit file!" );
408
+ return NULL ;
409
+ }
410
+ if (endl == 0 ) endl = len ;
411
+ if (endl > len ) endl = len ;
412
+ end = (uint32_t ) endl ;
413
+ if (startl >= endl && startl > 0 ) {
414
+ PyErr_SetString (PyExc_RuntimeError , "The start value must be less then the end value (and the end of the chromosome" );
415
+ return NULL ;
416
+ }
417
+ start = (uint32_t ) startl ;
418
+
419
+ if (!tb -> idx -> maskBlockStart ) {
420
+ PyErr_SetString (PyExc_RuntimeError , "The file was not opened with storeMasked=True! Consequently, there are no stored soft-masked regions." );
421
+ return NULL ;
422
+ }
423
+
424
+ // Count the total number of overlapping soft-masked blocks
425
+ for (i = 0 ; i < tb -> idx -> maskBlockCount [tid ]; i ++ ) {
426
+ blockStart = tb -> idx -> maskBlockStart [tid ][i ];
427
+ blockEnd = blockStart + tb -> idx -> maskBlockSizes [tid ][i ];
428
+ if (blockStart < end && blockEnd > start ) totalBlocks ++ ;
429
+ }
430
+
431
+ // Form the output
432
+ ret = PyList_New (totalBlocks );
433
+ if (!ret ) goto error ;
434
+ if (totalBlocks == 0 ) return ret ;
435
+ for (i = 0 , j = 0 ; i < tb -> idx -> maskBlockCount [tid ]; i ++ ) {
436
+ blockStart = tb -> idx -> maskBlockStart [tid ][i ];
437
+ blockEnd = blockStart + tb -> idx -> maskBlockSizes [tid ][i ];
438
+ if (blockStart < end && blockEnd > start ) {
439
+ tup = Py_BuildValue ("(kk)" , (unsigned long ) blockStart , (unsigned long ) blockEnd );
440
+ if (!tup ) goto error ;
441
+ if (PyList_SetItem (ret , j ++ , tup )) goto error ;
442
+ }
443
+ }
444
+
445
+ return ret ;
446
+ error :
447
+ if (ret ) Py_XDECREF (ret );
448
+ if (tup ) Py_XDECREF (tup );
449
+ PyErr_SetString (PyExc_RuntimeError , "Received an error while constructing the output list and tuples!" );
450
+ return NULL ;
451
+ }
452
+
378
453
#if PY_MAJOR_VERSION >= 3
379
454
PyMODINIT_FUNC PyInit_py2bit (void ) {
380
455
PyObject * res ;
0 commit comments