import sys

# Try to load one of the humann modules to check the installation
try:
    from . import check
except ImportError:
    sys.exit("CRITICAL ERROR: Unable to find the HUMAnN python package." +
        " Please check your install.")

# Check the python version
check.python_version()

import argparse
import subprocess
import os
import time
import tempfile
import re
import logging

from . import config
from . import store
from . import utilities
from .search import prescreen
from .search import nucleotide
from .search import translated
from .quantify import families
from .quantify import modules

# name global logging instance
logger=logging.getLogger(__name__)

VERSION="4.0"

MAX_SIZE_DEMO_INPUT_FILE=35

def parse_arguments(args):
    """
    Parse the arguments from the user
    """
    parser = argparse.ArgumentParser(
        description= "HUMAnN : HMP Unified Metabolic Analysis Network 3\n",
        formatter_class=argparse.RawTextHelpFormatter,
        prog="humann")

    common_settings=parser.add_argument_group("[0] Common settings")

    common_settings.add_argument(
        "-i", "--input",
        help="input file of type {" +",".join(config.input_format_choices)+ "} \n[REQUIRED]",
        metavar="<input.fastq>",
        required=True)
    common_settings.add_argument(
        "-o", "--output",
        help="directory to write output files\n[REQUIRED]",
        metavar="<output>",
        required=True)
    common_settings.add_argument(
        "--threads",
        help="number of threads/processes\n[DEFAULT: " + str(config.threads) + "]",
        metavar="<" + str(config.threads) + ">",
        type=int,
        default=config.threads)
    common_settings.add_argument(
        "--version",
        action="version",
        version="%(prog)s v"+VERSION)

    workflow_refinement=parser.add_argument_group("[1] Workflow refinement")

    workflow_refinement.add_argument(
        "-r","--resume",
        help="bypass commands if the output files exist\n",
        action="store_true",
        default=config.resume)
    workflow_refinement.add_argument(
        "--bypass-nucleotide-index",
        help="bypass the nucleotide index step and run on the indexed ChocoPhlAn database\n",
        action="store_true",
        default=config.bypass_nucleotide_index)
    workflow_refinement.add_argument(
        "--bypass-nucleotide-search",
        help="bypass the nucleotide search steps\n",
        action="store_true",
        default=config.bypass_nucleotide_search)
    workflow_refinement.add_argument(
        "--bypass-prescreen",
        help="bypass the prescreen step and run on the full ChocoPhlAn database\n",
        action="store_true",
        default=config.bypass_prescreen)
    workflow_refinement.add_argument(
        "--bypass-translated-search",
        help="bypass the translated search step\n",
        action="store_true",
        default=config.bypass_translated_search)
    workflow_refinement.add_argument(
        "--taxonomic-profile",
        help="a taxonomic profile (the output file created by metaphlan)\n[DEFAULT: file will be created]",
        metavar="<taxonomic_profile.tsv>")
    workflow_refinement.add_argument(
        "--memory-use",
        help="the amount of memory to use\n[DEFAULT: " +
        config.memory_use + "]",
        default=config.memory_use,
        choices=config.memory_use_options)
    workflow_refinement.add_argument(
        "--input-format",
        help="the format of the input file\n[DEFAULT: format identified by software]",
        choices=config.input_format_choices)
    workflow_refinement.add_argument(
        "--search-mode",
        help="search for uniref50 or uniref90 gene families\n" +
        "[DEFAULT: based on translated database selected]",
        choices=[config.search_mode_uniref50, config.search_mode_uniref90],
        default=None)
    workflow_refinement.add_argument(
        "-v","--verbose",
        help="additional output is printed\n",
        action="store_true",
        default=config.verbose)

    tier1_prescreen=parser.add_argument_group("[2] Configure tier 1: prescreen")

    tier1_prescreen.add_argument(
        "--metaphlan",
        help="directory containing the MetaPhlAn software\n[DEFAULT: $PATH]",
        metavar="<metaphlan>")
    tier1_prescreen.add_argument(
        "--metaphlan-options",
        help="options to be provided to the MetaPhlAn software\n[DEFAULT: \"" + str(" ".join(config.metaphlan_opts)) + "\"]",
        metavar="<metaphlan_options>",
        default=" ".join(config.metaphlan_opts))
    tier1_prescreen.add_argument(
        "--prescreen-threshold",
        help="minimum estimated genome coverage for inclusion in pangenome search\n[DEFAULT: "
            + str(config.prescreen_threshold) + "]",
        metavar="<" + str(config.prescreen_threshold) + ">",
        type=float,
        default=config.prescreen_threshold)
    tier1_prescreen.add_argument(
        "--average-read-length",
        help="average read length for input file\n[DEFAULT: "
            + str(config.average_read_length) + "]",
        metavar="<" + str(config.average_read_length) + ">",
        type=float,
        default=config.average_read_length)

    tier2_nucleotide_search=parser.add_argument_group("[3] Configure tier 2: nucleotide search")

    tier2_nucleotide_search.add_argument(
        "--bowtie2",
        help="directory containing the bowtie2 executable\n[DEFAULT: $PATH]",
        metavar="<bowtie2>")
    tier2_nucleotide_search.add_argument(
        "--bowtie-options",
        help="options to be provided to the bowtie software\n[DEFAULT: \"" + str(" ".join(config.bowtie2_align_opts)) + "\"]",
        metavar="<bowtie_options>",
        default=" ".join(config.bowtie2_align_opts))
    tier2_nucleotide_search.add_argument(
        "--nucleotide-database",
        help="directory containing the nucleotide database\n[DEFAULT: "
            + config.nucleotide_database + "]",
        metavar="<nucleotide_database>")
    tier2_nucleotide_search.add_argument(
        "--nucleotide-identity-threshold",
        help="identity threshold for nuclotide alignments\n[DEFAULT: " + str(config.nucleotide_identity_threshold) + "]",
        metavar="<" + str(config.nucleotide_identity_threshold) + ">",
        type=float)
    tier2_nucleotide_search.add_argument(
        "--nucleotide-query-coverage-threshold",
        help="query coverage threshold for nucleotide alignments\n[DEFAULT: "
            + str(config.nucleotide_query_coverage_threshold) + "]",
        metavar="<" + str(config.nucleotide_query_coverage_threshold) + ">",
        type=float,
        default=config.nucleotide_query_coverage_threshold)
    tier2_nucleotide_search.add_argument(
        "--nucleotide-subject-coverage-threshold",
        help="subject coverage threshold for nucleotide alignments\n[DEFAULT: "
            + str(config.nucleotide_subject_coverage_threshold) + "]",
        metavar="<" + str(config.nucleotide_subject_coverage_threshold) + ">",
        type=float,
        default=config.nucleotide_subject_coverage_threshold)

    tier3_translated_search=parser.add_argument_group("[3] Configure tier 2: translated search")

    tier3_translated_search.add_argument(
        "--diamond",
        help="directory containing the diamond executable\n[DEFAULT: $PATH]",
        metavar="<diamond>")
    tier3_translated_search.add_argument(
        "--diamond-options",
        help="options to be provided to the diamond software\n[DEFAULT: \"" + str(" ".join(config.diamond_opts_uniref90)) + "\"]",
        metavar="<diamond_options>",
        default=" ".join(config.diamond_opts_uniref90))
    tier3_translated_search.add_argument(
        "--evalue",
        help="the evalue threshold to use with the translated search\n[DEFAULT: " + str(config.evalue_threshold) + "]",
        metavar="<" + str(config.evalue_threshold) + ">",
        type=float,
        default=config.evalue_threshold)
    tier3_translated_search.add_argument(
        "--protein-database",
        help="directory containing the protein database\n[DEFAULT: "
            + config.protein_database + "]",
        metavar="<protein_database>")
    tier3_translated_search.add_argument(
        "--rapsearch",
        help="directory containing the rapsearch executable\n[DEFAULT: $PATH]",
        metavar="<rapsearch>")
    tier3_translated_search.add_argument(
        "--translated-alignment",
        help="software to use for translated alignment\n[DEFAULT: " +
            config.translated_alignment_selected + "]",
        default=config.translated_alignment_selected,
        choices=config.translated_alignment_choices)
    tier3_translated_search.add_argument(
        "--translated-identity-threshold",
        help="identity threshold for translated alignments\n[DEFAULT: "
            + "Tuned automatically (based on uniref mode) unless a custom value is specified]",
        metavar="<Automatically: 50.0 or 80.0, Custom: 0.0-100.0>",
        type=float,
        dest="identity_threshold")
    tier3_translated_search.add_argument(
        "--translated-query-coverage-threshold",
        help="query coverage threshold for translated alignments\n[DEFAULT: "
            + str(config.translated_query_coverage_threshold) + "]",
        metavar="<" + str(config.translated_query_coverage_threshold) + ">",
        type=float,
        default=config.translated_query_coverage_threshold)
    tier3_translated_search.add_argument(
        "--translated-subject-coverage-threshold",
        help="subject coverage threshold for translated alignments\n[DEFAULT: "
            + str(config.translated_subject_coverage_threshold) + "]",
        metavar="<" + str(config.translated_subject_coverage_threshold) + ">",
        type=float,
        default=config.translated_subject_coverage_threshold)
    tier3_translated_search.add_argument(
        "--usearch",
        help="directory containing the usearch executable\n[DEFAULT: $PATH]",
        metavar="<usearch>")

    gene_and_pathway=parser.add_argument_group("[5] Gene and pathway quantification")

    gene_and_pathway.add_argument(
        "--count-normalization",
        help="normalization mode for results from both nucleotide and translated search\n[DEFAULT: " +
        config.count_normalization + "]",
        default=config.count_normalization,
        choices=config.count_normalization_choices)
    gene_and_pathway.add_argument(
        "--utility-database",
        help="directory containing the utility database\n[DEFAULT: "
            + config.utility_mapping_database + "]",
        metavar="<utility_mapping_database>")
    gene_and_pathway.add_argument(
        "--gap-fill",
        help="turn on/off the gap fill computation\n[DEFAULT: " +
        config.gap_fill_toggle + "]",
        default=config.gap_fill_toggle,
        choices=config.toggle_choices)
    gene_and_pathway.add_argument(
        "--minpath",
        help="turn on/off the minpath computation\n[DEFAULT: " +
        config.minpath_toggle + "]",
        default=config.minpath_toggle,
        choices=config.toggle_choices)
    gene_and_pathway.add_argument(
        "--pathways",
        help="the database to use for pathway computations\n[DEFAULT: " +
        config.pathways_database + "]",
        default=config.pathways_database,
        choices=config.pathways_database_choices)
    gene_and_pathway.add_argument(
        "--pathways-database",
        help="mapping file (or files, at most two in a comma-delimited list) to use for pathway computations\n[DEFAULT: " +
        config.pathways_database + " database ]",
        metavar=("<pathways_database.tsv>"),
        nargs=1)
    gene_and_pathway.add_argument(
        "--xipe",
        help="turn on/off the xipe computation\n[DEFAULT: " +
        config.xipe_toggle + "]",
        default=config.xipe_toggle,
        choices=config.toggle_choices)
    gene_and_pathway.add_argument(
        "--annotation-gene-index",
        help="the index of the gene in the sequence annotation\n[DEFAULT: "
            + ",".join(str(i) for i in config.chocophlan_gene_indexes) + "]",
        metavar="<"+",".join(str(i) for i in config.chocophlan_gene_indexes)+">",
        default=",".join(str(i) for i in config.chocophlan_gene_indexes))
    gene_and_pathway.add_argument(
        "--id-mapping",
        help="id mapping file for alignments\n[DEFAULT: alignment reference used]",
        metavar="<id_mapping.tsv>")

    more_output_config=parser.add_argument_group("[6] More output configuration")

    more_output_config.add_argument(
        "--remove-temp-output",
        help="remove temp output files\n" +
            "[DEFAULT: temp files are not removed]",
        action="store_true")
    more_output_config.add_argument(
        "--log-level",
        help="level of messages to display in log\n" +
        "[DEFAULT: " + config.log_level + "]",
        default=config.log_level,
        choices=config.log_level_choices)
    more_output_config.add_argument(
        "--o-log",
        help="log file\n" +
        "[DEFAULT: sample_0.log]",
        metavar="<sample_0.log>")
    more_output_config.add_argument(
        "--output-basename",
        help="the basename for the output files\n[DEFAULT: " +
        "input file basename]",
        default=config.file_basename,
        metavar="<sample_name>")
    more_output_config.add_argument(
        "--output-format",
        help="the format of the output files\n[DEFAULT: " +
        config.output_format + "]",
        default=config.output_format,
        choices=config.output_format_choices)
    more_output_config.add_argument(
        "--output-max-decimals",
        help="the number of decimals to output\n[DEFAULT: " +
        str(config.output_max_decimals) + "]",
        metavar="<" + str(config.output_max_decimals) + ">",
        type=int,
        default=config.output_max_decimals)
    more_output_config.add_argument(
        "--remove-column-description-output",
        help="remove the description in the output column\n" +
            "[DEFAULT: output column includes description]",
        action="store_true",
        default=config.remove_column_description_output)
    more_output_config.add_argument(
        "--remove-stratified-output",
        help="remove stratification from output\n" +
            "[DEFAULT: output is stratified]",
        action="store_true",
        default=config.remove_stratified_output)

    return parser.parse_args()

def update_configuration(args):
    """
    Update the configuration settings based on the arguments
    """

    # Use the full path to the input file
    args.input=os.path.abspath(args.input)

    # set the version header
    config.version_header=config.version_header+VERSION

    # If set, append paths executable locations
    if args.metaphlan:
        utilities.add_exe_to_path(os.path.abspath(args.metaphlan))

    if args.bowtie2:
        utilities.add_exe_to_path(os.path.abspath(args.bowtie2))

    if args.usearch:
        utilities.add_exe_to_path(os.path.abspath(args.usearch))

    if args.rapsearch:
        utilities.add_exe_to_path(os.path.abspath(args.rapsearch))

    if args.diamond:
        utilities.add_exe_to_path(os.path.abspath(args.diamond))

    # Set the metaphlan options, removing any extra spaces
    if args.metaphlan_options:
        config.metaphlan_opts=list(filter(None,args.metaphlan_options.split(" ")))

    # check for custom diamond options
    if args.diamond_options and args.diamond_options != " ".join(config.diamond_opts_uniref90):
        config.diamond_options_custom = True
        config.diamond_opts=list(filter(None,args.diamond_options.split(" ")))

    if args.bowtie_options:
        config.bowtie2_align_opts=list(filter(None,args.bowtie_options.split(" ")))

    # Set the pathways database selection
    if args.pathways == "metacyc":
        config.pathways_database_part1=config.metacyc_gene_to_reactions
        config.pathways_database_part2=config.metacyc_reactions_to_pathways
        config.pathways_ec_column=True
    elif args.pathways == "unipathway":
        config.pathways_database_part1=config.unipathway_database_part1
        config.pathways_database_part2=config.unipathway_database_part2
        config.pathways_ec_column=True

    # Set the locations of the pathways databases
    # If provided by the user, this will take precedence over the pathways database selection
    if args.pathways_database:
        custom_pathways_files=args.pathways_database[0].split(",")
        if len(custom_pathways_files)==2:
            config.pathways_database_part1=os.path.abspath(custom_pathways_files[0])
            config.pathways_database_part2=os.path.abspath(custom_pathways_files[1])
        elif len(custom_pathways_files)==1:
            config.pathways_database_part1=None
            config.pathways_database_part2=os.path.abspath(custom_pathways_files[0])
        else:
            sys.exit("ERROR: Please provide one or two pathways files.")
        config.pathways_ec_column=False

    # Set the locations of the other databases
    if args.nucleotide_database:
        config.nucleotide_database=os.path.abspath(args.nucleotide_database)

    if args.protein_database:
        config.protein_database=os.path.abspath(args.protein_database)

    # if set, update the config run mode to resume
    if args.resume:
        config.resume=True

    # if set, update the config run mode to verbose
    if args.verbose:
        config.verbose=True

    # if set, update the config run mode to bypass prescreen step
    if args.bypass_prescreen:
        config.bypass_prescreen=True

    # if set, update the config run mode to bypass nucleotide index step
    if args.bypass_nucleotide_index:
        config.bypass_nucleotide_index=True
        config.bypass_prescreen=True

    # if set, update the config run mode to bypass translated search step
    # set the pick_frames toggle based on the bypass
    config.pick_frames_toggle="off"
    if args.bypass_translated_search:
        config.bypass_translated_search=True

    # if set, update the config run mode to bypass nucleotide search steps
    if args.bypass_nucleotide_search:
        config.bypass_prescreen=True
        config.bypass_nucleotide_index=True
        config.bypass_nucleotide_search=True

    # update the average read length
    config.average_read_length=args.average_read_length

    # Update thresholds
    config.prescreen_threshold=args.prescreen_threshold
    config.translated_subject_coverage_threshold=args.translated_subject_coverage_threshold
    config.nucleotide_subject_coverage_threshold=args.nucleotide_subject_coverage_threshold
    config.translated_query_coverage_threshold=args.translated_query_coverage_threshold
    config.nucleotide_query_coverage_threshold=args.nucleotide_query_coverage_threshold

    # Update the max decimals output
    config.output_max_decimals=args.output_max_decimals

    # Update memory use
    config.memory_use=args.memory_use

    # Update threads
    config.threads=args.threads

    # Update the evalue threshold
    config.evalue_threshold=args.evalue

    # Update translated alignment software
    config.translated_alignment_selected=args.translated_alignment

    # Update the computation toggle choices
    config.xipe_toggle=args.xipe
    config.minpath_toggle=args.minpath
    config.gap_fill_toggle=args.gap_fill
    config.count_normalization=args.count_normalization

    if args.utility_database:
        config.utility_mapping_database=os.path.abspath(args.utility_database)

    # Check that the input file exists and is readable
    if not os.path.isfile(args.input):
        sys.exit("CRITICAL ERROR: Can not find input file selected: "+ args.input)

    if not os.access(args.input, os.R_OK):
        sys.exit("CRITICAL ERROR: Not able to read input file selected: " + args.input)

    # Update the output format
    config.remove_stratified_output=args.remove_stratified_output
    config.remove_column_description_output=args.remove_column_description_output

    # Check that the output directory is writeable
    output_dir = os.path.abspath(args.output)

    if not os.path.isdir(output_dir):
        try:
            print("Creating output directory: " + output_dir)
            os.mkdir(output_dir)
        except EnvironmentError:
            sys.exit("CRITICAL ERROR: Unable to create output directory.")

    if not os.access(output_dir, os.W_OK):
        sys.exit("CRITICAL ERROR: The output directory is not " +
            "writeable. This software needs to write files to this directory.\n" +
            "Please select another directory.")

    print("Output files will be written to: " + output_dir)

    # Set the basename of the output files if specified as an option
    if args.output_basename:
        config.file_basename=args.output_basename
    else:
        # Determine the basename of the input file to use as output file basename
        input_file_basename=os.path.basename(args.input)
        # Remove gzip extension if present
        if re.search('.gz$',input_file_basename):
            input_file_basename='.'.join(input_file_basename.split('.')[:-1])
        # Remove input file extension if present
        if '.' in input_file_basename:
            input_file_basename='.'.join(input_file_basename.split('.')[:-1])

        config.file_basename=input_file_basename

    # Set the output format
    config.output_format=args.output_format

    # Set final output file names and location
    config.pathabundance_file=os.path.join(output_dir,
            config.file_basename + config.pathabundance_file + "." +
            config.output_format)
    config.pathcoverage_file=os.path.join(output_dir,
            config.file_basename + config.pathcoverage_file + "." +
            config.output_format)
    config.genefamilies_file=os.path.join(output_dir,
            config.file_basename + config.genefamilies_file + "." +
            config.output_format)
    config.profile_file=os.path.join(output_dir,
            config.file_basename + config.profile_file + "." +
            config.output_format)
    config.reactions_file=os.path.join(output_dir,
            config.file_basename + config.reactions_file + "." +
            config.output_format)

    # set the location of the temp directory
    if not args.remove_temp_output:
        config.temp_dir=os.path.join(output_dir,config.file_basename+"_humann_temp")
        if not os.path.isdir(config.temp_dir):
            try:
                os.mkdir(config.temp_dir)
            except EnvironmentError:
                sys.exit("Unable to create temp directory: " + config.temp_dir)
    else:
        config.temp_dir=tempfile.mkdtemp(
            prefix=config.file_basename+'_humann_temp_',dir=output_dir)

    # create the unnamed temp directory
    config.unnamed_temp_dir=tempfile.mkdtemp(dir=config.temp_dir)

    # set the name of the log file
    log_file=os.path.join(output_dir,config.file_basename+"_0.log")

    # change file name if set
    if args.o_log:
        log_file=args.o_log

    # configure the logger
    logging.basicConfig(filename=log_file,format='%(asctime)s - %(name)s - %(levelname)s: %(message)s',
        level=getattr(logging,args.log_level), filemode='w', datefmt='%m/%d/%Y %I:%M:%S %p')

    # write the version of the software to the log
    logger.info("Running humann v"+VERSION)

    # write the location of the output files to the log
    logger.info("Output files will be written to: " + output_dir)

    # write the location of the temp file directory to the log
    message="Writing temp files to directory: " + config.temp_dir
    logger.info(message)
    if config.verbose:
        print("\n"+message+"\n")

    return log_file

def parse_chocophlan_gene_indexes(annotation_gene_index):
    """ Parse the chocophlan gene index input """

    # Update the chocophlan gene indexes
    chocophlan_gene_indexes=[]
    for index in annotation_gene_index.split(","):
        # Look for array range
        if ":" in index:
            split_index=index.split(":")
            start=split_index[0]
            end=split_index[1]

            try:
                start=int(start)
                end=int(end)
                chocophlan_gene_indexes+=range(start,end)
            except ValueError:
                pass
        else:
            # Convert to int
            try:
                index=int(index)
                chocophlan_gene_indexes.append(index)
            except ValueError:
                pass

    return chocophlan_gene_indexes

