# Path: augur/reconstruct_sequences.py
# def load_alignments(sequence_files, gene_names):
#     from Bio import AlignIO
#     alignments = {}
#     for fname, gene in zip(sequence_files, gene_names):
#         alignments[gene] = AlignIO.read(fname, 'fasta')
#     return alignments
# 
# Path: augur/titer_model.py
# class InsufficientDataException(Exception):
#     pass
# 
# Path: augur/utils.py
# def read_metadata(fname, query=None, as_data_frame=False):
#     return MetadataFile(fname, query, as_data_frame).read()
# 
# def read_node_data(fnames, tree=None):
#     return NodeDataReader(fnames, tree).read()
# 
# 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)


import json, os, sys
import numpy as np
from collections import defaultdict
from Bio import Phylo
from .reconstruct_sequences import load_alignments
from .titer_model import InsufficientDataException
from .utils import read_metadata, read_node_data, write_json
    from . import add_default_command
        from .titer_model import SubstitutionModel
        from .titer_model import TreeModel
    tree_model.set_defaults(
        __command__ = infer_tree_model
    )

    sub_model = subparsers.add_parser('sub', help='substitution model')
    sub_model.add_argument('--titers', nargs='+', type=str, required=True, help="file with titer measurements")
    sub_model.add_argument('--alignment', nargs='+', type=str, required=True, help="sequence to be used in the substitution model, supplied as fasta files")
    sub_model.add_argument('--gene-names', nargs='+', type=str, required=True, help="names of the sequences in the alignment, same order assumed")
    sub_model.add_argument('--tree', '-t', type=str, help="optional tree to annotate fit titer model to")
    sub_model.add_argument('--allow-empty-model', action="store_true", help="allow model to be empty")
    sub_model.add_argument('--output', '-o', type=str, required=True, help='JSON file to save titer model')
    sub_model.set_defaults(
        __command__ = infer_substitution_model
    )


class infer_substitution_model():
    def run(args):
        alignments = load_alignments(args.alignment, args.gene_names)

        TM_subs = SubstitutionModel(alignments, args.titers)
        try:

            TM_subs.prepare()
            TM_subs.train()

            subs_model = {'titers':TM_subs.compile_titers(),
                      'potency':TM_subs.compile_potencies(),
                      'avidity':TM_subs.compile_virus_effects(),
                      'substitution':TM_subs.compile_substitution_effects()}

# Path: augur/reconstruct_sequences.py
# def load_alignments(sequence_files, gene_names):
#     from Bio import AlignIO
#     alignments = {}
#     for fname, gene in zip(sequence_files, gene_names):
#         alignments[gene] = AlignIO.read(fname, 'fasta')
#     return alignments
# 
# Path: augur/titer_model.py
# class InsufficientDataException(Exception):
#     pass
# 
# Path: augur/utils.py
# def read_metadata(fname, query=None, as_data_frame=False):
#     return MetadataFile(fname, query, as_data_frame).read()
# 
# def read_node_data(fnames, tree=None):
#     return NodeDataReader(fnames, tree).read()
# 
# 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)


# Path: augur/titers.py
import json, os, sys
import numpy as np
from collections import defaultdict
from Bio import Phylo
from .reconstruct_sequences import load_alignments
from .titer_model import InsufficientDataException
from .utils import read_metadata, read_node_data, write_json
    from . import add_default_command
        from .titer_model import SubstitutionModel
        from .titer_model import TreeModel

    tree_model.set_defaults(
        __command__ = infer_tree_model
    )

    sub_model = subparsers.add_parser('sub', help='substitution model')
    sub_model.add_argument('--titers', nargs='+', type=str, required=True, help="file with titer measurements")
    sub_model.add_argument('--alignment', nargs='+', type=str, required=True, help="sequence to be used in the substitution model, supplied as fasta files")
    sub_model.add_argument('--gene-names', nargs='+', type=str, required=True, help="names of the sequences in the alignment, same order assumed")
    sub_model.add_argument('--tree', '-t', type=str, help="optional tree to annotate fit titer model to")
    sub_model.add_argument('--allow-empty-model', action="store_true", help="allow model to be empty")
    sub_model.add_argument('--output', '-o', type=str, required=True, help='JSON file to save titer model')
    sub_model.set_defaults(
        __command__ = infer_substitution_model
    )


class infer_substitution_model():
    def run(args):
        alignments = load_alignments(args.alignment, args.gene_names)

        TM_subs = SubstitutionModel(alignments, args.titers)
        try:

            TM_subs.prepare()
            TM_subs.train()

            subs_model = {'titers':TM_subs.compile_titers(),
                      'potency':TM_subs.compile_potencies(),
                      'avidity':TM_subs.compile_virus_effects(),
                      'substitution':TM_subs.compile_substitution_effects()}

        except InsufficientDataException: