def check_reference(self, sequence_region=False, fasta_embedded=False, fasta_external=False, check_bounds=True, check_n=True, allowed_num_of_n=<NUM_LIT:0>, feature_types=('<STR_LIT>',)):
<EOL>error_lines = set()<EOL>if not self.lines:<EOL><INDENT>self.logger.debug('<STR_LIT>')<EOL>return error_lines<EOL><DEDENT>check_n_feature_types = set(feature_types)<EOL>if len(check_n_feature_types) == <NUM_LIT:0>:<EOL><INDENT>check_n_feature_types.add('<STR_LIT>')<EOL><DEDENT>n_segments_finditer = re.compile(r'<STR_LIT>').finditer<EOL>check_all_sources = True<EOL>if sequence_region or fasta_embedded or fasta_external:<EOL><INDENT>check_all_sources = False<EOL><DEDENT>start_end_error_locations = set(('<STR_LIT:start>', '<STR_LIT:end>', '<STR_LIT>'))<EOL>valid_line_data_seqid = [(line_data, unquote(line_data['<STR_LIT>'])) for line_data in self.lines if line_data['<STR_LIT>'] == '<STR_LIT>' and line_data['<STR_LIT>'] != '<STR_LIT:.>' and (not line_data['<STR_LIT>'] or not [error_info for error_info in line_data['<STR_LIT>'] if '<STR_LIT:location>' in error_info and error_info['<STR_LIT:location>'] in start_end_error_locations])]<EOL>checked_at_least_one_source = False<EOL>valid_sequence_regions = dict([(unquote(line_data['<STR_LIT>']), line_data) for line_data in self.lines if line_data['<STR_LIT>'] == '<STR_LIT>' and not line_data['<STR_LIT>']])<EOL>unresolved_seqid = set()<EOL>if (check_all_sources or sequence_region) and valid_sequence_regions:<EOL><INDENT>checked_at_least_one_source = True<EOL>for line_data, seqid in valid_line_data_seqid:<EOL><INDENT>if seqid not in valid_sequence_regions and seqid not in unresolved_seqid:<EOL><INDENT>unresolved_seqid.add(seqid)<EOL>error_lines.add(line_data['<STR_LIT>'])<EOL>self.add_line_error(line_data, {'<STR_LIT:message>': u'<STR_LIT>'.format(<EOL>seqid), '<STR_LIT>': '<STR_LIT>', '<STR_LIT:location>': '<STR_LIT>'})<EOL>continue<EOL><DEDENT>if line_data['<STR_LIT:start>'] < valid_sequence_regions[seqid]['<STR_LIT:start>']:<EOL><INDENT>error_lines.add(line_data['<STR_LIT>'])<EOL>self.add_line_error(line_data, {'<STR_LIT:message>': '<STR_LIT>' % valid_sequence_regions[seqid]['<STR_LIT:start>'], '<STR_LIT>': '<STR_LIT>', '<STR_LIT:location>': '<STR_LIT>'})<EOL><DEDENT>if line_data['<STR_LIT:end>'] > valid_sequence_regions[seqid]['<STR_LIT:end>']:<EOL><INDENT>error_lines.add(line_data['<STR_LIT>'])<EOL>self.add_line_error(line_data, {'<STR_LIT:message>': '<STR_LIT>' % valid_sequence_regions[seqid]['<STR_LIT:end>'], '<STR_LIT>': '<STR_LIT>', '<STR_LIT:location>': '<STR_LIT>'})<EOL><DEDENT><DEDENT><DEDENT>elif sequence_region:<EOL><INDENT>self.logger.debug('<STR_LIT>')<EOL><DEDENT>unresolved_seqid = set()<EOL>if (check_all_sources or fasta_embedded) and self.fasta_embedded:<EOL><INDENT>checked_at_least_one_source = True<EOL>for line_data, seqid in valid_line_data_seqid:<EOL><INDENT>if seqid not in self.fasta_embedded and seqid not in unresolved_seqid:<EOL><INDENT>unresolved_seqid.add(seqid)<EOL>error_lines.add(line_data['<STR_LIT>'])<EOL>self.add_line_error(line_data, {'<STR_LIT:message>': '<STR_LIT>' % seqid, '<STR_LIT>': '<STR_LIT>', '<STR_LIT:location>': '<STR_LIT>'})<EOL>continue<EOL><DEDENT>if line_data['<STR_LIT:end>'] > len(self.fasta_embedded[seqid]['<STR_LIT>']):<EOL><INDENT>error_lines.add(line_data['<STR_LIT>'])<EOL>self.add_line_error(line_data, {'<STR_LIT:message>': '<STR_LIT>' % len(self.fasta_embedded[seqid]['<STR_LIT>']), '<STR_LIT>': '<STR_LIT>', '<STR_LIT:location>': '<STR_LIT>'})<EOL><DEDENT>if check_n and line_data['<STR_LIT:type>'] in check_n_feature_types:<EOL><INDENT>"""<STR_LIT>"""<EOL>n_count = self.fasta_embedded[seqid]['<STR_LIT>'].count('<STR_LIT:N>', line_data['<STR_LIT:start>'] - <NUM_LIT:1>, line_data['<STR_LIT:end>']) + self.fasta_embedded[seqid]['<STR_LIT>'].count('<STR_LIT:n>', line_data['<STR_LIT:start>'] - <NUM_LIT:1>, line_data['<STR_LIT:end>'])<EOL>if n_count > allowed_num_of_n:<EOL><INDENT>n_segments = [(m.start(), m.end() - m.start()) for m in n_segments_finditer(self.fasta_embedded[seqid]['<STR_LIT>'], line_data['<STR_LIT:start>'] - <NUM_LIT:1>, line_data['<STR_LIT:end>'])]<EOL>n_segments_str = ['<STR_LIT>' % (m[<NUM_LIT:0>], m[<NUM_LIT:1>]) for m in n_segments]<EOL>error_lines.add(line_data['<STR_LIT>'])<EOL>self.add_line_error(line_data, {'<STR_LIT:message>': '<STR_LIT>' % (n_count, line_data['<STR_LIT:type>'], line_data['<STR_LIT:end>'] - line_data['<STR_LIT:start>'], len(n_segments), '<STR_LIT:U+002CU+0020>'.join(n_segments_str)), '<STR_LIT>': '<STR_LIT>', '<STR_LIT>': n_segments, '<STR_LIT:location>': '<STR_LIT>'})<EOL><DEDENT><DEDENT><DEDENT><DEDENT>elif fasta_embedded:<EOL><INDENT>self.logger.debug('<STR_LIT>')<EOL><DEDENT>unresolved_seqid = set()<EOL>if (check_all_sources or fasta_external) and self.fasta_external:<EOL><INDENT>checked_at_least_one_source = True<EOL>for line_data, seqid in valid_line_data_seqid:<EOL><INDENT>if seqid not in self.fasta_external and seqid not in unresolved_seqid:<EOL><INDENT>unresolved_seqid.add(seqid)<EOL>error_lines.add(line_data['<STR_LIT>'])<EOL>self.add_line_error(line_data, {'<STR_LIT:message>': '<STR_LIT>' % seqid, '<STR_LIT>': '<STR_LIT>', '<STR_LIT:location>': '<STR_LIT>'})<EOL>continue<EOL><DEDENT>if line_data['<STR_LIT:end>'] > len(self.fasta_external[seqid]['<STR_LIT>']):<EOL><INDENT>error_lines.add(line_data['<STR_LIT>'])<EOL>self.add_line_error(line_data, {'<STR_LIT:message>': '<STR_LIT>' % len(self.fasta_external[seqid]['<STR_LIT>']), '<STR_LIT>': '<STR_LIT>', '<STR_LIT:location>': '<STR_LIT>'})<EOL><DEDENT>if check_n and line_data['<STR_LIT:type>'] in check_n_feature_types:<EOL><INDENT>n_count = self.fasta_external[seqid]['<STR_LIT>'].count('<STR_LIT:N>', line_data['<STR_LIT:start>'] - <NUM_LIT:1>, line_data['<STR_LIT:end>']) + self.fasta_external[seqid]['<STR_LIT>'].count('<STR_LIT:n>', line_data['<STR_LIT:start>'] - <NUM_LIT:1>, line_data['<STR_LIT:end>'])<EOL>if n_count > allowed_num_of_n:<EOL><INDENT>n_segments = [(m.start(), m.end() - m.start()) for m in n_segments_finditer(self.fasta_external[seqid]['<STR_LIT>'], line_data['<STR_LIT:start>'] - <NUM_LIT:1>, line_data['<STR_LIT:end>'])]<EOL>n_segments_str = ['<STR_LIT>' % (m[<NUM_LIT:0>], m[<NUM_LIT:1>]) for m in n_segments]<EOL>error_lines.add(line_data['<STR_LIT>'])<EOL>self.add_line_error(line_data, {'<STR_LIT:message>': '<STR_LIT>' % (n_count, line_data['<STR_LIT:type>'], line_data['<STR_LIT:end>'] - line_data['<STR_LIT:start>'], len(n_segments), '<STR_LIT:U+002CU+0020>'.join(n_segments_str)), '<STR_LIT>': '<STR_LIT>', '<STR_LIT>': n_segments, '<STR_LIT:location>': '<STR_LIT>'})<EOL><DEDENT><DEDENT><DEDENT><DEDENT>elif fasta_external:<EOL><INDENT>self.logger.debug('<STR_LIT>')<EOL><DEDENT>if check_all_sources and not checked_at_least_one_source:<EOL><INDENT>self.logger.debug('<STR_LIT>')<EOL><DEDENT>return error_lines<EOL>
Check seqid, bounds and the number of Ns in each feature using one or more reference sources.

Seqid check: check if the seqid can be found in the reference sources.

Bounds check: check the start and end fields of each features and log error if the values aren't within the seqid sequence length, requires at least one of these sources: ##sequence-region, embedded #FASTA, or external FASTA file.

Ns check: count the number of Ns in each feature with the type specified in *line_types (default: 'CDS') and log an error if the number is greater than allowed_num_of_n (default: 0), requires at least one of these sources: embedded #FASTA, or external FASTA file.

When called with all source parameters set as False (default), check all available sources, and log debug message if unable to perform a check due to none of the reference sources being available.

If any source parameter is set to True, check only those sources marked as True, log error if those sources don't exist.

:param sequence_region: check bounds using the ##sequence-region directive (default: False)
:param fasta_embedded: check bounds using the embedded fasta specified by the ##FASTA directive (default: False)
:param fasta_external: check bounds using the external fasta given by the self.parse_fasta_external (default: False)
:param check_bounds: If False, don't run the bounds check (default: True)
:param check_n: If False, don't run the Ns check (default: True)
:param allowed_num_of_n: only report features with a number of Ns greater than the specified value (default: 0)
:param feature_types: only check features of these feature_types, multiple types may be specified, if none are specified, check only 'CDS'
:return: error_lines: a set of line_index(int) with errors detected by check_reference