# Path: unicycler/misc.py
# def reverse_complement(seq):
#     """
#     Given a DNA sequences, this function returns the reverse complement sequence.
#     """
#     return ''.join([complement_base(x) for x in seq][::-1])
# 
# def add_line_breaks_to_sequence(sequence, line_length=0):
#     """
#     Wraps sequences to the defined length.  All resulting sequences end in a line break.
#     """
#     if not sequence:
#         return '\n'
#     if line_length <= 0:
#         line_length = settings.BASES_PER_FASTA_LINE
#     seq_with_breaks = ''
#     pos = 0
#     while pos < len(sequence):
#         seq_with_breaks += sequence[pos:pos+line_length] + '\n'
#         pos += line_length
#     return seq_with_breaks
# 
# def get_right_arrow():
#     """
#     This function returns either a Unicode right arrow or '->', depending on the system encoding.
#     """
#     try:
#         '\u2192'.encode(sys.stdout.encoding)
#     except (AttributeError, UnicodeEncodeError):
#         return '->'
#     else:
#         return '\u2192'
# 
# def bold(text):
#     return BOLD + text + END_FORMATTING
# 
# def load_fasta(filename):
#     """
#     Returns a list of tuples (name, seq) for each record in the fasta file.
#     """
#     fasta_seqs = []
#     open_func = get_open_function(filename)
#     with open_func(filename, 'rt') as fasta_file:
#         name = ''
#         sequence = ''
#         for line in fasta_file:
#             line = line.strip()
#             if not line:
#                 continue
#             if line[0] == '>':  # Header line = start of new contig
#                 if name:
#                     fasta_seqs.append((name.split()[0], sequence))
#                     sequence = ''
#                 name = line[1:]
#             else:
#                 sequence += line
#         if name:
#             fasta_seqs.append((name.split()[0], sequence))
#     return fasta_seqs
# 
# def load_fasta_with_full_header(filename):
#     """
#     Returns a list of tuples (name, header, seq) for each record in the fasta file.
#     """
#     fasta_seqs = []
#     open_func = get_open_function(filename)
#     with open_func(filename, 'rt') as fasta_file:
#         name = ''
#         sequence = ''
#         for line in fasta_file:
#             line = line.strip()
#             if not line:
#                 continue
#             if line[0] == '>':  # Header line = start of new contig
#                 if name:
#                     fasta_seqs.append((name.split()[0], name, sequence))
#                     sequence = ''
#                 name = line[1:]
#             else:
#                 sequence += line
#         if name:
#             fasta_seqs.append((name.split()[0], name, sequence))
#     return fasta_seqs
# 
# def get_first_character_of_file(filename):
#     open_func = get_open_function(filename)
#     with open_func(filename, 'r') as f:
#         first_line = f.readline()
#         try:
#             return first_line[0]
#         except IndexError:
#             return ''
# 
# Path: unicycler/assembly_graph.py
# def build_reverse_links(links):
#     """
#     This function builds a dictionary of links going the other way.  I.e. if given a dictionary
#     of start to end links, it will return a dictionary of end to start links.
#     """
#     reverse_links = {}
#     for start, ends in links.items():
#         for end in ends:
#             if end not in reverse_links:
#                 reverse_links[end] = []
#             reverse_links[end].append(start)
#     return reverse_links


import sys
import re
from collections import deque, defaultdict
from .misc import reverse_complement, add_line_breaks_to_sequence, get_right_arrow, bold, \
    load_fasta, load_fasta_with_full_header, get_first_character_of_file
from .assembly_graph import build_reverse_links
from . import settings
from . import log
    from .cpp_wrappers import semi_global_alignment_exhaustive
                start_seg_name = segments_with_dead_ends[1]

        # Now we can build the unitig sequence by following the graph outward from the starting
        # segment, always trimming overlaps from the end of segments.
        unitig_seq = ''
        current_seg = start_seg_name
        name_list = []
        while True:
            name_list.append(get_string_graph_segment_nickname(current_seg, read_nicknames))
            current_seq = string_graph.seq_from_signed_seg_name(current_seg)
            next_seg = string_graph.get_following_segments(current_seg)
            if circular:
                assert len(next_seg) == 1  # no dead ends in circular unitigs
            if len(next_seg) == 0:  # no next segment means we've hit the end of a linear unitig
                unitig_seq += current_seq
                break
            else:
                assert len(next_seg) == 1
                overlap = string_graph.links[(current_seg, next_seg[0])].seg_1_overlap
                if overlap == 0:  # I don't think this will happen...
                    unitig_seq += current_seq
                else:
                    unitig_seq += current_seq[:-overlap]
            if circular and next_seg[0] == start_seg_name:  # don't loop endlessly in a circle
                break
            current_seg = next_seg[0]

        arrow = ' ' + get_right_arrow() + ' '
        if circular:
            unitig_sequences.append((unitig_seq, 'circular'))

