# Path: augur/utils.py
# def read_tree(fname, min_terminals=3):
#     """Safely load a tree from a given filename or raise an error if the file does
#     not contain a valid tree.
# 
#     Parameters
#     ----------
#     fname : str
#         name of a file containing a phylogenetic tree
# 
#     min_terminals : int
#         minimum number of terminals required for the parsed tree as a sanity
#         check on the tree
# 
#     Raises
#     ------
#     InvalidTreeError
#         If the given file exists but does not seem to contain a valid tree format.
# 
#     Returns
#     -------
#     Bio.Phylo :
#         BioPython tree instance
# 
#     """
#     T = None
#     supported_tree_formats = ["newick", "nexus"]
#     for fmt in supported_tree_formats:
#         try:
#             T = Bio.Phylo.read(fname, fmt)
# 
#             # Check the sanity of the parsed tree to handle cases when non-tree
#             # data are still successfully parsed by BioPython. Too few terminals
#             # in a tree indicates that the input is not valid.
#             if T.count_terminals() < min_terminals:
#                 T = None
#             else:
#                 break
#         except ValueError:
#             # We cannot open the tree in the current format, so we will try
#             # another.
#             pass
# 
#     # If the tree cannot be loaded, raise an error to that effect.
#     if T is None:
#         raise InvalidTreeError(
#             "Could not read the given tree %s using the following supported formats: %s" % (fname, ", ".join(supported_tree_formats))
#         )
# 
#     return T
# 
# class InvalidTreeError(Exception):
#     """Represents an error loading a phylogenetic tree from a filename.
#     """
#     pass
# 
# def write_json(data, file_name, indent=(None if os.environ.get("AUGUR_MINIFY_JSON") else 2), include_version=True):
#     """
#     Write ``data`` as JSON to the given ``file_name``, creating parent directories
#     if necessary. The augur version is included as a top-level key "augur_version".
# 
#     Parameters
#     ----------
#     data : dict
#         data to write out to JSON
#     file_name : str
#         file name to write to
#     indent : int or None, optional
#         JSON indentation level. Default is `None` if the environment variable `AUGUR_MINIFY_JSON`
#         is truthy, else 1
#     include_version : bool, optional
#         Include the augur version. Default: `True`.
# 
#     Raises
#     ------
#     OSError
#     """
#     #in case parent folder does not exist yet
#     parent_directory = os.path.dirname(file_name)
#     if parent_directory and not os.path.exists(parent_directory):
#         try:
#             os.makedirs(parent_directory)
#         except OSError: #Guard against race condition
#             if not os.path.isdir(parent_directory):
#                 raise
# 
#     if include_version:
#         data["generated_by"] = {"program": "augur", "version": get_augur_version()}
# 
#     with open(file_name, 'w', encoding='utf-8') as handle:
#         json.dump(data, handle, indent=indent, sort_keys=True)
# 
# def get_json_name(args, default=None):
#     if args.output_node_data:
#         return args.output_node_data
#     else:
#         if default:
#             print("WARNING: no name for the output file was specified. Writing results to %s."%default, file=sys.stderr)
#             return default
#         else:
#             raise ValueError("Please specify a name for the JSON file containing the results.")


import os, shutil, time, json, sys
import numpy as np
    import numpy as np
    import treetime
from Bio import Phylo, SeqIO
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
from .utils import read_tree, InvalidTreeError, write_json, get_json_name
from treetime.vcf_utils import read_vcf, write_vcf
from collections import defaultdict
    from treetime import TreeAnc, version as treetime_version
    from distutils.version import StrictVersion
            except:
                print("No sequence available for node ",n.name)

    return {"nodes": data, "mask": mask}


def register_arguments(parser):
    parser.add_argument('--tree', '-t', required=True, help="prebuilt Newick")
    parser.add_argument('--alignment', '-a', help="alignment in fasta or VCF format")
    parser.add_argument('--output-node-data', type=str, help='name of JSON file to save mutations and ancestral sequences to')
    parser.add_argument('--output-sequences', type=str, help='name of FASTA file to save ancestral sequences to (FASTA alignments only)')
    parser.add_argument('--inference', default='joint', choices=["joint", "marginal"],
                                    help="calculate joint or marginal maximum likelihood ancestral sequence states")
    parser.add_argument('--vcf-reference', type=str, help='fasta file of the sequence the VCF was mapped to')
    parser.add_argument('--output-vcf', type=str, help='name of output VCF file which will include ancestral seqs')
    ambiguous = parser.add_mutually_exclusive_group()
    ambiguous.add_argument('--keep-ambiguous', action="store_true",
                                help='do not infer nucleotides at ambiguous (N) sites on tip sequences (leave as N).')
    ambiguous.add_argument('--infer-ambiguous', action="store_true", default=True,
                                help='infer nucleotides at ambiguous (N,W,R,..) sites on tip sequences and replace with most likely state.')
    parser.add_argument('--keep-overhangs', action="store_true", default=False,
                                help='do not infer nucleotides for gaps (-) on either side of the alignment')

def run(args):
    # check alignment type, set flags, read in if VCF
    is_vcf = False
    ref = None
    anc_seqs = {}

    try:

# Path: augur/utils.py
# def read_tree(fname, min_terminals=3):
#     """Safely load a tree from a given filename or raise an error if the file does
#     not contain a valid tree.
# 
#     Parameters
#     ----------
#     fname : str
#         name of a file containing a phylogenetic tree
# 
#     min_terminals : int
#         minimum number of terminals required for the parsed tree as a sanity
#         check on the tree
# 
#     Raises
#     ------
#     InvalidTreeError
#         If the given file exists but does not seem to contain a valid tree format.
# 
#     Returns
#     -------
#     Bio.Phylo :
#         BioPython tree instance
# 
#     """
#     T = None
#     supported_tree_formats = ["newick", "nexus"]
#     for fmt in supported_tree_formats:
#         try:
#             T = Bio.Phylo.read(fname, fmt)
# 
#             # Check the sanity of the parsed tree to handle cases when non-tree
#             # data are still successfully parsed by BioPython. Too few terminals
#             # in a tree indicates that the input is not valid.
#             if T.count_terminals() < min_terminals:
#                 T = None
#             else:
#                 break
#         except ValueError:
#             # We cannot open the tree in the current format, so we will try
#             # another.
#             pass
# 
#     # If the tree cannot be loaded, raise an error to that effect.
#     if T is None:
#         raise InvalidTreeError(
#             "Could not read the given tree %s using the following supported formats: %s" % (fname, ", ".join(supported_tree_formats))
#         )
# 
#     return T
# 
# class InvalidTreeError(Exception):
#     """Represents an error loading a phylogenetic tree from a filename.
#     """
#     pass
# 
# def write_json(data, file_name, indent=(None if os.environ.get("AUGUR_MINIFY_JSON") else 2), include_version=True):
#     """
#     Write ``data`` as JSON to the given ``file_name``, creating parent directories
#     if necessary. The augur version is included as a top-level key "augur_version".
# 
#     Parameters
#     ----------
#     data : dict
#         data to write out to JSON
#     file_name : str
#         file name to write to
#     indent : int or None, optional
#         JSON indentation level. Default is `None` if the environment variable `AUGUR_MINIFY_JSON`
#         is truthy, else 1
#     include_version : bool, optional
#         Include the augur version. Default: `True`.
# 
#     Raises
#     ------
#     OSError
#     """
#     #in case parent folder does not exist yet
#     parent_directory = os.path.dirname(file_name)
#     if parent_directory and not os.path.exists(parent_directory):
#         try:
#             os.makedirs(parent_directory)
#         except OSError: #Guard against race condition
#             if not os.path.isdir(parent_directory):
#                 raise
# 
#     if include_version:
#         data["generated_by"] = {"program": "augur", "version": get_augur_version()}
# 
#     with open(file_name, 'w', encoding='utf-8') as handle:
#         json.dump(data, handle, indent=indent, sort_keys=True)
# 
# def get_json_name(args, default=None):
#     if args.output_node_data:
#         return args.output_node_data
#     else:
#         if default:
#             print("WARNING: no name for the output file was specified. Writing results to %s."%default, file=sys.stderr)
#             return default
#         else:
#             raise ValueError("Please specify a name for the JSON file containing the results.")


# Path: augur/ancestral.py
import os, shutil, time, json, sys
import numpy as np
    import numpy as np
    import treetime
from Bio import Phylo, SeqIO
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
from .utils import read_tree, InvalidTreeError, write_json, get_json_name
from treetime.vcf_utils import read_vcf, write_vcf
from collections import defaultdict
    from treetime import TreeAnc, version as treetime_version
    from distutils.version import StrictVersion

            except:
                print("No sequence available for node ",n.name)

    return {"nodes": data, "mask": mask}


def register_arguments(parser):
    parser.add_argument('--tree', '-t', required=True, help="prebuilt Newick")
    parser.add_argument('--alignment', '-a', help="alignment in fasta or VCF format")
    parser.add_argument('--output-node-data', type=str, help='name of JSON file to save mutations and ancestral sequences to')
    parser.add_argument('--output-sequences', type=str, help='name of FASTA file to save ancestral sequences to (FASTA alignments only)')
    parser.add_argument('--inference', default='joint', choices=["joint", "marginal"],
                                    help="calculate joint or marginal maximum likelihood ancestral sequence states")
    parser.add_argument('--vcf-reference', type=str, help='fasta file of the sequence the VCF was mapped to')
    parser.add_argument('--output-vcf', type=str, help='name of output VCF file which will include ancestral seqs')
    ambiguous = parser.add_mutually_exclusive_group()
    ambiguous.add_argument('--keep-ambiguous', action="store_true",
                                help='do not infer nucleotides at ambiguous (N) sites on tip sequences (leave as N).')
    ambiguous.add_argument('--infer-ambiguous', action="store_true", default=True,
                                help='infer nucleotides at ambiguous (N,W,R,..) sites on tip sequences and replace with most likely state.')
    parser.add_argument('--keep-overhangs', action="store_true", default=False,
                                help='do not infer nucleotides for gaps (-) on either side of the alignment')

def run(args):
    # check alignment type, set flags, read in if VCF
    is_vcf = False
    ref = None
    anc_seqs = {}

    try:

        T = read_tree(args.tree)