def check_requirements(args):
    """
    Check requirements (file format, dependencies, permissions)
    """

    # Check the pathways database files exist and are readable
    if config.pathways_database_part1:
        utilities.file_exists_readable(config.pathways_database_part1)
    utilities.file_exists_readable(config.pathways_database_part2)

    # Determine the input file format if not provided
    if not args.input_format:
        args.input_format=utilities.determine_file_format(args.input)

        if args.input_format == "unknown":
            sys.exit("CRITICAL ERROR: Unable to determine the input file format." +
                " Please provide the format with the --input_format argument.")

    config.input_format = args.input_format

    # If the input file is compressed, then decompress
    if args.input_format.endswith(".gz"):
        new_file=utilities.gunzip_file(args.input)

        if new_file:
            args.input=new_file
            args.input_format=args.input_format.split(".")[0]
        else:
            sys.exit("CRITICAL ERROR: Unable to use gzipped input file. " +
                " Please check the format of the input file.")

    # check if the input file has sequence identifiers of the new illumina casava v1.8+ format
    # these have spaces causing the paired end reads to have the same identifier after
    # delimiting by space (causing bowtie2/diamond to label the reads with the same identifier)
    if args.input_format in ["fasta","fastq"]:
        if utilities.space_in_identifier(args.input):
            message="Removing spaces from identifiers in input file"
            print(message+" ...\n")
            logger.info(message)
            new_file = utilities.remove_spaces_from_file(args.input)

            if new_file:
                args.input=new_file
            else:
                sys.exit("CRITICAL ERROR: Unable to remove spaces from identifiers in input file.")

    # If the input format is in binary then convert to sam (tab-delimited text)
    if args.input_format == "bam":

        # Check for the samtools software
        if not utilities.find_exe_in_path("samtools"):
            sys.exit("CRITICAL ERROR: The samtools executable can not be found. "
            "Please check the install or select another input format.")

        new_file=utilities.bam_to_sam(args.input)

        if new_file:
            args.input=new_file
            args.input_format="sam"
        else:
            sys.exit("CRITICAL ERROR: Unable to convert bam input file to sam.")

    # If the input format is in biom then convert to tsv
    if args.input_format == "biom":

        # Check for the biom software
        if not utilities.find_exe_in_path("biom"):
            sys.exit("CRITICAL ERROR: The biom executable can not be found. "
            "Please check the install or select another input format.")

        new_file=utilities.biom_to_tsv(args.input)

        if new_file:
            args.input=new_file
            # determine the format of the file
            args.input_format=utilities.determine_file_format(args.input)
        else:
            sys.exit("CRITICAL ERROR: Unable to convert biom input file to tsv.")

    # If the biom output format is selected, check for the biom package
    if config.output_format=="biom":
        if not utilities.find_exe_in_path("biom"):
            sys.exit("CRITICAL ERROR: The biom executable can not be found. "
            "Please check the install or select another output format.")

        try:
            import biom
        except ImportError:
            sys.exit("Could not find the biom software."+
                " This software is required since the output file is a biom file.")

    if os.path.basename(config.utility_mapping_database) == "utility_DEMO":
        # Check the input file is a demo input if running with demo database
        try:
            input_file_size=os.path.getsize(args.input)/1024**2
        except EnvironmentError:
            input_file_size=0
        if input_file_size > MAX_SIZE_DEMO_INPUT_FILE:
            sys.exit("ERROR: You are using the demo utility database with "
                + "a non-demo input file. If you have not already done so, please "
                + "run humann_databases to download the full utility database. "
                + "If you have downloaded the full database, use the option "
                + "--utility-database to provide the location. "
                + "You can also run humann_config to update the default "
                + "database location. For additional information, please "
                + "see the HUMAnN User Manual.")

    # If the file is fasta/fastq check for requirements
    if args.input_format in ["fasta","fastq"]:
        # Check that the chocophlan directory exists
        if not config.bypass_nucleotide_index:
            if not os.path.isdir(config.nucleotide_database):
                if args.nucleotide_database:
                    sys.exit("CRITICAL ERROR: The directory provided for the ChocoPhlAn database at "
                        + args.nucleotide_database + " does not exist. Please select another directory.")
                else:
                    sys.exit("CRITICAL ERROR: The default ChocoPhlAn database directory of "
                        + config.nucleotide_database + " does not exist. Please provide the location "
                        + "of the ChocoPhlAn directory using the --nucleotide-database option.")

        # Check that the files in the chocophlan folder are of the right format
        if not config.bypass_nucleotide_index:
            valid_format_count=0
            for file in os.listdir(config.nucleotide_database):
                # expect most of the file names to be of the format g__*s__*
                if re.search("^SGB",file):
                    valid_format_count+=1

                if not config.metaphlan_v4_db_matching_uniref in file:
                    sys.exit("\n\nCRITICAL ERROR: The directory provided for ChocoPhlAn contains files ( "+file+" )"+\
                        " that are not of the expected version. Please install the latest version"+\
                        " of the database: "+config.metaphlan_v4_db_matching_uniref)

            if valid_format_count == 0:
                sys.exit("CRITICAL ERROR: The directory provided for ChocoPhlAn does not "
                    + "contain files of the expected format (ie \'^SGB\').")

        # Check if running with the demo database
        if not config.bypass_nucleotide_index:
            if os.path.basename(config.nucleotide_database) == "chocophlan_DEMO":
                # Check the input file is a demo input if running with demo database
                try:
                    input_file_size=os.path.getsize(args.input)/1024**2
                except EnvironmentError:
                    input_file_size=0
                if input_file_size > MAX_SIZE_DEMO_INPUT_FILE:
                    sys.exit("ERROR: You are using the demo ChocoPhlAn database with "
                        + "a non-demo input file. If you have not already done so, please "
                        + "run humann_databases to download the full ChocoPhlAn database. "
                        + "If you have downloaded the full database, use the option "
                        + "--nucleotide-database to provide the location. "
                        + "You can also run humann_config to update the default "
                        + "database location. For additional information, please "
                        + "see the HUMAnN User Manual.")

        # Check that the metaphlan2 executable can be found
        if not config.bypass_prescreen and not config.bypass_nucleotide_index:
            if not utilities.find_exe_in_path("metaphlan"):
                sys.exit("CRITICAL ERROR: The metaphlan executable can not be found. "
                    "Please check the install.")

            # Check the metaphlan2 version
            utilities.check_software_version("metaphlan",config.metaphlan_version)

        # Check that the bowtie2 executable can be found
        if not config.bypass_nucleotide_search:
            if not utilities.find_exe_in_path("bowtie2"):
                sys.exit("CRITICAL ERROR: The bowtie2 executable can not be found. "
                    "Please check the install.")

            # Check the bowtie2 version
            utilities.check_software_version("bowtie2", config.bowtie2_version, warning=True)

        if not config.bypass_translated_search:
            # Check that the protein database directory exists
            if not os.path.isdir(config.protein_database):
                if args.protein_database:
                    sys.exit("CRITICAL ERROR: The directory provided for the protein database at "
                        + args.protein_database + " does not exist. Please select another directory.")
                else:
                    sys.exit("CRITICAL ERROR: The default protein database directory of "
                        + config.protein_database + " does not exist. Please provide the location "
                        + "of the directory using the --protein-database option.")

            # Check that some files in the protein database folder are of the expected extension
            expected_database_extension=""
            if config.translated_alignment_selected == "usearch":
                expected_database_extension=config.usearch_database_extension
            elif config.translated_alignment_selected == "rapsearch":
                expected_database_extension=config.rapsearch_database_extension
            elif config.translated_alignment_selected == "diamond":
                expected_database_extension=config.diamond_database_extension

            valid_format_count=0
            database_files=os.listdir(config.protein_database)
            valid_format_database_files=[]
            for file in database_files:
                if not config.matching_uniref in file:
                    sys.exit("\n\nCRITICAL ERROR: The directory provided for the translated database contains files ( "+file+" )"+\
                        " that are not of the expected version. Please install the latest version"+\
                        " of the database: "+config.matching_uniref)

                if file.endswith(expected_database_extension):
                    # if rapsearch check for the second database file
                    if config.translated_alignment_selected == "rapsearch":
                        database_file=re.sub(config.rapsearch_database_extension+"$","",file)
                        if database_file in database_files:
                            valid_format_count+=1
                            valid_format_database_files.append(database_file)
                    else:
                        valid_format_count+=1
                        valid_format_database_files.append(file)

            if valid_format_count == 0:
                sys.exit("CRITICAL ERROR: The protein database directory provided ( " + config.protein_database
                    + " ) does not contain any files that have been formatted to run with"
                    " the translated alignment software selected ( " +
                    config.translated_alignment_selected + " ). Please format these files so"
                    + " they are of the expected extension ( " + expected_database_extension +" ).")

            # if a search mode is not set by the user, then try to get mode based on translated search database
            if not args.search_mode:
                if config.search_mode_uniref90 in valid_format_database_files[0].lower():
                    logger.info("Search mode set to uniref90 because a uniref90 translated search database is selected")
                    config.search_mode=config.search_mode_uniref90
                elif config.search_mode_uniref50 in valid_format_database_files[0].lower():
                    logger.info("Search mode set to uniref50 because a uniref50 translated search database is selected")
                    config.search_mode=config.search_mode_uniref50

        # Check if running with the demo database
        if not config.bypass_translated_search:
            if os.path.basename(config.protein_database) == "uniref_DEMO":
                # Check the input file is a demo input if running with demo database
                try:
                    input_file_size=os.path.getsize(args.input)/1024**2
                except EnvironmentError:
                    input_file_size=0
                if input_file_size > MAX_SIZE_DEMO_INPUT_FILE:
                    sys.exit("ERROR: You are using the demo UniRef database with "
                        + "a non-demo input file. If you have not already done so, please "
                        + "run humann_databases to download the full UniRef database. "
                        + "If you have downloaded the full database, use the option "
                        + "--protein-database to provide the location. "
                        + "You can also run humann_config to update the default "
                        + "database location. For additional information, please "
                        + "see the HUMAnN User Manual.")

            # Check that the translated alignment executable can be found
            if not utilities.find_exe_in_path(config.translated_alignment_selected):
                sys.exit("CRITICAL ERROR: The " +  config.translated_alignment_selected +
                    " executable can not be found. Please check the install.")

            # Check for correct usearch version
            if config.translated_alignment_selected == "usearch":
                utilities.check_software_version("usearch",config.usearch_version)

            # Check for correct rapsearch version
            if config.translated_alignment_selected == "rapsearch":
                utilities.check_software_version("rapsearch", config.rapsearch_version)

            # Check for the correct diamond version
            if config.translated_alignment_selected == "diamond":
                utilities.check_software_version("diamond", config.diamond_version)

    # parse the chocophlan gene index
    chocophlan_gene_indexes=parse_chocophlan_gene_indexes(args.annotation_gene_index)

    # set the user provided search mode, if set
    if args.search_mode:
        config.search_mode = args.search_mode

    # set the values based on the search mode
    if config.search_mode == config.search_mode_uniref90:
        # only change identity threshold to default if user has not provided a specific setting
        if args.identity_threshold is None:
            config.identity_threshold = config.identity_threshold_uniref90_mode
        else:
            config.identity_threshold = args.identity_threshold

        # only change chocophlan gene index if user has not provided a specific setting
        if config.chocophlan_gene_indexes == chocophlan_gene_indexes:
            config.chocophlan_gene_indexes = config.chocophlan_gene_indexes_uniref90_mode
        else:
            config.chocophlan_gene_indexes = chocophlan_gene_indexes

        # set the diamond options if custom options were not provided
        if not config.diamond_options_custom:
            config.diamond_opts = config.diamond_opts_uniref90
    else:
        # only change identity threshold to default if user has not provided a specific setting
        if args.identity_threshold is None:
            config.identity_threshold = config.identity_threshold_uniref50_mode
        else:
            config.identity_threshold = args.identity_threshold

        # only change chocophlan gene index if user has not provided a specific setting
        if config.chocophlan_gene_indexes == chocophlan_gene_indexes:
            config.chocophlan_gene_indexes = config.chocophlan_gene_indexes_uniref50_mode
        else:
            config.chocophlan_gene_indexes = chocophlan_gene_indexes

        # set the diamond options if custom options were not provided
        if not config.diamond_options_custom:
            config.diamond_opts = config.diamond_opts_uniref50

def timestamp_message(task, start_time):
    """
    Print and log a message about the task completed and the time
    Log messages are tab delimited for quick task/time access with awk
    Return the new start time
    """
    message="TIMESTAMP: Completed \t" + task + " \t:\t " + \
        str(int(round(time.time() - start_time))) + "\t seconds"
    logger.info(message)
    if config.verbose:
        print("\n"+message.replace("\t","")+"\n")

    return time.time()

def main():
    # Parse arguments from command line
    args=parse_arguments(sys.argv)

    # Update the configuration settings based on the arguments
    log_file=update_configuration(args)

    # Check for required files, software, databases, and also permissions
    check_requirements(args)

    # Write the config settings to the log file
    config.log_settings()

    # Initialize alignments and gene scores
    minimize_memory_use=True
    if config.memory_use == "maximum":
        minimize_memory_use=False

    alignments=store.Alignments(minimize_memory_use=minimize_memory_use)
    unaligned_reads_store=store.Reads(minimize_memory_use=minimize_memory_use)
    gene_scores=store.GeneScores()

    # If id mapping is provided then process
    if args.id_mapping:
        alignments.process_id_mapping(args.id_mapping)

    # Load in the reactions database
    reactions_database=None
    if config.pathways_database_part1:
        reactions_database=store.ReactionsDatabase(config.pathways_database_part1)

        message="Load pathways database part 1: " + config.pathways_database_part1
        logger.info(message)

    # Load in the pathways database
    pathways_database=store.PathwaysDatabase(config.pathways_database_part2, reactions_database)

    if config.pathways_database_part1:
        message="Load pathways database part 2: " + config.pathways_database_part2
    else:
        message="Load pathways database: " + config.pathways_database_part2
    logger.info(message)

    # Start timer
    start_time=time.time()

    # Process fasta or fastq input files
    output_files=[]
    if args.input_format in ["fasta","fastq"]:
        # Run prescreen to identify bugs
        bug_file = "Empty"
        if args.taxonomic_profile:
            bug_file = os.path.abspath(args.taxonomic_profile)
        else:
            if not config.bypass_prescreen:
                bug_file = prescreen.alignment(args.input)
                output_files.append(bug_file)
                start_time=timestamp_message("prescreen",start_time)

        # Create the custom database from the bugs list
        custom_database = ""
        if not config.bypass_nucleotide_index:
            custom_database = prescreen.create_custom_database(config.nucleotide_database, bug_file)
            start_time=timestamp_message("custom database creation",start_time)
        else:
            custom_database = "Bypass"

        # Run nucleotide search on custom database
        if custom_database != "Empty" and not config.bypass_nucleotide_search:
            if not config.bypass_nucleotide_index:
                nucleotide_index_file = nucleotide.index(custom_database)
                start_time=timestamp_message("database index",start_time)
            else:
                nucleotide_index_file = nucleotide.find_index(config.nucleotide_database)

            nucleotide_alignment_file = nucleotide.alignment(args.input,
                nucleotide_index_file)

            start_time=timestamp_message("nucleotide alignment",start_time)

            # Determine which reads are unaligned and reduce aligned reads file
            # Remove the alignment_file as we only need the reduced aligned reads file
            [ unaligned_reads_file_fasta, reduced_aligned_reads_file ] = nucleotide.unaligned_reads(
                nucleotide_alignment_file, alignments, unaligned_reads_store, keep_sam=True)

            start_time=timestamp_message("nucleotide alignment post-processing",start_time)

            # Print out total alignments per bug
            message="Total bugs from nucleotide alignment: " + str(alignments.count_bugs())
            logger.info(message)
            print(message)

            message=alignments.counts_by_bug()
            logger.info("\n"+message)
            print(message)

            message="Total gene families from nucleotide alignment: " + str(alignments.count_genes())
            logger.info(message)
            print("\n"+message)

            # Report reads unaligned
            message="Unaligned reads after nucleotide alignment: " + utilities.estimate_unaligned_reads_stored(
                args.input, unaligned_reads_store) + " %"
            logger.info(message)
            print("\n"+message+"\n")
        else:
            logger.debug("Custom database is empty")
            reduced_aligned_reads_file = "Empty"
            unaligned_reads_file_fasta=args.input
            unaligned_reads_store=store.Reads(unaligned_reads_file_fasta, minimize_memory_use=minimize_memory_use)

        # Do not run if set to bypass translated search in config file
        if not config.bypass_translated_search:
            # Run translated search on UniRef database if unaligned reads exit
            if unaligned_reads_store.count_reads()>0:
                translated_alignment_file = translated.alignment(config.protein_database,
                    unaligned_reads_file_fasta)

                start_time=timestamp_message("translated alignment",start_time)

                # Determine which reads are unaligned
                translated_unaligned_reads_file_fastq = translated.unaligned_reads(
                    unaligned_reads_store, translated_alignment_file, alignments)

                start_time=timestamp_message("translated alignment post-processing",start_time)

                # Print out total alignments per bug
                message="Total bugs after translated alignment: " + str(alignments.count_bugs())
                logger.info(message)
                print(message)

                message=alignments.counts_by_bug()
                logger.info("\n"+message)
                print(message)

                message="Total gene families after translated alignment: " + str(alignments.count_genes())
                logger.info(message)
                print("\n"+message)

                # Report reads unaligned
                message="Unaligned reads after translated alignment: " + utilities.estimate_unaligned_reads_stored(
                    args.input, unaligned_reads_store) + " %"
                logger.info(message)
                print("\n"+message+"\n")
            else:
                message="All reads are aligned so translated alignment will not be run"
                logger.info(message)
                print(message)
        else:
            message="Bypass translated search"
            logger.info(message)
            print(message)

    # Process input files of sam format
    elif args.input_format in ["sam"]:

        # Store the sam mapping results
        message="Process the sam mapping results ..."
        logger.info(message)
        print("\n"+message)

        [unaligned_reads_file_fasta, reduced_aligned_reads_file] = nucleotide.unaligned_reads(
            args.input, alignments, unaligned_reads_store, keep_sam=True)

        start_time=timestamp_message("alignment post-processing",start_time)

    # Process input files of tab-delimited blast format
    elif args.input_format in ["blastm8"]:

        # Store the blastm8 mapping results
        message="Process the blastm8 mapping results ..."
        logger.info(message)
        print("\n"+message)

        translated_unaligned_reads_file_fastq = translated.unaligned_reads(
            unaligned_reads_store, args.input, alignments)

        start_time=timestamp_message("alignment post-processing",start_time)

    # Get the number of remaining unaligned reads
    unaligned_reads_count=unaligned_reads_store.count_reads()

    # Clear all of the unaligned reads as they are no longer needed
    unaligned_reads_store.clear()

    # Compute or load in gene families
    if args.input_format in ["fasta","fastq","sam","blastm8"]:
        # Compute the gene families
        message="Computing gene families ..."
        logger.info(message)
        print("\n"+message)

        families_file=families.gene_families(alignments,gene_scores,unaligned_reads_count)
        output_files.append(families_file)

        start_time=timestamp_message("computing gene families",start_time)

    elif args.input_format in ["genetable"]:
        # Load the gene scores
        message="Process the gene table ..."
        logger.info(message)
        print("\n"+message)

        unaligned_reads_count=gene_scores.add_from_file(args.input,id_mapping_file=args.id_mapping)

        start_time=timestamp_message("processing gene table",start_time)

    # Handle input files of unknown formats
    else:
        sys.exit("CRITICAL ERROR: Input file of unknown format.")

    # Clear all of the alignments data as they are no longer needed
    alignments.clear()

    # Identify reactions and then pathways from the alignments
    message="Computing reaction and pathway abundance ..."
    logger.info(message)
    print("\n"+message)
    pathways_and_reactions_store=modules.identify_reactions_and_pathways(
        gene_scores, reactions_database, pathways_database, unaligned_reads_count)

    # Compute pathway abundance and coverage
    abundance_file, coverage_file, reaction_file=modules.compute_pathways_abundance_and_coverage(
        gene_scores, reactions_database, pathways_and_reactions_store, pathways_database, unaligned_reads_count)
    output_files.append(reaction_file)
    output_files.append(abundance_file)
    output_files.append(log_file)
    #output_files.append(coverage_file)

    start_time=timestamp_message("computing pathways",start_time)

    message="\nOutput files created: \n" + "\n".join(output_files) + "\n"
    logger.info(message)
    print(message)

    # Remove the unnamed temp files
    utilities.remove_directory(config.unnamed_temp_dir)

    # Remove named temp directory
    if args.remove_temp_output:
        utilities.remove_directory(config.temp_dir)


from django.shortcuts import render
from .models import Post
from django.utils import timezone
from .forms import PostForm
from django.shortcuts import redirect

def post_list(request):
    context = {}
    posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
    context['posts'] = posts
    return render(request, 'blog/post_list.html', context)

def post_new(request):
    if request.method == "POST":
        form = PostForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.published_date = timezone.now()
            post.save()
            return redirect('post_list')
    else:
        form = PostForm()
        return render(request, 'blog/post_new.html', {'form': form})


from enum import Enum

from pandas.tseries.holiday import AbstractHolidayCalendar, Holiday, sunday_to_monday, USMemorialDay, USLaborDay, \
    USThanksgivingDay

class Iso(Enum):
    MISO = 'miso'
    ISONE = 'isone'
    ERCOT = 'ercot'
    PJM = 'pjm'
    SPP = 'spp'
    AESO = 'aeso'
    NYISO = 'nyiso'
    CAISO = 'caiso'

class Block(Enum):
    _7x8 = '7x8'
    _5x16 = '5x16'
    _2x16 = '2x16'
    _7x24 = '7x24'
    _7x16 = '7x16'
    _1x1 = '1x1'
    Wrap = 'wrap'
    _6x16 = '6x16'

class Frequency(Enum):
    Daily = 'daily'
    Monthly = 'monthly'
    Hourly = 'hourly'

class NERCHolidayCalendar(AbstractHolidayCalendar):
    """
    Creates a custom holiday calendar based on NERC schedule.
    Defined at https://www.nerc.com/comm/OC/RS%20Agendas%20Highlights%20and%20Minutes%20DL/Additional_Off-peak_Days.pdf
    """

    rules = [
        Holiday('NewYearsDay', month=1, day=1, observance=sunday_to_monday),
        USMemorialDay,
        Holiday('USIndependenceDay', month=7, day=4, observance=sunday_to_monday),
        USLaborDay,
        USThanksgivingDay,
        Holiday('Christmas', month=12, day=25, observance=sunday_to_monday)
    ]


