# Path: gffutils/constants.py
# SCHEMA = """
# 
# CREATE TABLE features (
#     id text,
#     seqid text,
#     source text,
#     featuretype text,
#     start int,
#     end int,
#     score text,
#     strand text,
#     frame text,
#     attributes text,
#     extra text,
#     bin int,
#     primary key (id)
#     );
# 
# CREATE TABLE relations (
#     parent text,
#     child text,
#     level int,
#     primary key (parent, child, level)
#     );
# 
# CREATE TABLE meta (
#     dialect text,
#     version text
#     );
# 
# CREATE TABLE directives (
#     directive text
#     );
# 
# CREATE TABLE autoincrements (
#     base text,
#     n int,
#     primary key (base)
#     );
# 
# CREATE TABLE duplicates (
#     idspecid text,
#     newid text,
#     primary key (newid)
#     );
# 
# 
# """
# _SELECT = "SELECT " \
#     + ', '.join(_keys) \
#     + ", features.rowid as file_order FROM features "
# _INSERT = "INSERT INTO features (" \
#     + ', '.join(_keys) + ") VALUES (" + ','.join(list('?' * len(_keys))) + ")"
# _UPDATE = "UPDATE features SET " + _update_clause + " WHERE id = ?"
# INDEXES = []
# 
# Path: gffutils/bins.py
# def bins(start, stop, fmt='gff', one=True):
#     """
#     Uses the definition of a "genomic bin" described in Fig 7 of
#     http://genome.cshlp.org/content/12/6/996.abstract.
# 
#     Parameters
#     ----------
#     one : boolean
#         If `one=True` (default), then only return the smallest bin that
#         completely contains these coordinates (useful for assigning a single
#         bin).
# 
#         If `one=False`, then return the set of *all* bins that overlap these
#         coordinates (useful for looking for features that could intersect)
# 
#     fmt : 'gff' | 'bed'
#         This specifies 1-based start coords (gff) or 0-based start coords (bed)
#     """
# 
#     # For very large coordinates, return 1 which is "somewhere on the
#     # chromosome".
#     if start >= MAX_CHROM_SIZE or stop >= MAX_CHROM_SIZE:
#         if one:
#             return 1
#         else:
#             return set([1])
# 
#     # Jump to highest resolution bin that will fit these coords (depending on
#     # whether we have a BED or GFF-style coordinate).
#     #
#     # Some GFF files include negative coords, which will throw off this
#     # calculation.  If negative coords, then set the bin to the largest
#     # possible.
#     if start < 0:
#         if one:
#             return 1
#         else:
#             return set([1])
# 
#     if stop < 0:
#         if one:
#             return 1
#         else:
#             return set([1])
# 
#     start = (start - COORD_OFFSETS[fmt]) >> FIRST_SHIFT
#     stop = (stop) >> FIRST_SHIFT
# 
#     # We always at least fit within the chrom, which is bin 1.
#     bins = set([1])
# 
#     for offset in OFFSETS:
#         # Since we're going from smallest to largest bins, the first one where
#         # the feature's start and stop positions are both within the same bin
#         # is the smallest one these coords fit within.
#         if one:
#             if start == stop:
#                 # Note that at this point, because of the bit-shifting, `start`
#                 # is the number of bins (at this current level).  So we need to
#                 # add it to `offset` to get the actual bin ID.
#                 return offset + start
# 
#         # See the Fig 7 reproduction above to see why range().
#         bins.update(list(range(offset + start, offset + stop + 1)))
# 
#         # Move to the next level (8x larger bin size; i.e., 2**NEXT_SHIFT
#         # larger bin size)
#         start >>= NEXT_SHIFT
#         stop >>= NEXT_SHIFT
# 
#     return bins
# 
# Path: gffutils/gffwriter.py
# class GFFWriter:
#     def __init__(self, out, with_header=True, in_place=False):
#     def write_rec(self, rec):
#     def write_recs(self, recs):
#     def write_gene_recs(self, db, gene_id):
#     def write_mRNA_children(self, db, mRNA_id):
#     def write_exon_children(self, db, exon_id):
#     def close(self):
# 
# Path: gffutils/parser.py
# class Quoter(collections.defaultdict):
#     def __missing__(self, b):
# def _reconstruct(keyvals, dialect, keep_order=False,
#                  sort_attribute_values=False):
#     def sort_key(x):
# def _split_keyvals(keyval_str, dialect=None):
#     def _unquote_quals(quals, dialect):
# 
# Path: gffutils/attributes.py
# class Attributes(collectionsAbc.MutableMapping):
#     def __init__(self, *args, **kwargs):
#     def __setitem__(self, k, v):
#     def __getitem__(self, k):
#     def __delitem__(self, key):
#     def __iter__(self):
#     def __len__(self):
#     def keys(self):
#     def values(self):
#     def items(self):
#     def __str__(self):
#     def update(self, *args, **kwargs):


