<commit_before>################################################################################
#
#   MRC FGU Computational Genomics Group
#
#   $Id$
#
#   Copyright (C) 2009 <NAME>
#
#   This program is free software; you can redistribute it and/or
#   modify it under the terms of the GNU General Public License
#   as published by the Free Software Foundation; either version 2
#   of the License, or (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#################################################################################
'''
Bed.py - Tools for working with bed files
=========================================

:Author: <NAME>
:Release: $Id$
:Date: |today|
:Tags: Python

Code
----

'''
import re
import ncl
import numpy
import bisect
import itertools

class Bed(object):
    """an interval in bed format."""

    map_key2field = { 'name' : 0,
                      'score' : 1,
                      'strand' : 2,
                      'thickStart' : 3,
                      'thickEnd' : 4,
                      'itemRGB' : 5,
                      'blockCount': 6,
                      'blockSizes': 7,
                      'blockStarts': 8 }

    def __init__(self):
        '''empty constructor.'''
        self.contig = None
        self.start = 0
        self.end = 0
        self.mFields = []
        self.mTrack = None
        
    def __str__(self):
        return "\t".join( (self.contig, str(self.start), str(self.end) ) + tuple(map(str, self.mFields)))

    def fromGFF( self, gff, is_gtf = False, name=None ):
        """fill from gff formatted entry."""
        self.contig, self.start, self.end = gff.contig, gff.start, gff.end
        try:
            self.mFields = [getattr( gff, name), 
                            [gff.score,0][gff.score == None], 
                            gff.strand ]
        except AttributeError:
            self.mFields = [gff[name],
                            [gff.score,0][gff.score == None], 
                            gff.strand ]
            
    def __contains__(self, key ):
        return self.map_key2field[key] < len(self.mFields)

    def __getitem__(self, key):
        return self.mFields[self.map_key2field[key]]

    def __getattr__(self, key ):
        return self.mFields[self.map_key2field[key]]
        

    @property
    def columns(self):
        '''return number of columns in bed-entry.'''
        return 3 + len(self.mFields)

class Track(object):
    '''bed track information.'''
    def __init__(self, line ):
        r= re.compile('([^ =]+) *= *("[^"]*"|[^ ]*)')

        self._d = {}
        for k, v in r.findall(line[:-1]):
            if v[:1]=='"':
                self._d[k] = v[1:-1]
            else:
                self._d[k] = v
            
        self._line = line[:-1]
    def __str__(self):
        return self._line

    def __getitem__(self, key): return self._d[key]
    def __setitem__(self, key,val): self._d[key] = val
        
def iterator( infile ):
    """iterate over a bed formatted file.

    The iterator is :term:`track` aware.

    This iterator yields :class:`Bed` objects. 
    """

    track = None
    for line in infile:
        if line.startswith("track"):
            track = Track( line )
            continue
        # ignore comments
        if line.startswith("#"): continue
        # ignore empty lines (in order to parse pseudo bed files)
        if line.strip() == "": continue

        b = Bed()
        data = line[:-1].split()
        try:
            b.contig, b.start, b.end = data[0], int(data[1]), int(data[2])
        except IndexError:
            raise ValueError("parsing error in line '%s'" % line[:-1])
        b.mFields = data[3:]
        b.mTrack = track
        yield b

# for compatibility, remove
def bed_iterator( infile ):
    return iterator( infile )
<commit_msg>Bed.py - use tab as separator only<commit_after>################################################################################
#
#   MRC FGU Computational Genomics Group
#
#   $Id$
#
#   Copyright (C) 2009 <NAME>
#
#   This program is free software; you can redistribute it and/or
#   modify it under the terms of the GNU General Public License
#   as published by the Free Software Foundation; either version 2
#   of the License, or (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#################################################################################
'''
Bed.py - Tools for working with bed files
=========================================

:Author: <NAME>
:Release: $Id$
:Date: |today|
:Tags: Python

Code
----

'''
import re
import ncl
import numpy
import bisect
import itertools

class Bed(object):
    """an interval in bed format."""

    map_key2field = { 'name' : 0,
                      'score' : 1,
                      'strand' : 2,
                      'thickStart' : 3,
                      'thickEnd' : 4,
                      'itemRGB' : 5,
                      'blockCount': 6,
                      'blockSizes': 7,
                      'blockStarts': 8 }

    def __init__(self):
        '''empty constructor.'''
        self.contig = None
        self.start = 0
        self.end = 0
        self.mFields = []
        self.mTrack = None
        
    def __str__(self):
        return "\t".join( (self.contig, str(self.start), str(self.end) ) + tuple(map(str, self.mFields)))

    def fromGFF( self, gff, is_gtf = False, name=None ):
        """fill from gff formatted entry."""
        self.contig, self.start, self.end = gff.contig, gff.start, gff.end
        try:
            self.mFields = [getattr( gff, name), 
                            [gff.score,0][gff.score == None], 
                            gff.strand ]
        except AttributeError:
            self.mFields = [gff[name],
                            [gff.score,0][gff.score == None], 
                            gff.strand ]
            
    def __contains__(self, key ):
        return self.map_key2field[key] < len(self.mFields)

    def __getitem__(self, key):
        return self.mFields[self.map_key2field[key]]

    def __getattr__(self, key ):
        return self.mFields[self.map_key2field[key]]
        

    @property
    def columns(self):
        '''return number of columns in bed-entry.'''
        return 3 + len(self.mFields)

class Track(object):
    '''bed track information.'''
    def __init__(self, line ):
        r= re.compile('([^ =]+) *= *("[^"]*"|[^ ]*)')

        self._d = {}
        for k, v in r.findall(line[:-1]):
            if v[:1]=='"':
                self._d[k] = v[1:-1]
            else:
                self._d[k] = v
            
        self._line = line[:-1]
    def __str__(self):
        return self._line

    def __getitem__(self, key): return self._d[key]
    def __setitem__(self, key,val): self._d[key] = val
        
def iterator( infile ):
    """iterate over a bed formatted file.

    The iterator is :term:`track` aware.

    This iterator yields :class:`Bed` objects. 
    """

    track = None
    for line in infile:
        if line.startswith("track"):
            track = Track( line )
            continue
        # ignore comments
        if line.startswith("#"): continue
        # ignore empty lines (in order to parse pseudo bed files)
        if line.strip() == "": continue

        b = Bed()
        # split at tab (Bed standard, do not split at space as this will split the name field)
        data = line[:-1].split("\t")
        try:
            b.contig, b.start, b.end = data[0], int(data[1]), int(data[2])
        except IndexError:
            raise ValueError("parsing error in line '%s'" % line[:-1])
        b.mFields = data[3:]
        b.mTrack = track
        yield b

# for compatibility, remove
def bed_iterator( infile ):
    return iterator( infile )

{'fraction_non_alphanumeric': 0.16236460013828072, 'fraction_numerical': 0.011062456787278175, 'mean_word_length': 2.019832985386221, 'pattern_counts': {'":': 2, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1380608', 'n_tokens_mistral': 2603, 'n_tokens_neox': 2471, 'n_words': 786}