def solution(land):

    # 한 단계 전에 것들을 사용하므로 1부터
    for i in range(1,len(land)):
        for j in range(4):
            # 해당 위치 값은 전 행에서 그 열 값을 뺀 나머지 값들 중의 최대값을 더해줌
            # 어떤 인덱스였는지는 기록 안함, j가 이미 정보 보유
            land[i][j] += max(land[i-1][:j] + land[i-1][j+1:])
    # 마지막 행이 값들의 총합 리스트
    return max(land[-1])

프로그래머스/땅따먹기.py


import pytest

from python_on_whales import DockerException, docker
from python_on_whales.components.image.models import ImageInspectResult
from python_on_whales.test_utils import get_all_jsons, random_name

@pytest.mark.parametrize("json_file", get_all_jsons("images"))
def test_load_json(json_file):
    json_as_txt = json_file.read_text()
    ImageInspectResult.parse_raw(json_as_txt)
    # we could do more checks here if needed

def test_image_remove():
    docker.image.pull("busybox:1", quiet=True)
    docker.image.pull("busybox:1.32", quiet=True)
    docker.image.remove(["busybox:1", "busybox:1.32"])

def test_image_save_load(tmp_path):
    tar_file = tmp_path / "dodo.tar"
    docker.image.pull("busybox:1", quiet=True)
    docker.image.save("busybox:1", output=tar_file)
    docker.image.remove("busybox:1")
    assert docker.image.load(input=tar_file) == ["busybox:1"]

def test_save_iterator_bytes():
    docker.image.pull("busybox:1", quiet=True)
    iterator = docker.image.save("busybox:1")

    for i, my_bytes in enumerate(iterator):
        if i == 0:
            assert len(my_bytes) != 0

    assert i != 0

def test_save_iterator_bytes_fails():
    docker.image.pull("busybox:1", quiet=True)
    iterator = docker.image.save("busybox:42")

    with pytest.raises(DockerException) as err:
        for _ in iterator:
            pass
    assert "docker image save busybox:42" in str(err.value)
    assert "Error response from daemon: reference does not exist" in str(err.value)

def test_save_iterator_bytes_and_load():
    image_name = "busybox:1"
    docker.image.pull(image_name, quiet=True)
    iterator = docker.image.save(image_name)

    my_tar_as_bytes = b"".join(iterator)

    docker.image.remove(image_name)

    loaded = docker.image.load(my_tar_as_bytes)
    assert loaded == [image_name]
    docker.image.inspect(image_name)

def test_save_iterator_bytes_and_load_from_iterator():
    image_name = "busybox:1"
    docker.image.pull(image_name, quiet=True)
    iterator = docker.image.save(image_name)

    assert docker.image.load(iterator) == [image_name]
    docker.image.inspect(image_name)

def test_save_iterator_bytes_and_load_from_iterator_list_of_images():
    images = ["busybox:1", "hello-world:latest"]
    docker.image.pull(images[0], quiet=True)
    docker.image.pull(images[1], quiet=True)
    iterator = docker.image.save(images)

    assert set(docker.image.load(iterator)) == set(images)
    docker.image.inspect(images[0])
    docker.image.inspect(images[1])

def test_image_list():
    image_list = docker.image.list()
    all_ids = [x.id for x in image_list]
    all_ids_uniquified = set(all_ids)
    assert len(set(all_ids_uniquified)) == len(image_list)

def test_image_bulk_reload():
    pass

def test_image_list_tags():
    image_name = "busybox:1"
    docker.image.pull(image_name, quiet=True)
    all_images = docker.image.list()
    for image in all_images:
        if image_name in image.repo_tags:
            return
    else:
        raise ValueError("Tag not found in images.")

def test_pull_not_quiet():
    try:
        docker.image.remove("busybox:1")
    except DockerException:
        pass
    image = docker.image.pull("busybox:1")
    assert "busybox:1" in image.repo_tags

def test_copy_from_and_to(tmp_path):
    my_image = docker.pull("busybox:1")
    (tmp_path / "dodo.txt").write_text("Hello world!")

    new_image_name = random_name()
    my_image.copy_to(tmp_path / "dodo.txt", "/dada.txt", new_tag=new_image_name)

    new_image_name = docker.image.inspect(new_image_name)
    new_image_name.copy_from("/dada.txt", tmp_path / "dudu.txt")
    assert (tmp_path / "dodo.txt").read_text() == (tmp_path / "dudu.txt").read_text()

def test_copy_from_and_to_directory(tmp_path):
    my_image = docker.pull("busybox:1")
    (tmp_path / "dodo.txt").write_text("Hello world!")

    new_image_name = random_name()
    my_image.copy_to(tmp_path, "/some_path", new_tag=new_image_name)

    new_image_name = docker.image.inspect(new_image_name)
    new_image_name.copy_from("/some_path", tmp_path / "some_path")
    assert "Hello world!" == (tmp_path / "some_path" / "dodo.txt").read_text()


n = int(input())

testCase = []
for i in range(n):
    testCase.append(input())

for case in testCase:
    sum_case = 0
    num = 0
    for char in case:
        if char == 'O':
            num += 1
        elif char == 'X':
            num = 0
        sum_case += num

    print(sum_case)


#!/usr/bin/env python
"""Converts valgrind log output to a suppressions file.

Run valgrind with something like:

    valgrind --leak-check=full --show-reachable=yes
       --error-limit=no --gen-suppressions=all --num-callers=12
       --log-file=output.log executable_to_check

Use the created `output.log` file as input to this script.

Duplicated suppressions are discarted.
"""
import os
import re
import argparse
import hashlib

def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        'infile', type=argparse.FileType('rt'),
        help='Input file created with the valgrind --log-file option.')
    parser.add_argument(
        'outfile', type=argparse.FileType('wt'),
        help='Output suppressions file.')
    parser.add_argument(
        '--head', '-H', type=argparse.FileType('rt'),
        help="A file who's content will included first in the output.")
    parser.add_argument(
        '--tail', '-t', type=argparse.FileType('rt'),
        help="A file who's content will appended to the output.")
    parser.add_argument(
        '--skip-leak-kinds', '-s', action='store_true',
        help='Whether to skip matching leak kinds.')
    parser.add_argument(
        '--keep-obj', '-k', action='store_true',
        help=('Whether to keep `obj:<library>` in output.  The default is '
              'to replace it with `obj:*`.'))
    parser.add_argument(
        '--exclude-regex', '-x', metavar='REGEX',
        help='Exclude suppressions matching regular expression REGEX')
    args = parser.parse_args()

    d = parse_input(args)
    write_output(args, d)

    args.infile.close()
    args.outfile.close()

def parse_input(args):
    """Parse the valgrind log file and return a dict mapping md5 hashes to
    suppression sections."""
    d = {}
    n = 1
    sec = []
    fin = args.infile

    for line in fin:
        if line.startswith('=='):
            pass

        elif re.match(r'\s*{', line):
            sec = ['{']

        elif re.search(r'<[a-z_]+>', line):
            sec.append('   suppression-%d-%s' % (n, os.path.basename(fin.name)))

        elif args.skip_leak_kinds and re.search(r'match-leak-kinds:', line):
            pass

        elif not args.keep_obj and re.search(r'obj:', line):
            #if 'obj:' in sec[-1]:
            #    sec[-1] = '   ...'
            #elif '...' in sec[-1]:
            #    pass
            #else:
            #    sec.append('   obj:*')
            if '...' not in sec[-1]:
                sec.append('   ...')

        elif re.match(r'\s*}', line):

            # skip final "obj:" or "..." matches
            m = len(sec)
            for s in sec[::-1]:
                if 'obj:' not in s and '...' not in s:
                    break
                m -= 1
            sec = sec[:m]

            sec.append(line)

            txt = '\n'.join(sec)
            sec = []
            if not args.exclude_regex or not re.search(args.exclude_regex, txt):
                md5 = hashlib.md5(txt.encode())
                d[md5] = txt
                n += 1

        else:
            sec.append(line.rstrip())

    return d

def write_output(args, d):
    """Write output file. `d` is the dict returned by parse_input(). """
    fout = args.outfile
    if args.head:
        fout.write(args.head.read() + '\n')
    fout.write('# ------------------------------------------\n')
    fout.write('# valgrind suppressions generated from\n')
    fout.write('# %s\n' % args.infile.name)
    fout.write('# ------------------------------------------\n')
    for s in d.values():
        fout.write(str(s))
    if args.tail:
        fout.write(args.tail.read())

if __name__ == '__main__':
    main()


#Assinging elements to different list
list1=[1,2,3,4,5]
list2=["abc","def","ghi"]
list3=[11,22,33,44,55]
list1.append(6)
list1
list2.append("jkl")
list3.append(66)
list2
list3
#Accesing elements from tuple
tup1=(1,2,3,4,5)
tup1[0]
tup2=("adc","def","ghi")
tup2[2]
#Deleting diffferent dictionary elements
dic={"a":1,"b":2,"c":3}
if "a" in dic:
    del dic["a"]
print(dic)


from account_bt import Account
from order_bt import Order
from database_bt import Database
import globals
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time

# mabe use this https://pythonguides.com/matplotlib-update-plot-in-loop/ animate func
# def initialize(database):
#     database['mv_bid'] = 0
#     database['mv_ask'] = 0

def process(account, current_data, database):
    n = 10
    current_index = globals.global_index
    new_df = database.get_df_period(current_index - n, current_index + 1)
    # print(new_df)
    mv_bid = sum(new_df.Bid) / min(n, current_index + 1)
    mv_ask = sum(new_df.Ask) / min(n, current_index + 1)
    # database['mv_bid'][current_index] = mv_bid
    # database['mv_ask'][current_index] = mv_ask
    # print(mv_bid, mv_ask)

    return

def animate_plot(inp):
    x_plot = range(0, 101)
    y_plot = db.get_data_frame().iloc[:101]['Bid'].values

    print(y_plot)

    line1.set_data(x_plot, y_plot)
    return line1,

if __name__ == '__main__':
    globals.initialize()
    db = Database("TEST.txt")
    # initialize(db)

    print(db.get_data_frame().head())

    plt.ion()
    figure, ax = plt.subplots(figsize=(10, 8))
    x = []
    y = []
    line1, = ax.plot(x, y)
    # plt.show()
    account_1 = Account(1000 * 500)
    i = 0
    # while i < 20:
    #     current_data = db.get_df_index(globals.global_index)
    #     current_index = globals.global_index
    #
    #     process(account_1, current_data, db)
    #     '''
    #     print(db.get_df_index(current_index))
    #     print(db.get_data_frame().info())
    #     print(db.get_data_frame().iloc[:current_index+1]['DateTime'].values)
    #     print(db.get_data_frame().iloc[current_index]['Bid'])
    #     '''
    #     print(range(0,current_index+1))
    #     print(db.get_data_frame().iloc[:current_index+1]['Bid'].values)
    #     line1.set_xdata(list(range(0,current_index+1)))
    #     line1.set_ydata(db.get_data_frame().iloc[:current_index+1]['Bid'].values)
    #     # plt.pause(1)
    #     figure.canvas.draw()
    #     figure.canvas.flush_events()
    #     time.sleep(1)
    #
    #     globals.update_global_index()
    #     i += 1

    ani = animation.FuncAnimation(figure, animate_plot, frames=100, interval=100, blit=True)
    #ani.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])

    plt.show()

#%%


import requests
from datetime import datetime

def get_questions(days_ago, tag):
    counter = 0
    todate = int(datetime.timestamp(datetime.today()))
    fromdate = todate - days_ago * 86400
    question_create_time, counter = get_next_questions(fromdate, todate, tag, counter)
    while question_create_time < todate:
        question_create_time, counter = get_next_questions(question_create_time, todate, tag, counter)
        question_create_time += 1
    return f'За {days_ago} дня(-ей) опубликовано {counter} новых вопросов.'

def get_next_questions(fromdate, todate, tag, counter):
    question_create_time = todate
    params = {
        'fromdate': fromdate,
        'todate': todate,
        'order': 'asc',
        'sort': 'creation',
        'tagged': tag,
        'site': 'stackoverflow'
    }

    responce = requests.get('https://api.stackexchange.com/2.3/questions', params=params)
    responce.raise_for_status()
    if responce.status_code != 200:
        print(f"Ошибка обработки запроса! Код ошибки: {responce.status_code}")
        return question_create_time, counter
    for question in responce.json().get('items'):
        counter += 1
        question_create_time = question['creation_date']
        with open(f'last_questions_{datetime.fromtimestamp(todate)}.txt', 'a') as file:
            file.write(f'Question # {counter}: {question["title"]}\n'
                       f'Tags: {str(question["tags"])}\n '
                       f'Creation Date {datetime.fromtimestamp(question_create_time)}\n'
                       f'___\n')
        print(f'Question # {counter}: {question["title"]}')
        print(f'Tags: {str(question["tags"])}')
        print(f'Creation Time: {datetime.fromtimestamp(question_create_time)}')
        print('___')

    return question_create_time, counter

if __name__ == '__main__':
    print(get_questions(2, 'python'))


from collections import OrderedDict
from rest_framework import serializers

from ..models import Image, Author, Entity, AuthorsSpecialization, Occupation, Land

class PrimaryKeySerializerField(serializers.PrimaryKeyRelatedField):
    def __init__(self, **kwargs):
        self.serializer = kwargs.pop('serializer')
        super(PrimaryKeySerializerField, self).__init__(**kwargs)

    def get_choices(self, cutoff=None):
        queryset = self.get_queryset()
        if queryset is None:
            return {}

        if cutoff is not None:
            queryset = queryset[:cutoff]

        return OrderedDict([
            (
                super(PrimaryKeySerializerField, self).to_representation(item),
                super(PrimaryKeySerializerField, self).display_value(item)
            )
            for item in queryset
        ])

    def use_pk_only_optimization(self):
        return False

    def to_representation(self, value):
        serializer = self.serializer(value, context=self.context)
        serializer.parent = self.parent
        return serializer.data

class ImageURLField(serializers.URLField):
    def to_representation(self, value):
        if value:
            return value.image.url
        else:
            return ""

class OccupationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Occupation
        fields = '__all__'

class LandSerializer(serializers.ModelSerializer):
    class Meta:
        model = Land
        fields = '__all__'

class ImageSpecializationSerializer(serializers.ModelSerializer):
    image_id = serializers.SlugRelatedField(
        read_only=True,
        source='image',
        slug_field='id',
    )
    image_ru = serializers.SlugRelatedField(
        read_only=True,
        source='image',
        slug_field='name_ru',
    )
    image_en = serializers.SlugRelatedField(
        read_only=True,
        source='image',
        slug_field='name_en',
    )
    specialization = serializers.ChoiceField(
        choices=AuthorsSpecialization.SPECIALIZATIONS,
        source='get_specialization_display',
    )

    class Meta:
        model = AuthorsSpecialization
        fields = ('image_id', 'image_ru', 'image_en', 'specialization')

class AuthorSerializer(serializers.ModelSerializer):
    images = ImageSpecializationSerializer(
        many=True,
        required=False,
    )
    occupations = OccupationSerializer(
        many=True,
        required=False,
    )
    lands = LandSerializer(
        many=True,
        required=False,
    )

    class Meta:
        model = Author
        fields = (
            'id', 'name_ru', 'name_en',
            'begin_date', 'end_date', 'begin_work_date', 'end_work_date',
            'index', 'gnd', 'notes',
            'images', 'occupations', 'lands',
        )

class AuthorShortSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = ('id', 'index', 'name_ru', 'name_en',)

class AuthorSpecSerializer(serializers.ModelSerializer):
    specialization = serializers.ChoiceField(
        choices=AuthorsSpecialization.SPECIALIZATIONS,
        source='get_specialization_display',
    )
    author = PrimaryKeySerializerField(
        serializer=AuthorShortSerializer,
        queryset=Author.objects.all(),
    )

    class Meta:
        model = AuthorsSpecialization
        fields = ('id', 'author', 'specialization')

class ImageShortSerializer(serializers.ModelSerializer):
    image_front_link = serializers.HyperlinkedIdentityField(
        view_name='image-detail-front',
        source='self',
        read_only=True,
    )

    class Meta:
        model = Image
        fields = (
            'id', 'name_ru', 'name_en',
            'create_date',
            'image_front_link',
        )

class EntitySerializer(serializers.HyperlinkedModelSerializer):
    main_image = ImageURLField()
    images = PrimaryKeySerializerField(
        serializer=ImageShortSerializer,
        many=True,
        queryset=Image.objects.all(),
    )

    class Meta:
        model = Entity
        fields = (
            'id', 'index', 'normdate',
            'name_ru', 'name_en',
            'begin_date', 'end_date',
            'description', 'notes',
            'source', 'source_link',
            'main_image', 'images',
        )

class EntityShortSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Entity
        fields = ('id', 'index', 'name_ru', 'name_en', 'begin_date', 'end_date',)

class ImageSerializer(serializers.ModelSerializer):
    authors = AuthorSpecSerializer(
        many=True,
        style={'base_template': 'list_fieldset.html'},
    )
    entity = PrimaryKeySerializerField(
        serializer=EntityShortSerializer,
        queryset=Entity.objects.all(),
    )

    class Meta:
        model = Image
        fields = (
            'id', 'index_image_mu', 'index_image_hab',
            'image', 'thumb_image', 'size',
            'name_ru', 'name_en',
            'description', 'description_lat', 'notes',
            'create_date', 'source_link', 'doublet_links', 'catalog_links',
            'authors', 'entity', 'technique',
        )


import unittest

import pytest

from resend.exceptions import (MissingApiKeyError, ResendError,
                               raise_for_code_and_type)

class TestResendError(unittest.TestCase):
    def test_raise_when_unknown_error(self):
        with pytest.raises(ResendError) as e:
            raise_for_code_and_type(999, "error_type", "msg")
        assert e.type is ResendError

    def test_raise_known_error(self):
        with pytest.raises(MissingApiKeyError) as e:
            raise_for_code_and_type(401, "missing_api_key", "err")
        assert e.type is MissingApiKeyError


from __future__ import absolute_import

from pyswagger.core import BaseClient
from requests import Session, Request

import six
import json
import base64

class Client(BaseClient):

    # declare supported schemes here
    __schemes__ = set(['http', 'https'])

    def __init__(self, config=None, auth=None, send_opt=None, extraheaders=None):
        """ constructor
        :param auth pyswagger.SwaggerAuth: auth info used when requesting
        :param send_opt dict: options used in requests.send, ex verify=False
        """
        super(Client, self).__init__(auth)
        if send_opt is None:
            send_opt = {}

        self.__s = Session()
        self.__send_opt = send_opt

        self.extraheaders = extraheaders

        auth = base64.b64encode(config['user'] + ":" + config['password'])
        self.authhead = {"authorization": "Basic " + auth}

    def request(self, req_and_resp, opt):
        # passing to parent for default patching behavior,
        # applying authorizations, ...etc.
        req, resp = super(Client, self).request(req_and_resp, opt)

        req.prepare(scheme=self.prepare_schemes(req).pop(), handle_files=False)
        req._patch(opt)

        file_obj = []
        def append(name, obj):
            f = obj.data or open(obj.filename, 'rb')
            if 'Content-Type' in obj.header:
                file_obj.append((name, (obj.filename, f, obj.header['Content-Type'])))
            else:
                file_obj.append((name, (obj.filename, f)))

        for k, v in six.iteritems(req.files):
            if isinstance(v, list):
                for vv in v:
                    append(k, vv)
            else:
                append(k, v)

        rq = Request(
            method=req.method.upper(),
            url=req.url,
            params=req.query,
            data=req.data,
            headers=req.header,
            files=file_obj
        )

        rq = self.__s.prepare_request(rq)
        rq.headers.update(self.authhead)
        rs = self.__s.send(rq, stream=True, **self.__send_opt)

        myresp = {}
        myresp['status'] = rs.status_code
        myresp['data'] = json.loads(rs.content.rstrip())
        #myresp['headers'] = rs.headers

        return myresp


# uncompyle6 version 3.8.0
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.15 (default, Dec 21 2021, 12:03:22)
# [GCC 10.2.1 20210110]
# Embedded file name: /home/cagatay/PycharmProjects/Expiry/FCOS/fcos_core/utils/model_serialization.py
# Compiled at: 2021-12-16 06:36:40
# Size of source mod 2**32: 3457 bytes
from collections import OrderedDict
import logging, torch
from FCOS.fcos_core.utils.imports import import_file

def align_and_update_state_dicts(model_state_dict, loaded_state_dict):
    """
    Strategy: suppose that the models that we will create will have prefixes appended
    to each of its keys, for example due to an extra level of nesting that the original
    pre-trained data from ImageNet won't contain. For example, model.state_dict()
    might return backbone[0].body.res2.conv1.weight, while the pre-trained model contains
    res2.conv1.weight. We thus want to match both parameters together.
    For that, we look for each model weight, look among all loaded keys if there is one
    that is a suffix of the current weight name, and use it if that's the case.
    If multiple matches exist, take the one with longest size
    of the corresponding name. For example, for the same model as before, the pretrained
    weight file can contain both res2.conv1.weight, as well as conv1.weight. In this case,
    we want to match backbone[0].body.conv1.weight to conv1.weight, and
    backbone[0].body.res2.conv1.weight to res2.conv1.weight.
    """
    current_keys = sorted(list(model_state_dict.keys()))
    loaded_keys = sorted(list(loaded_state_dict.keys()))
    match_matrix = [len(j) if i.endswith(j) else 0 for i in current_keys for j in loaded_keys]
    match_matrix = torch.as_tensor(match_matrix).view(len(current_keys), len(loaded_keys))
    max_match_size, idxs = match_matrix.max(1)
    idxs[max_match_size == 0] = -1
    max_size = max([len(key) for key in current_keys]) if current_keys else 1
    max_size_loaded = max([len(key) for key in loaded_keys]) if loaded_keys else 1
    log_str_template = '{: <{}} loaded from {: <{}} of shape {}'
    logger = logging.getLogger(__name__)
    for idx_new, idx_old in enumerate(idxs.tolist()):
        if idx_old == -1:
            pass
        else:
            key = current_keys[idx_new]
            key_old = loaded_keys[idx_old]
            model_state_dict[key] = loaded_state_dict[key_old]
            logger.info(log_str_template.format(key, max_size, key_old, max_size_loaded, tuple(loaded_state_dict[key_old].shape)))

def strip_prefix_if_present(state_dict, prefix):
    keys = sorted(state_dict.keys())
    if not all(key.startswith(prefix) for key in keys):
        return state_dict
    else:
        stripped_state_dict = OrderedDict()
        for key, value in state_dict.items():
            stripped_state_dict[key.replace(prefix, '')] = value

        return stripped_state_dict

def load_state_dict(model, loaded_state_dict):
    model_state_dict = model.state_dict()
    loaded_state_dict = strip_prefix_if_present(loaded_state_dict, prefix='module.')
    align_and_update_state_dicts(model_state_dict, loaded_state_dict)
    model.load_state_dict(model_state_dict)
# okay decompiling ./fcos_core/utils/model_serialization.pyc


import sys
import bisect

def Input_Data():
    readl = sys.stdin.readline
    N = int(readl())
    k = int(readl())
    return N, k

N, k = Input_Data()
ans = 0

def Solve():
    start, end = 1, k
    while start <= end:
        mid = (start+end)//2
        print(mid)
        temp = 0
        for i in range(1, N+1):
            temp += min(mid//i, N)
        if temp >= k:
            ans = mid
            end = mid-1
        else:
            start = mid + 1
    print(ans)

Solve()


class Student(object):
    type = 'student'
    __slots__ = ('name', '_age')

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if not isinstance(value, int):
            raise ValueError('age must be a integer')
        if value < 0 or value >150:
            print('age must between 0 and 150')
        self._age = value

s= Student()
s.name = 'Mick'
s.age = 18
# s.score = 90
s.age = -1

class HighStudent(Student):
    pass

hs = HighStudent()
hs.score = 70

class Screen(object):
    @property
    def width(self):
        return self._width

    @width.setter
    def width(self, value):
        if not isinstance(value, int):
            raise ValueError('width must be a integer')
        if value < 0:
            print('width must be positive')
        self._width = value

    @property
    def height(self):
        return self._height

    @height.setter
    def height(self, value):
        if not isinstance(value, int):
            raise ValueError('height must be a integer')
        if value < 0:
            print('height must be positive')
        self._height = value

    @property
    def solution(self):
        return self._height*self._width

screen = Screen()
screen.width = 16
screen.height = 20
print(screen.solution)
assert screen.solution == 320


from gerrychain import Graph
import geopandas as gpd
import networkx as nx
from typing import Optional, Dict, List, Tuple

def dualgraph(
        geometries: gpd.GeoDataFrame, index: Optional[str]=None,
        geometrycolumn: Optional[str]="geometry", colmap: Optional[Dict]={},
        buffer: Optional[float]=0, edges_to_add: Optional[List[Tuple]]=[],
        edges_to_cut: Optional[List[Tuple]]=[]
    ) -> Graph:
    """
    Generates a graph dual to the provided geometric data.

    :param geometries: Geometric data represented as a GeoDataFrame.
    :param index: Unique identifiers; indexing column of `geometries`. If this
    value is not set, vertex labels are integer indices; otherwise, vertex
    labels are the values of this column.
    :param geometrycolumn: Optional; name of `geoemtries`' geometry column.
    Defaults to `"geometry"`.
    :param colmap: Optional; maps old column names to new column names.
    :param buffer: Optional; geometric buffer distance; defaults to `0`.
    :param edges_to_add: Optional; edges to add to the graph object. Assumed to
    be a list of pairs of objects, e.g. `[(u, v), ...]` where `u` and `v` are
    vertex labels consistent with `index`.
    :param edges_to_cut: Optional; edges to cut from the graph object. Assumed to
    be a list of pairs of objects, e.g. `[(u, v), ...]` where `u` and `v` are
    vertex labels consistent with `index`.
    """
    # Buffer geometries by default.
    geometries[geometrycolumn] = geometries.buffer(buffer)

    # Set indices and rename columns.
    if index: geometries = geometries.set_index(index)
    if colmap: geometries = geometries.rename(colmap, axis=1)

    # Generate the dual graph.
    dg = Graph.from_geodataframe(geometries)

    # Add and remove extraneous edges.
    for add in edges_to_add: dg.add_edge(*add)
    for cut in edges_to_cut: dg.remove_edge(*cut)

    # Return the graph!
    return dg


# coding: utf-8

import numpy as np
import time
import copy
import torch
import torch.nn as nn
import torchvision.models as models
from torch.autograd import Variable
import pickle

import torchvision.transforms as transforms
from torch.utils.data import Dataset, DataLoader
from flickr8k import Flickr8k

class mVGG19(object):
    '''
    Args:
        bn (bool): load model with batch normalization or not
        pretrain (bool): whether you want the model is pretrained or not
        layer (string): desired feature out of which convolution layer
        img_dir (string): Location of Dataset images
        cap_dir (string): Location of Dataset text
        bsz (int): batch size in extracting features
    Example Usage:
        extractor = mVGG19(True, True)
        extractor.build('conv5_1')
        features, captions = extractor.forward('./Flickr8k_Dataset', './Flickr8k_text', 32)
    '''
    def __init__(self, bn=True, pretrain=True):
        # load vgg19 with/without batch_normalization
        print('building feature extractor on vgg...')
        self.bn_flag = bn
        if bn:
            self.model = models.vgg19_bn(pretrained=pretrain)
            self.layer_dict = {
                'conv1_1': 2, 'conv1_2': 5, 'conv2_1': 9, 'conv2_2': 12,
                'conv3_1': 16, 'conv3_2': 19, 'conv3_3': 22, 'conv3_4': 25,
                'conv4_1': 29, 'conv4_2': 32, 'conv4_3': 35, 'conv4_4': 38,
                'conv5_1': 42, 'conv5_2': 45, 'conv5_3': 48, 'conv5_4': 51
            }
        else:
            self.model = models.vgg19(pretrained=pretrain)
            self.layer_dict = {
                'conv1_1': 1, 'conv1_2': 3, 'conv2_1': 6, 'conv2_2': 8,
                'conv3_1': 11, 'conv3_2': 13, 'conv3_3': 15, 'conv3_4': 17,
                'conv4_1': 20, 'conv4_2': 22, 'conv4_3': 24, 'conv4_4': 26,
                'conv5_1': 29, 'conv5_2': 31, 'conv5_3': 33, 'conv5_4': 35
            }

    def build(self, layer='conv5_1'):
        # build the desire feature extractor
        idx = self.layer_dict[layer]
        self.extractor = nn.Sequential(*list(self.model.features.children())[:idx+1])
        if torch.cuda.is_available():
            self.extractor.cuda()

    def forward(self, img_dir='./Flickr8k_Dataset', cap_dir='./Flickr8k_text', bsz=32):
        print('extracting features...')
        # load & preprocess the data
        normalization = transforms.Compose(
                    [
                        transforms.Scale((224,224)),
                        # (H x W x C) in the range [0, 255] to (C x H x W) in the range [0.0, 1.0].
                        transforms.ToTensor(),
                        transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
                    ]
                )
        datasets = {
            'train': Flickr8k(img_dir, cap_dir, normalization, 'train'),
            'hold': Flickr8k(img_dir, cap_dir, normalization, 'dev'),
            'test': Flickr8k(img_dir, cap_dir, normalization, 'test')
        }
        # get dataloader
        dataloaders = {
            'train': DataLoader(
                    dataset = datasets['train'],
                    batch_size = bsz,
                    num_workers = 4
                ),
            'hold': DataLoader(
                    dataset = datasets['hold'],
                    batch_size = bsz,
                    num_workers = 4
                ),
            'test': DataLoader(
                    dataset = datasets['test'],
                    batch_size = bsz,
                    num_workers = 4
                )
        }
        # forward
        all_names = {'train': [], 'hold': [], 'test': []}
        all_features = {'train': [], 'hold': [], 'test': []}
        all_captions = {'train': [], 'hold': [], 'test': []}
        since = time.time()
        for phase in ['train', 'hold', 'test']:
            print('   '+phase+' features...')
            self.extractor.eval()
            tmp_features = []
            for sample in dataloaders[phase]:
                # get the inputs
                img_names, images, captions = sample
                images = Variable(images, volatile=True)
                if torch.cuda.is_available():
                    images = images.cuda()
                # (# of sample, # of filter, 14, 14)
                features = self.extractor(images)
                # (# of sample, # of filter, 196)
                features = features.view(features.size()[0], features.size()[1], -1)
                tmp_features.append(features.data.cpu().numpy())
                for i in range(len(captions[0])):
                    all_names[phase].append(img_names[i])
                    all_captions[phase].append([cap[i] for cap in captions])
            all_features[phase] = np.vstack(tmp_features)
        print('extracting feature took {0:.1f}s'.format(time.time()-since))
        #### return featuers as ndarray, captions as list
        return all_names, all_features, all_captions

if __name__ == '__main__':
    # get feature extractor
    extractor = mVGG19()
    extractor.build('conv5_1')
    # feature: (sample num, D, L)
    names, features, captions = extractor.forward()

    # save extracted features
    print('saving extracted features...')
    with open('img_names.pickle', 'wb') as handle:
        pickle.dump(names, handle, protocol=pickle.HIGHEST_PROTOCOL)
    with open('features.pickle', 'wb') as handle:
        pickle.dump(features, handle, protocol=pickle.HIGHEST_PROTOCOL)
    with open('captions.pickle', 'wb') as handle:
        pickle.dump(captions, handle, protocol=pickle.HIGHEST_PROTOCOL)


import numpy as np
from mlp import NN
import gendata
from pydbm.dbm.deepboltzmannmachine.stacked_auto_encoder import StackedAutoEncoder
from pydbm.dbm.builders.dbm_multi_layer_builder import DBMMultiLayerBuilder
from pydbm.approximation.contrastive_divergence import ContrastiveDivergence
from pydbm.activation.tanh_function import TanhFunction
from pydbm.activation.logistic_function import LogisticFunction
from sklearn.metrics import confusion_matrix, classification_report,  accuracy_score
from sklearn.model_selection import train_test_split

data = gendata.arrnilais #generate idf score from dataset
labels = gendata.labels
#target_arr = np.random.normal(loc=0.0, scale=1.0, size=(100, 50))
#target_arr = (target_arr - target_arr.mean()) / target_arr.std()
labels = labels.reshape(len(labels),1)

activation_list = [LogisticFunction(), LogisticFunction(), LogisticFunction()]

approximaion_list = [ContrastiveDivergence(), ContrastiveDivergence()]

dbm = StackedAutoEncoder(
    DBMMultiLayerBuilder(),
    [data.shape[1], 100, data.shape[1]],
    activation_list,
    approximaion_list,
    1e-03 # Setting  rate.
)

dbm.learn(
    data,
    training_count=10, # If approximation is the Contrastive Divergence, this parameter is `k` in CD method.
    batch_size=-1,  # Batch size in mini-batch training.
    r_batch_size=-1,  # if `r_batch_size` > 0, the function of `dbm.learn` is a kind of reccursive learning.
    sgd_flag=True
)

# layer_number corresponds to the index of approximaion_list.
# And reconstruct_error_arr is the np.ndarray of reconstruction error rates.
reconstruct_error_arr = dbm.get_reconstruct_error_arr(layer_number=0)

pre_trained_arr = dbm.feature_points_arr

weight_arr_list = dbm.get_weight_arr_list()

visible_bias_arr_list = dbm.get_visible_bias_arr_list()
hidden_bias_arr_list = dbm.get_hidden_bias_arr_list()

dbm.save_pre_learned_params(dir_path="pre-learned", file_name="dbm_demo")

dbm_t = StackedAutoEncoder(
    DBMMultiLayerBuilder(
        pre_learned_path_list=[
            "pre-learned/dbm_demo_0.npz",
            "pre-learned/dbm_demo_1.npz"
        ]
    ),
    [data.shape[1], 100, data.shape[1]],
    activation_list,
    approximaion_list,
    1e-03#Learning rate.
)

# Execute learning.
dbm_t.learn(
    data,
    training_count=10, # If approximation is the Contrastive Divergence, this parameter is `k` in CD method.
    batch_size=-1,  # Batch size in mini-batch training.
    r_batch_size=-1  # if `r_batch_size` > 0, the function of `dbm.learn` is a kind of reccursive learning.
)
trained_arr = dbm_t.feature_points_arr
reconstruct_error_arr = dbm_t.get_reconstruct_error_arr(layer_number=0)

X_train, X_test, Y_train, Y_test = train_test_split(trained_arr, labels, test_size=0.2, random_state=0)

n=NN(X_train)
n.train(X_train, Y_train, 3000)
pred = n.think(X_test)
pred = (pred > 0.5).astype(np.int_)

print('confusion_matrix :\n', confusion_matrix(Y_test, pred))
print('classification_report :\n', classification_report(Y_test, pred))
print('accuracy_score :\n', accuracy_score(Y_test, pred))


# Soru 1
students = {}
# students[st_number] = {
#     "Name" : st_name,
#     "Surname" : st_surname,
#     "Phone" : st_phone
# }
# 2. Yol
st_number = int(input("Lütfen öğrenci numarası giriniz : "))
st_name = str(input("Lütfen öğrenci adını yazınız : "))
st_surname = str(input("Lütfen öğrenci soyadını yazınız : "))
st_phone = int(input("Lütfen öğrencinin telefon numarasını yazınız : "))

students.update({
    st_number : {
        "Name" : st_name,
        "Surname" : st_surname,
        "Phone" : st_phone
    }
})
# Soru 2
print("*"*50)
ogr_no = int(input("Lütfen Aramak İstediğiniz Öğrenci Numarası Giriniz : "))
ogrencibul = students[ogr_no]
print(f'{ogr_no} numaralı öğrencinin:/n Adı : {students["Name"]}')

Basic Python/Objects and data types/dictionaries_examples.py


from typing import Optional, List
import tweepy
from decouple import config

apikey = config("APIKEY")
apisecret = config("APIKEY_SECRET")
access_token = config("ACCESS_TOKEN")
access_token_secret = config("ACCESS_TOKEN_SECRET")

auth = tweepy.OAuthHandler(apikey, apisecret)
auth.set_access_token(access_token,access_token_secret)

api = tweepy.API(auth)

def getSpecificUser(user: str, add_rts: Optional[bool] = False, add_replies: Optional[bool] = True, limit: Optional[int]=50):
    try:
        x = api.user_timeline(screen_name=user, include_rts = add_rts, count = limit, exclude_replies = add_replies,trim_user = '')
        # PRINT FOR TESTS
        for t in x:
            print('---------------------------------')
            print(t.full_text)
            print(t.created_at)
            print('---------------------------------')
        # return x
    except:
        return None
    #do something or return it

def gettrending(area: str, limit: Optional[int]=50):
    try:
        x = api.get_place_trends(area)
        y: List[str]
        for p in x[:limit]:
            y.add(p.text)
        return y
    except:
        return None


import logging
import random
from base64 import b64encode

import libnacl
from enum import Enum
from pyeclib.ec_iface import ECDriver

import src.messages.messages_pb2 as pb
from src.utils import Handled

_BRACHA_STEP = Enum('_BRACHA_STEP', 'one two three')
_INIT = pb.Bracha.Type.Value('INIT')
_ECHO = pb.Bracha.Type.Value('ECHO')
_READY = pb.Bracha.Type.Value('READY')

class Bracha(object):
    """
    Bracha broadcast '87
    Implemented using state machine (BrachaStep)
    """
    def __init__(self, factory, msg_wrapper_f=lambda _x: _x):
        self._factory = factory
        self._step = _BRACHA_STEP.one
        self._init_count = 0
        self._echo_count = 0
        self._ready_count = 0
        self._root = None
        self._fragments = {}
        self._v = None
        self._done = False
        self._msg_wrapper_f = msg_wrapper_f
        self._n = self._factory.config.n
        self._t = self._factory.config.t
        self._sent_ready = False

        # NOTE: #define EC_MAX_FRAGMENTS 32
        # https://github.com/openstack/liberasurecode/blob/master/include/erasurecode/erasurecode.h
        k = self._n - 2 * self._t
        m = 2 * self._t
        logging.debug("Bracha: erasure code params k={}, m={}".format(k, m))
        self._ec_driver = ECDriver(k=k, m=m, ec_type='liberasurecode_rs_vand')
        random.seed()

    def handle(self, msg, sender_vk):
        # type: (pb.Bracha) -> Handled
        """
        This function is called on a new incoming message, we expect the type is correct
        msg should be in the following format
        struct Msg {
            ty: u32,
            body: String,
        }
        :param msg: the input message to send
        :return: the delivered message when completed, otherwise None
        """
        if self._done:
            logging.debug("Bracha: done, doing nothing")
            return Handled()

        ty = msg.ty
        logging.debug("Bracha: received {}".format(msg))

        assert isinstance(ty, int)
        assert msg.digest is not None

        # initialisation
        if self._root is None:
            # if body is None, we must be in the initial state
            assert self._init_count == 0 and self._echo_count == 0 and self._ready_count == 0
            self._root = msg.digest

        if self._root != msg.digest:
            logging.debug("Bracha: self.root {} != root: {}, discarding"
                          .format(b64encode(self._root), b64encode(msg.digest)))
            return Handled()

        # here we update the state
        if ty == _INIT:
            self._init_count += 1

        elif ty == _ECHO:
            self._fragments[sender_vk] = msg.fragment
            self._echo_count += 1
            assert self._echo_count == len(self._fragments), \
                "echo_count {} != fragment count {}".format(self._echo_count, len(self._fragments))

        elif ty == _READY:
            self._ready_count += 1
            assert self._root == msg.digest, \
                "self.root {} != root: {}".format(self._root, msg.digest)

        else:
            raise AssertionError("Bracha: unexpected msg type")

        # we should only see one init message
        assert self._init_count == 0 or self._init_count == 1

        # everything below is the algorithm, acting on the current state
        if ty == _INIT:
            logging.debug("Bracha: got init value, root = {}".format(b64encode(msg.digest)))
            self._upon_init(msg)

        if ty == _ECHO:
            logging.debug("Bracha: got echo value, root = {}".format(b64encode(msg.digest)))
            # TODO check Merkle branch
            pass

        if ty == _ECHO and self._echo_count >= self._n - self._t:
            logging.debug("Bracha: got n - t echo values, root = {}".format(b64encode(msg.digest)))
            self._upon_n_minus_t_echo()

        if ty == _READY and self._ready_count >= self._t + 1:
            self._upon_t_plus_1_ready()

        if self._ready_count >= 2 * self._t + 1 and self._echo_count >= self._n - 2*self._t:
            res = self._upon_2t_plus_1_ready()

            # NOTE: we use a random value to trip up tests, since it shouldn't be viewed by tests
            logging.info("Bracha: DELIVER {}"
                         .format(random.random() if self._factory.config.from_instruction else b64encode(res)))

            self._done = True
            return Handled(res)

        return Handled()

    def _upon_init(self, msg):
        assert isinstance(msg, pb.Bracha)
        msg.ty = _ECHO
        self.bcast(msg)

    def _decode_fragments(self):
        fragments = random.sample(self._fragments.values(), self._n - 2 * self._t)
        v = self._ec_driver.decode(fragments)
        return v

    def _upon_n_minus_t_echo(self):
        v = self._decode_fragments()
        assert libnacl.crypto_hash_sha256(v) == self._root
        self._v = v
        logging.debug("Bracha: erasure decoded msg v {}".format(b64encode(v)))

        if not self._sent_ready:
            logging.debug("Bracha: broadcast ready 1, root = {}".format(b64encode(self._root)))
            self.bcast(pb.Bracha(ty=_READY, digest=self._root))
            self._sent_ready = True

    def _upon_t_plus_1_ready(self):
        if not self._sent_ready:
            logging.debug("Bracha: broadcast ready 2, root = {}".format(b64encode(self._root)))
            self.bcast(pb.Bracha(ty=_READY, digest=self._root))
            self._sent_ready = True

    def _upon_2t_plus_1_ready(self):
        if self._v is None:
            self._v = self._decode_fragments()
        return self._v

    def bcast_init(self, msg="some test msg!!"):
        assert isinstance(msg, str)
        self._bcast_init_fragments(msg)

    def _bcast_init_fragments(self, msg):
        """

        :param msg: some bytes
        :return:
        """
        fragments = self._ec_driver.encode(msg)
        digest = libnacl.crypto_hash_sha256(msg)

        logging.info("Bracha: initiate erasure code with {} fragments, digest {}"
                     .format(len(fragments), b64encode(digest)))

        assert len(fragments) == len(self._factory.promoters)
        for fragment, promoter in zip(fragments, self._factory.promoters):
            m = pb.Bracha(ty=_INIT, digest=digest, fragment=fragment)
            self._factory.send(promoter, self._msg_wrapper_f(m))

    def bcast(self, msg):
        self._factory.promoter_cast(self._msg_wrapper_f(msg))


fname = input("Enter file name: ")
fh = open(fname)
lst = list()
temp = list()
for line in fh:
	line = line.rstrip()
	temp = line.split()
	for element in temp:
		if element in lst:
			continue
		lst.append(element)
lst.sort()
print(lst)


__author__ = 'abdullahabdullah'

# -- Functions ---

"""
def fonk():
    print('Merhaba')

fonk()

def fonk2(name):
    print(name)

fonk2('Abdullah')

def fonk3(name):
    print('{}'.format(name))

fonk3('Yakut')

def fonk4(first,last):
    print('my name is {} and my sourname {}'.format(first,last))

fonk4('Abdullah','Yakut')

def fonk5(first,last):
    print('my name is {} and my sourname {}'.format(first,last))

fonk5(first ='Abdullah',last='Yakut')

"""

# fonksiyona  gonderecegimiz rakamin tek mi ciftmi
# ciktisini gosteren kod yazalim.

def tek_cift(rakam):

    if rakam %2 ==0:
        return 'Cift'

    if rakam %2 ==1:
        return 'Tek'

# sonuc = 'cift'
# sonuc = 'tek'

sonuc = tek_cift(8)

print(sonuc)