# Path: unicycler/misc.py
# def reverse_complement(seq):
#     """
#     Given a DNA sequences, this function returns the reverse complement sequence.
#     """
#     return ''.join([complement_base(x) for x in seq][::-1])
# 
# def add_line_breaks_to_sequence(sequence, line_length=0):
#     """
#     Wraps sequences to the defined length.  All resulting sequences end in a line break.
#     """
#     if not sequence:
#         return '\n'
#     if line_length <= 0:
#         line_length = settings.BASES_PER_FASTA_LINE
#     seq_with_breaks = ''
#     pos = 0
#     while pos < len(sequence):
#         seq_with_breaks += sequence[pos:pos+line_length] + '\n'
#         pos += line_length
#     return seq_with_breaks
# 
# def get_right_arrow():
#     """
#     This function returns either a Unicode right arrow or '->', depending on the system encoding.
#     """
#     try:
#         '\u2192'.encode(sys.stdout.encoding)
#     except (AttributeError, UnicodeEncodeError):
#         return '->'
#     else:
#         return '\u2192'
# 
# def bold(text):
#     return BOLD + text + END_FORMATTING
# 
# def load_fasta(filename):
#     """
#     Returns a list of tuples (name, seq) for each record in the fasta file.
#     """
#     fasta_seqs = []
#     open_func = get_open_function(filename)
#     with open_func(filename, 'rt') as fasta_file:
#         name = ''
#         sequence = ''
#         for line in fasta_file:
#             line = line.strip()
#             if not line:
#                 continue
#             if line[0] == '>':  # Header line = start of new contig
#                 if name:
#                     fasta_seqs.append((name.split()[0], sequence))
#                     sequence = ''
#                 name = line[1:]
#             else:
#                 sequence += line
#         if name:
#             fasta_seqs.append((name.split()[0], sequence))
#     return fasta_seqs
# 
# def load_fasta_with_full_header(filename):
#     """
#     Returns a list of tuples (name, header, seq) for each record in the fasta file.
#     """
#     fasta_seqs = []
#     open_func = get_open_function(filename)
#     with open_func(filename, 'rt') as fasta_file:
#         name = ''
#         sequence = ''
#         for line in fasta_file:
#             line = line.strip()
#             if not line:
#                 continue
#             if line[0] == '>':  # Header line = start of new contig
#                 if name:
#                     fasta_seqs.append((name.split()[0], name, sequence))
#                     sequence = ''
#                 name = line[1:]
#             else:
#                 sequence += line
#         if name:
#             fasta_seqs.append((name.split()[0], name, sequence))
#     return fasta_seqs
# 
# def get_first_character_of_file(filename):
#     open_func = get_open_function(filename)
#     with open_func(filename, 'r') as f:
#         first_line = f.readline()
#         try:
#             return first_line[0]
#         except IndexError:
#             return ''
# 
# Path: unicycler/assembly_graph.py
# def build_reverse_links(links):
#     """
#     This function builds a dictionary of links going the other way.  I.e. if given a dictionary
#     of start to end links, it will return a dictionary of end to start links.
#     """
#     reverse_links = {}
#     for start, ends in links.items():
#         for end in ends:
#             if end not in reverse_links:
#                 reverse_links[end] = []
#             reverse_links[end].append(start)
#     return reverse_links


# Path: unicycler/string_graph.py
import sys
import re
from collections import deque, defaultdict
from .misc import reverse_complement, add_line_breaks_to_sequence, get_right_arrow, bold, \
    load_fasta, load_fasta_with_full_header, get_first_character_of_file
from .assembly_graph import build_reverse_links
from . import settings
from . import log
    from .cpp_wrappers import semi_global_alignment_exhaustive

                start_seg_name = segments_with_dead_ends[1]

        # Now we can build the unitig sequence by following the graph outward from the starting
        # segment, always trimming overlaps from the end of segments.
        unitig_seq = ''
        current_seg = start_seg_name
        name_list = []
        while True:
            name_list.append(get_string_graph_segment_nickname(current_seg, read_nicknames))
            current_seq = string_graph.seq_from_signed_seg_name(current_seg)
            next_seg = string_graph.get_following_segments(current_seg)
            if circular:
                assert len(next_seg) == 1  # no dead ends in circular unitigs
            if len(next_seg) == 0:  # no next segment means we've hit the end of a linear unitig
                unitig_seq += current_seq
                break
            else:
                assert len(next_seg) == 1
                overlap = string_graph.links[(current_seg, next_seg[0])].seg_1_overlap
                if overlap == 0:  # I don't think this will happen...
                    unitig_seq += current_seq
                else:
                    unitig_seq += current_seq[:-overlap]
            if circular and next_seg[0] == start_seg_name:  # don't loop endlessly in a circle
                break
            current_seg = next_seg[0]

        arrow = ' ' + get_right_arrow() + ' '
        if circular:
            unitig_sequences.append((unitig_seq, 'circular'))

            log.log(bold('Circular unitig: ') + arrow.join(name_list), verbosity=2)