import copy
import sys
import os
import simplejson as json
import time
import tempfile
import six
import gffutils
    import pybedtools
    import pyfaidx
from gffutils import constants
from gffutils import bins
from gffutils import gffwriter
from gffutils import parser
from gffutils.attributes import dict_class
    try:
        start = int(d['start'])
        end = int(d['end'])
        return bins.bins(start, end, one=True)

    # e.g., if "."
    except ValueError:
        return None


def _jsonify(x):
    """Use most compact form of JSON"""
    if isinstance(x, dict_class):
        return json.dumps(x._d, separators=(',', ':'))
    return json.dumps(x, separators=(',', ':'))


def _unjsonify(x, isattributes=False):
    """Convert JSON string to an ordered defaultdict."""
    if isattributes:
        obj = json.loads(x)
        return dict_class(obj)
    return json.loads(x)


def _feature_to_fields(f, jsonify=True):
    """
    Convert feature to tuple, for faster sqlite3 import
    """
    x = []

# Path: gffutils/constants.py
# SCHEMA = """
# 
# CREATE TABLE features (
#     id text,
#     seqid text,
#     source text,
#     featuretype text,
#     start int,
#     end int,
#     score text,
#     strand text,
#     frame text,
#     attributes text,
#     extra text,
#     bin int,
#     primary key (id)
#     );
# 
# CREATE TABLE relations (
#     parent text,
#     child text,
#     level int,
#     primary key (parent, child, level)
#     );
# 
# CREATE TABLE meta (
#     dialect text,
#     version text
#     );
# 
# CREATE TABLE directives (
#     directive text
#     );
# 
# CREATE TABLE autoincrements (
#     base text,
#     n int,
#     primary key (base)
#     );
# 
# CREATE TABLE duplicates (
#     idspecid text,
#     newid text,
#     primary key (newid)
#     );
# 
# 
# """
# _SELECT = "SELECT " \
#     + ', '.join(_keys) \
#     + ", features.rowid as file_order FROM features "
# _INSERT = "INSERT INTO features (" \
#     + ', '.join(_keys) + ") VALUES (" + ','.join(list('?' * len(_keys))) + ")"
# _UPDATE = "UPDATE features SET " + _update_clause + " WHERE id = ?"
# INDEXES = []
# 
# Path: gffutils/bins.py
# def bins(start, stop, fmt='gff', one=True):
#     """
#     Uses the definition of a "genomic bin" described in Fig 7 of
#     http://genome.cshlp.org/content/12/6/996.abstract.
# 
#     Parameters
#     ----------
#     one : boolean
#         If `one=True` (default), then only return the smallest bin that
#         completely contains these coordinates (useful for assigning a single
#         bin).
# 
#         If `one=False`, then return the set of *all* bins that overlap these
#         coordinates (useful for looking for features that could intersect)
# 
#     fmt : 'gff' | 'bed'
#         This specifies 1-based start coords (gff) or 0-based start coords (bed)
#     """
# 
#     # For very large coordinates, return 1 which is "somewhere on the
#     # chromosome".
#     if start >= MAX_CHROM_SIZE or stop >= MAX_CHROM_SIZE:
#         if one:
#             return 1
#         else:
#             return set([1])
# 
#     # Jump to highest resolution bin that will fit these coords (depending on
#     # whether we have a BED or GFF-style coordinate).
#     #
#     # Some GFF files include negative coords, which will throw off this
#     # calculation.  If negative coords, then set the bin to the largest
#     # possible.
#     if start < 0:
#         if one:
#             return 1
#         else:
#             return set([1])
# 
#     if stop < 0:
#         if one:
#             return 1
#         else:
#             return set([1])
# 
#     start = (start - COORD_OFFSETS[fmt]) >> FIRST_SHIFT
#     stop = (stop) >> FIRST_SHIFT
# 
#     # We always at least fit within the chrom, which is bin 1.
#     bins = set([1])
# 
#     for offset in OFFSETS:
#         # Since we're going from smallest to largest bins, the first one where
#         # the feature's start and stop positions are both within the same bin
#         # is the smallest one these coords fit within.
#         if one:
#             if start == stop:
#                 # Note that at this point, because of the bit-shifting, `start`
#                 # is the number of bins (at this current level).  So we need to
#                 # add it to `offset` to get the actual bin ID.
#                 return offset + start
# 
#         # See the Fig 7 reproduction above to see why range().
#         bins.update(list(range(offset + start, offset + stop + 1)))
# 
#         # Move to the next level (8x larger bin size; i.e., 2**NEXT_SHIFT
#         # larger bin size)
#         start >>= NEXT_SHIFT
#         stop >>= NEXT_SHIFT
# 
#     return bins
# 
# Path: gffutils/gffwriter.py
# class GFFWriter:
#     def __init__(self, out, with_header=True, in_place=False):
#     def write_rec(self, rec):
#     def write_recs(self, recs):
#     def write_gene_recs(self, db, gene_id):
#     def write_mRNA_children(self, db, mRNA_id):
#     def write_exon_children(self, db, exon_id):
#     def close(self):
# 
# Path: gffutils/parser.py
# class Quoter(collections.defaultdict):
#     def __missing__(self, b):
# def _reconstruct(keyvals, dialect, keep_order=False,
#                  sort_attribute_values=False):
#     def sort_key(x):
# def _split_keyvals(keyval_str, dialect=None):
#     def _unquote_quals(quals, dialect):
# 
# Path: gffutils/attributes.py
# class Attributes(collectionsAbc.MutableMapping):
#     def __init__(self, *args, **kwargs):
#     def __setitem__(self, k, v):
#     def __getitem__(self, k):
#     def __delitem__(self, key):
#     def __iter__(self):
#     def __len__(self):
#     def keys(self):
#     def values(self):
#     def items(self):
#     def __str__(self):
#     def update(self, *args, **kwargs):


# Path: gffutils/helpers.py
import copy
import sys
import os
import simplejson as json
import time
import tempfile
import six
import gffutils
    import pybedtools
    import pyfaidx
from gffutils import constants
from gffutils import bins
from gffutils import gffwriter
from gffutils import parser
from gffutils.attributes import dict_class

    try:
        start = int(d['start'])
        end = int(d['end'])
        return bins.bins(start, end, one=True)

    # e.g., if "."
    except ValueError:
        return None


def _jsonify(x):
    """Use most compact form of JSON"""
    if isinstance(x, dict_class):
        return json.dumps(x._d, separators=(',', ':'))
    return json.dumps(x, separators=(',', ':'))


def _unjsonify(x, isattributes=False):
    """Convert JSON string to an ordered defaultdict."""
    if isattributes:
        obj = json.loads(x)
        return dict_class(obj)
    return json.loads(x)


def _feature_to_fields(f, jsonify=True):
    """
    Convert feature to tuple, for faster sqlite3 import
    """
    x = []

    for k in constants._keys: