nodes: 0, module; 1, function_definition; 2, function_name:interfeatures; 3, parameters; 4, block; 5, identifier:self; 6, identifier:features; 7, default_parameter; 8, default_parameter; 9, default_parameter; 10, default_parameter; 11, default_parameter; 12, expression_statement; 13, for_statement; 14, identifier:new_featuretype; 15, None; 16, identifier:merge_attributes; 17, True; 18, identifier:dialect; 19, None; 20, identifier:attribute_func; 21, None; 22, identifier:update_attributes; 23, None; 24, comment:"""
          Construct new features representing the space between features.
  
          For example, if `features` is a list of exons, then this method will
          return the introns.  If `features` is a list of genes, then this method
          will return the intergenic regions.
  
          Providing N features will return N - 1 new features.
  
          This method purposefully does *not* do any merging or sorting of
          coordinates, so you may want to use :meth:`FeatureDB.merge` first, or
          when selecting features use the `order_by` kwarg, e.g.,
          `db.features_of_type('gene', order_by=('seqid', 'start'))`.
  
          Parameters
          ----------
          features : iterable of :class:`feature.Feature` instances
              Sorted, merged iterable
  
          new_featuretype : string or None
              The new features will all be of this type, or, if None (default)
              then the featuretypes will be constructed from the neighboring
              features, e.g., `inter_exon_exon`.
  
          merge_attributes : bool
              If True, new features' attributes will be a merge of the neighboring
              features' attributes.  This is useful if you have provided a list of
              exons; the introns will then retain the transcript and/or gene
              parents as a single item. Otherwise, if False, the attribute will
              be a comma-separated list of values, potentially listing the same
              gene ID twice.
  
          attribute_func : callable or None
              If None, then nothing special is done to the attributes.  If
              callable, then the callable accepts two attribute dictionaries and
              returns a single attribute dictionary.  If `merge_attributes` is
              True, then `attribute_func` is called before `merge_attributes`.
              This could be useful for manually managing IDs for the new
              features.
  
          update_attributes : dict
              After attributes have been modified and merged, this dictionary can
              be used to replace parts of the attributes dictionary.
  
          Returns
          -------
          A generator that yields :class:`Feature` objects
          """; 25, pattern_list; 26, call; 27, comment:# no inter-feature for the first one; 28, block; 29, identifier:i; 30, identifier:f; 31, identifier:enumerate; 32, argument_list; 33, if_statement; 34, expression_statement; 35, if_statement; 36, if_statement; 37, if_statement; 38, expression_statement; 39, expression_statement; 40, comment:# Shrink; 41, expression_statement; 42, expression_statement; 43, if_statement; 44, if_statement; 45, expression_statement; 46, expression_statement; 47, expression_statement; 48, if_statement; 49, expression_statement; 50, expression_statement; 51, identifier:features; 52, comparison_operator:i == 0; 53, block; 54, assignment; 55, comparison_operator:new_featuretype is None; 56, block; 57, comparison_operator:last_feature.strand != f.strand; 58, block; 59, else_clause; 60, comparison_operator:last_feature.chrom != f.chrom; 61, comment:# We've moved to a new chromosome.  For example, if we're; 62, comment:# getting intergenic regions from all genes, they will be on; 63, comment:# different chromosomes. We still assume sorted features, but; 64, comment:# don't complain if they're on different chromosomes -- just; 65, comment:# move on.; 66, block; 67, assignment; 68, assignment; 69, augmented_assignment; 70, augmented_assignment; 71, identifier:merge_attributes; 72, block; 73, else_clause; 74, identifier:update_attributes; 75, block; 76, assignment; 77, assignment; 78, assignment; 79, comparison_operator:dialect is None; 80, comment:# Support for @classmethod -- if calling from the class, then; 81, comment:# self.dialect is not defined, so defer to Feature's default; 82, comment:# (which will be constants.dialect, or GFF3).; 83, block; 84, yield; 85, assignment; 86, identifier:i; 87, integer:0; 88, expression_statement; 89, expression_statement; 90, continue_statement; 91, identifier:interfeature_stop; 92, attribute; 93, identifier:new_featuretype; 94, None; 95, expression_statement; 96, attribute; 97, attribute; 98, expression_statement; 99, block; 100, attribute; 101, attribute; 102, expression_statement; 103, continue_statement; 104, identifier:strand; 105, identifier:new_strand; 106, identifier:chrom; 107, attribute; 108, identifier:interfeature_start; 109, integer:1; 110, identifier:interfeature_stop; 111, integer:1; 112, expression_statement; 113, block; 114, expression_statement; 115, identifier:new_bin; 116, call; 117, identifier:_id; 118, None; 119, identifier:fields; 120, call; 121, identifier:dialect; 122, None; 123, try_statement; 124, call; 125, identifier:interfeature_start; 126, attribute; 127, assignment; 128, assignment; 129, identifier:f; 130, identifier:start; 131, assignment; 132, identifier:last_feature; 133, identifier:strand; 134, identifier:f; 135, identifier:strand; 136, assignment; 137, expression_statement; 138, identifier:last_feature; 139, identifier:chrom; 140, identifier:f; 141, identifier:chrom; 142, assignment; 143, identifier:last_feature; 144, identifier:chrom; 145, assignment; 146, expression_statement; 147, call; 148, attribute; 149, argument_list; 150, identifier:dict; 151, argument_list; 152, block; 153, except_clause; 154, attribute; 155, argument_list; 156, identifier:f; 157, identifier:stop; 158, identifier:interfeature_start; 159, attribute; 160, identifier:last_feature; 161, identifier:f; 162, identifier:new_featuretype; 163, binary_operator:'inter_%s_%s' % (
                      last_feature.featuretype, f.featuretype); 164, identifier:new_strand; 165, string; 166, assignment; 167, identifier:last_feature; 168, identifier:f; 169, identifier:new_attributes; 170, call; 171, assignment; 172, attribute; 173, argument_list; 174, identifier:bins; 175, identifier:bins; 176, identifier:interfeature_start; 177, identifier:interfeature_stop; 178, keyword_argument; 179, keyword_argument; 180, keyword_argument; 181, keyword_argument; 182, keyword_argument; 183, keyword_argument; 184, keyword_argument; 185, keyword_argument; 186, keyword_argument; 187, keyword_argument; 188, keyword_argument; 189, expression_statement; 190, identifier:AttributeError; 191, block; 192, identifier:self; 193, identifier:_feature_returner; 194, dictionary_splat; 195, identifier:f; 196, identifier:stop; 197, string; 198, tuple; 199, string_content:.; 200, identifier:new_strand; 201, attribute; 202, attribute; 203, argument_list; 204, identifier:new_attributes; 205, dictionary; 206, identifier:new_attributes; 207, identifier:update; 208, identifier:update_attributes; 209, identifier:one; 210, True; 211, identifier:seqid; 212, identifier:chrom; 213, identifier:source; 214, string; 215, identifier:featuretype; 216, identifier:new_featuretype; 217, identifier:start; 218, identifier:interfeature_start; 219, identifier:end; 220, identifier:interfeature_stop; 221, identifier:score; 222, string; 223, identifier:strand; 224, identifier:strand; 225, identifier:frame; 226, string; 227, identifier:attributes; 228, identifier:new_attributes; 229, identifier:bin; 230, identifier:new_bin; 231, assignment; 232, expression_statement; 233, identifier:fields; 234, string_content:inter_%s_%s; 235, attribute; 236, attribute; 237, identifier:f; 238, identifier:strand; 239, identifier:helpers; 240, identifier:merge_attributes; 241, attribute; 242, attribute; 243, string_content:gffutils_derived; 244, string_content:.; 245, string_content:.; 246, identifier:dialect; 247, attribute; 248, assignment; 249, identifier:last_feature; 250, identifier:featuretype; 251, identifier:f; 252, identifier:featuretype; 253, identifier:last_feature; 254, identifier:attributes; 255, identifier:f; 256, identifier:attributes; 257, identifier:self; 258, identifier:dialect; 259, identifier:dialect; 260, None
code: def interfeatures(self, features, new_featuretype=None,
                        merge_attributes=True, dialect=None,
                        attribute_func=None, update_attributes=None):
          """
          Construct new features representing the space between features.
  
          For example, if `features` is a list of exons, then this method will
          return the introns.  If `features` is a list of genes, then this method
          will return the intergenic regions.
  
          Providing N features will return N - 1 new features.
  
          This method purposefully does *not* do any merging or sorting of
          coordinates, so you may want to use :meth:`FeatureDB.merge` first, or
          when selecting features use the `order_by` kwarg, e.g.,
          `db.features_of_type('gene', order_by=('seqid', 'start'))`.
  
          Parameters
          ----------
          features : iterable of :class:`feature.Feature` instances
              Sorted, merged iterable
  
          new_featuretype : string or None
              The new features will all be of this type, or, if None (default)
              then the featuretypes will be constructed from the neighboring
              features, e.g., `inter_exon_exon`.
  
          merge_attributes : bool
              If True, new features' attributes will be a merge of the neighboring
              features' attributes.  This is useful if you have provided a list of
              exons; the introns will then retain the transcript and/or gene
              parents as a single item. Otherwise, if False, the attribute will
              be a comma-separated list of values, potentially listing the same
              gene ID twice.
  
          attribute_func : callable or None
              If None, then nothing special is done to the attributes.  If
              callable, then the callable accepts two attribute dictionaries and
              returns a single attribute dictionary.  If `merge_attributes` is
              True, then `attribute_func` is called before `merge_attributes`.
              This could be useful for manually managing IDs for the new
              features.
  
          update_attributes : dict
              After attributes have been modified and merged, this dictionary can
              be used to replace parts of the attributes dictionary.
  
          Returns
          -------
          A generator that yields :class:`Feature` objects
          """
          for i, f in enumerate(features):
              # no inter-feature for the first one
              if i == 0:
                  interfeature_start = f.stop
                  last_feature = f
                  continue
  
              interfeature_stop = f.start
              if new_featuretype is None:
                  new_featuretype = 'inter_%s_%s' % (
                      last_feature.featuretype, f.featuretype)
              if last_feature.strand != f.strand:
                  new_strand = '.'
              else:
                  new_strand = f.strand
  
              if last_feature.chrom != f.chrom:
                  # We've moved to a new chromosome.  For example, if we're
                  # getting intergenic regions from all genes, they will be on
                  # different chromosomes. We still assume sorted features, but
                  # don't complain if they're on different chromosomes -- just
                  # move on.
                  last_feature = f
                  continue
  
              strand = new_strand
              chrom = last_feature.chrom
  
              # Shrink
              interfeature_start += 1
              interfeature_stop -= 1
  
              if merge_attributes:
                  new_attributes = helpers.merge_attributes(
                      last_feature.attributes, f.attributes)
              else:
                  new_attributes = {}
  
              if update_attributes:
                  new_attributes.update(update_attributes)
  
              new_bin = bins.bins(
                  interfeature_start, interfeature_stop, one=True)
              _id = None
              fields = dict(
                  seqid=chrom,
                  source='gffutils_derived',
                  featuretype=new_featuretype,
                  start=interfeature_start,
                  end=interfeature_stop,
                  score='.',
                  strand=strand,
                  frame='.',
                  attributes=new_attributes,
                  bin=new_bin)
  
              if dialect is None:
                  # Support for @classmethod -- if calling from the class, then
                  # self.dialect is not defined, so defer to Feature's default
                  # (which will be constants.dialect, or GFF3).
                  try:
                      dialect = self.dialect
                  except AttributeError:
                      dialect = None
              yield self._feature_returner(**fields)
              interfeature_start = f.stop