def __init__(self, filename, fast_filter=None, info_delimiter='<STR_LIT:;>', key_delimiter='<STR_LIT:=>', quotechar='<STR_LIT>',<EOL>tag_map={'<STR_LIT>': '<STR_LIT>', '<STR_LIT>': '<STR_LIT>'}, preset=None):
super(GFFReader, self).__init__(filename)<EOL>self.positions = {}<EOL>self.fast_attributes = {}<EOL>self.filters = set(fast_filter) if fast_filter else []<EOL>GFF_TAGS = copy.deepcopy(config.GFF_TAGS)<EOL>self.feature_map = {}<EOL>child_list = []<EOL>if preset and preset.lower() == '<STR_LIT>':<EOL><INDENT>key_delimiter='<STR_LIT:U+0020>'<EOL>quotechar='<STR_LIT:">'<EOL>self.id_tag = '<STR_LIT>'<EOL>self.parent_tag = '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>self.id_tag = tag_map['<STR_LIT>']<EOL>self.parent_tag = tag_map['<STR_LIT>']<EOL><DEDENT>GFF_TAGS.add(self.id_tag)<EOL>GFF_TAGS.add(self.parent_tag)<EOL>for gff_object in GFFIterator(filename, info_delimiter=info_delimiter,<EOL>key_delimiter=key_delimiter, quotechar=quotechar):<EOL><INDENT>chrom, start, end = gff_object.seqid, int(gff_object.start), int(gff_object.end)<EOL>try:<EOL><INDENT>self.positions[chrom][(start, end)].append(gff_object)<EOL><DEDENT>except KeyError:<EOL><INDENT>try:<EOL><INDENT>self.positions[chrom][(start, end)] = [gff_object]<EOL><DEDENT>except KeyError:<EOL><INDENT>self.positions[chrom] = {(start, end): [gff_object]}<EOL><DEDENT><DEDENT>fast_lookup = [fast_access for fast_access in self.filters for attribute in gff_object.attributes if fast_access in attribute]<EOL>for fast_access in fast_lookup:<EOL><INDENT>try:<EOL><INDENT>self.fast_attributes[fast_access].append(gff_object)<EOL><DEDENT>except KeyError:<EOL><INDENT>self.fast_attributes[fast_access] = [gff_object]<EOL><DEDENT><DEDENT>known_tags = set([attribute for attribute in gff_object.attributes if attribute in GFF_TAGS])<EOL>if self.id_tag in known_tags:<EOL><INDENT>gff_id = gff_object.attributes.get(self.id_tag, None)<EOL>if gff_id:<EOL><INDENT>try:<EOL><INDENT>gff_feature = self.feature_map[gff_id]<EOL><DEDENT>except KeyError:<EOL><INDENT>gff_feature = structure.GFFFeature(gff_id)<EOL>self.feature_map[gff_id] = gff_feature<EOL><DEDENT>gff_feature.features.add(gff_object)<EOL>if self.parent_tag in known_tags:<EOL><INDENT>child_list.append(gff_object)<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>gff_id = str(len(self.feature_map))<EOL>gff_feature = structure.GFFFeature(gff_id)<EOL>gff_feature.features.add(gff_object)<EOL>self.feature_map[gff_id] = gff_feature<EOL><DEDENT><DEDENT>for child_gff_object in child_list:<EOL><INDENT>parent_ids = child_gff_object.attributes[self.parent_tag].split('<STR_LIT:U+002C>')<EOL>for parent_id in parent_ids:<EOL><INDENT>parent_feature = self.feature_map.get(parent_id, None)<EOL>if not parent_feature:<EOL><INDENT>parent_feature = structure.GFFFeature(parent_id)<EOL>self.feature_map[parent_id] = parent_feature<EOL>sys.stderr.write('<STR_LIT>' % parent_id)<EOL><DEDENT>parent_feature.add_child(self.feature_map.get(child_gff_object.attributes.get(self.id_tag, None)))<EOL><DEDENT><DEDENT>
This will read an entire GFF/GTF/GFF3 file and establish parent-child relations and
         allow for querying based on attributes such as transcripts, gene ids, and allow writing
         of useful file types such as fasta files of coding sequences, etc. It works at the
         "feature" level, which allows for grouping of exons of a gene and so on.

         The implementation is liberal because GFF/GFF3/GTF standards are so poorly followed. So
         errors such as a missing parent feature will be reported, but not break usage.

        :param filename: GFF file to read
        :param fast_filter: A list of attributes to keep in memory a reference to for fast querying
        :param info_delimiter: The character to split the info field on (default: ";")
        :param key_delimiter: The character to split the key-value pairings of the info field on (default: "=")
        :param quotechar: The character surrounding values in the info field (default: None)
        :param tag_map: A dictionary which can substitute the ID and Parent tags for alternatives
        :param preset: A string identifying various presets (choices: cufflinks)