#!/usr/bin/env python3


"""transcript annotation and analysis pipeline"""
import argparse
import os
from annogesiclib.controller import Controller

__author__ = "Sung-Huan Yu <sung-huan.yu@uni-wuerzburg.de>"
__email__ = "sung-huan.yu@uni-wuerzburg.de"
__version__ = "0.5.16"

def main():
    print("""
       ___    _   ___   ______                  _     
      /   |  / | / / | / / __ \____ ____  _____(_)____ \\
  __ / /| | /  |/ /  |/ / / / / __ `/ _ \/ ___/ / ___/__\\
 |  / ___ |/ /|  / /|  / /_/ / /_/ /  __(__  ) / /__    /
 | /_/  |_/_/ |_/_/ |_/\____/\__, /\___/____/_/\___/   /
 |                          /____/ 
 |__________________
 |_____________________
 |________________________________________________
 |                                                \\
 |________________________________________________/
""")
    home_path = os.environ["HOME"]
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--version", "-v", default=False, action="store_true",
        help="show version")
    subparsers = parser.add_subparsers(help="commands")
    # Arguments for project creation
    create_project_parser = subparsers.add_parser(
        "create", help="Create a project")
    create_project_basic = create_project_parser.add_argument_group(
            'basic arguments')
    create_project_basic.add_argument(
        "--project_path", "-pj", required=True, help="Name/path of the project.")
    create_project_parser.set_defaults(func=create_project)
    # Parameters for get input files
    get_input_parser = subparsers.add_parser(
        "get_input_files", help="Get required files. "
        "(i.e. annotation files, fasta files)")
    get_input_basic = get_input_parser.add_argument_group(
            'basic arguments')
    get_input_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    get_input_basic.add_argument(
        "--ftp_path", "-F",
        help="Path of folder on the NCBI FTP server where the required files "
        "are located.")
    get_input_basic.add_argument(
        "--ref_fasta", "-f", default=False, action="store_true",
        help="Download fasta files of the reference. Default is False.")
    get_input_basic.add_argument(
        "--ref_gff", "-g", default=False, action="store_true",
        help="Download gff files of the reference. Default is False.")
    get_input_basic.add_argument(
        "--ref_gbk", "-k", default=False, action="store_true",
        help="Download genbank files of the reference. Default is False.")
    get_input_add = get_input_parser.add_argument_group('additional arguments')
    get_input_add.add_argument(
        "--ref_ptt", "-p", default=False, action="store_true",
        help="Download ptt files of the reference. Default is False.")
    get_input_add.add_argument(
        "--ref_rnt", "-r", default=False, action="store_true",
        help="Download rnt files of the reference. Default is False.")
    get_input_add.add_argument(
        "--convert_embl", "-e", default=False, action="store_true",
        help="Convert gbk to embl files of the reference. Default is False.")
    get_input_parser.set_defaults(func=get_input)
    # get target fasta
    get_target_fasta_parser = subparsers.add_parser(
        "update_genome_fasta", help="Get fasta files of query genomes "
        "if the query sequences do not exist.")
    get_target_fasta_basic = get_target_fasta_parser.add_argument_group(
            'basic arguments')
    get_target_fasta_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    get_target_fasta_basic.add_argument(
        "--related_fasta_files", "-c", required=True, nargs='+',
        help="Path of the genome fasta files of the closely related species.")
    get_target_fasta_basic.add_argument(
        "--mutation_table", "-m", required=True,
        help="Path of the mutation table which stores the mutation "
        "information between the query genome and genome of the closely "
        "related species. For an example check "
        "https://github.com/Sung-Huan/ANNOgesic/"
        "blob/master/tutorial_data/mutation.csv")
    get_target_fasta_basic.add_argument(
        "--combine_to_one_fasta", "-cm", default=False, action="store_true",
        help="For combining all updated sequences in --mutation_table to "
        "one fasta file. Default is False.")
    get_target_fasta_parser.set_defaults(func=get_target_fasta)    

    # run RATT
    RATT_parser = subparsers.add_parser(
        "annotation_transfer", help="Transfer the annotations "
        "from a closely related species genome to a target genome.")
    RATT_basic = RATT_parser.add_argument_group(
        'basic arguments')
    RATT_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    RATT_basic.add_argument(
        "--compare_pair", "-p", required=True, nargs='+',
        help="Please assign the name of genome pairs, e.g. "
        "NC_007795:NEW_NC_007795. The related genome is NC_007795 and "
        "the target genome is NEW_NC_007795. The assigned names are the "
        "headers of the fasta file (start with \">\"), not the "
        "filename of fasta file. If multiple genomes need to be assigned, "
        "please use spaces to separate the genomes.")
    RATT_basic.add_argument(
        "--related_embl_files", "-ce", default=None, nargs='+',
        help="The paths of the embl files of the related species.")
    RATT_basic.add_argument(
        "--related_gbk_files", "-cg", default=None, nargs='+',
        help="The paths of the genbank files of the related species. "
        "The genbank can be ended by .gbk, .gbff or .gb")
    RATT_basic.add_argument(
        "--related_fasta_files", "-cf", required=True, nargs='+',
        help="The paths of the fasta files of the related species.")
    RATT_basic.add_argument(
        "--updated_fasta_files", "-uf", required=True, nargs='+',
        help="The paths of updated fasta files.")
    RATT_add = RATT_parser.add_argument_group(
        'additional arguments')
    RATT_add.add_argument(
        "--ratt_path", default="start.ratt.sh",
        help="Path of the start.ratt.sh file of RATT folder. "
        "Default is start.ratt.sh.")
    RATT_add.add_argument(
        "--element", "-e", required=True,
        help="--element will become the prefix of all output file.")
    RATT_add.add_argument(
        "--transfer_type", "-t", default="Strain",
        help="The transfer type for running RATT. (For the details, "
        "please refer to the manual of RATT.) Default is Strain.")
    RATT_add.add_argument(
        "--convert_to_gff_rnt_ptt", "-g", default=False, action="store_true",
        help="Convert the annotation to gff, rnt and ptt. Default is False.")
    RATT_parser.set_defaults(func=run_RATT)

    # Parameters of TSSpredator
    TSSpredator_parser = subparsers.add_parser(
        "tss_ps", help="Detect TSSs or "
        "processing sites.")
    TSSpredator_basic = TSSpredator_parser.add_argument_group(
        'basic arguments')
    TSSpredator_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    TSSpredator_basic.add_argument(
        "--program", "-p", default="TSS",
        help="Which feature you want to predict, please assign \"TSS\" or "
        "\"processing_site\". Default is TSS.")
    TSSpredator_basic.add_argument(
        "--fasta_files", "-f", required=True, nargs='+',
        help="Paths of the query genome fasta files.")
    TSSpredator_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of the query genome gff files.")
    TSSpredator_basic.add_argument(
        "--tex_notex_libs", "-tl", required=True, nargs='+',
        help="The libraries of TEX+/- wig files. The format is: "
        "wig_file_path:TEX+/-(tex or notex):condition_id(integer):"
        "replicate_id(alphabet):strand(+ or -). "
        "If multiple wig files need to be assigned, please use spaces to "
        "separate the wig files. For an example, "
        "$WIG_PATH_1:tex:1:a:+ $WIG_PATH_2:tex:1:a:-.")
    TSSpredator_basic.add_argument(
        "--replicate_tex", "-rt", default=["all_1"], nargs='+',
        help="This value is the minimal number of replicates that a TSS "
        "has to be detected. "
        "The format is $NUMBERofCONDITION_$NUMBERofREPLICATE. "
        "If different --replicate_tex values need to be assigned to different "
        "conditions, please use spaces to separate them. For an example, "
        "1_2 2_2 3_3. It means that --replicate_tex is 2 in number 1 and "
        "number 2 conditions. In number 3 condition, --replicate_tex is 3. "
        "For assigning the same --replicate_tex to all conditions, "
        "just use like all_1 (--replicate_tex is 1 in all conditions). "
        "Default is all_1.")
    TSSpredator_basic.add_argument(
        "--condition_names", "-cn", required=True, nargs='+',
        help="The output prefix of all conditions. If multiple conditions "
        "need to be assigned, please use spaces to separate them. "
        "For an example, prefix_condition1 prefix_condition2.")
    TSSpredator_add = TSSpredator_parser.add_argument_group(
        'additional arguments')
    TSSpredator_add.add_argument(
        "--tsspredator_path", default="/usr/local/bin/TSSpredator.jar",
        help="If you want to assign the path of TSSpredator, "
        "please assign here. Default is /usr/local/bin/TSSpredator.jar")
    TSSpredator_add.add_argument(
        "--specify_genomes", "-ss", default=None, nargs="+",
        help="If you want to assign different parameters to different "
        "genomes, Please input the genome names that you want to compute. "
        "The genome names should be separated by spaces. "
        "Default is running all genomes based on the same parameter.")
    TSSpredator_add.add_argument(
        "--height", "-he", default=[0.3], nargs="+",
        help="This value relates to the minimal number of read starts at a "
	"certain genomic position to be considered as a TSS candidate. "
        "If --specify_genomes is assigned, please input --height based on "
        "the order of --specify_genomes. Ex: if --specify_genomes is s1 s2 "
        "and --height is 0.3 0.4, it means the height of s1 is 0.3 and "
        "the height of s2 is 0.4. Default is 0.3.")
    TSSpredator_add.add_argument(
        "--height_reduction", "-rh", default=[0.2], nargs="+",
        help="When comparing different genomes/conditions and "
	"the step height threshold is reached in at least one "
        "genome/condition, the threshold is reduced for the other "
        "genomes/conditions by the value set here. "
        "This value must be smaller than the step height threshold. "
        "If --specify_genomes is assigned, please input --height_reduction "
        "based on the order of --specify_genomes like the statement of "
        "--height. Default is 0.2.")
    TSSpredator_add.add_argument(
        "--factor", "-fa", default=[2.0], nargs="+",
        help="This is the minimal factor by which the TSS height has to "
	"exceed the local expression background. If --specify_genomes is "
        "assigned, please input --factor based on the order of "
        "--specify_genomes like the statement of --height. Default is 2.0.")
    TSSpredator_add.add_argument(
        "--factor_reduction", "-rf", default=[0.5], nargs="+",
        help="When comparing different genomes/conditions and "
        "the step factor threshold is reached in at least one "
        "genome/condition, the threshold is reduced for the other "
        "genomes/conditions by the value set here. "
        "This value must be smaller than the step factor threshold. "
        "If --specify_genomes is assigned, please input --factor_reduction "
        "based on the order of --specify_genomes like the statement of "
        "--height. Default is 0.5.")
    TSSpredator_add.add_argument(
        "--enrichment_factor", "-ef", default=[2.0], nargs="+",
        help="This is the minimal enrichment factor. If --specify_genomes is "
        "assigned, please input --enrichment_factor "
        "based on the order of --specify_genomes like the statement of "
        "--height. Default is 2.0.")
    TSSpredator_add.add_argument(
        "--processing_factor", "-pf", default=[1.5], nargs="+",
        help="This is the minimal processing factor. If untreated library "
        "is higher than the treated library and above which the TSS candidate "
        "is considered as a processing site and not annotated as detected. "
        "If --specify_genomes is assigned, please input --processing_factor "
        "based on the order of --specify_genomes like the statement of "
        "--height. Default is 1.5.")
    TSSpredator_add.add_argument(
        "--base_height", "-bh", default=[0], nargs="+",
        help="This is the minimal number of reads should be mapped on TSS. "
        "If --specify_genomes is assigned, please input --base_height "
        "based on the order of --specify_genomes like the statement of "
        "--height.Default is 0.0.")
    TSSpredator_add.add_argument(
        "--utr_length", "-u", default=300, type=int,
        help="The length of UTR. It is for Primary and Secondary TSSs. "
        "Default is 300.")
    TSSpredator_add.add_argument(
        "--fuzzy", "-fu", default=5, type=int,
        help="If --compare_transcript_files is provided, please assign "
        "the fuzzy for comparing TSS and transcript. Default is 5.")
    TSSpredator_add.add_argument(
        "--cluster", "-c", default=2, type=int,
        help="This value defines the maximal distance (nucleotides) between "
        "TSS candidates have to be clustered together. If the distance "
        "between these multiple TSSs is smaller or equal to this value, "
        "only one of them will be printed out. Default is 2.")
    TSSpredator_add.add_argument(
        "--manual_files", "-m", default=None, nargs='+',
        help="If gff files of the manual checked TSS are provided, this "
        "function will merge manual checked ones and TSSpredator predicted "
        "ones. Please assign the path of manual-checked TSS gff files.")
    TSSpredator_add.add_argument(
        "--genome_lengths", "-le", default=None, nargs='+',
        help="If --manual_files is assigned, Please specify the genome length "
        "of input genomes. If you want to compare whole genome, please type "
        "\"all\". The input format is $GENOME:SLENGTH. Multiple genomes "
        "can be accepted, please use spaces to separate them. For an example, "
        "test.gff contain two genomes (s1 and s2). s1 was manual checked "
        "100kb and s2 was checked whole genome. The value of this argument "
        "will be s1:100000 s2:all. Default setting will compute all genomes "
        "in manual-detected TSS gff files with whole length of genome.")
    TSSpredator_add.add_argument(
        "--validate_gene", "-v", default=False, action="store_true",
        help="Using TSS candidates to validate genes in annotation file. "
        "it will be store in statistics folder. Default is False.")
    TSSpredator_add.add_argument(
        "--compare_transcript_files", "-ta", default=None, nargs='+',
        help="If the paths of transcript gff files are provided, this "
        "function will compare TSS and transcript to obtain the overlap "
        "information. Default is False. ")
    TSSpredator_add.add_argument(
        "--re_check_orphan", "-ro", default=False, action="store_true",
        help="If there is no information of gene or locus_tag in genome "
        "annotation gff file, all TSSs will be assigned to orphan TSSs by "
        "TSSpredator. The function can compare TSSs with CDSs to classify "
        "the TSS correctly. Default is False.")
    TSSpredator_add.add_argument(
        "--overlap_feature", "-of", default="both",
        help="If processing site and TSS are overlap, you can keep \"TSS\" "
        "or \"processing_site\" or \"both\". Default is both.")
    TSSpredator_add.add_argument(
        "--reference_gff_files", "-rg", default=None, nargs='+',
        help="If --overlap_feature is \"TSS\" or \"processing_site\", "
        "--reference_gff_files need to be assigned. For TSS, please assign "
        "the folder of processing site. For processing_site, please assign "
        "the folder of TSS. If --overlap_feature is \"both\", please don't "
        "use this function (Default). Default is None (keep both).")
    TSSpredator_add.add_argument(
        "--remove_low_expression", "-rl", default=None,
        help="If you want to remove low expressed TSS/processing site, please "
        "assign the file of manual-checked gff file here. This function will "
        "remove the low expressed ones based on comparison of manual-checked "
        "ones and predicted ones. BE CAREFUL: This function may remove some "
        "True positives as sell. Please make sure you want to do it.")
    TSSpredator_parser.set_defaults(func=run_TSSpredator)
    # Parameter of optimization of TSSpredator
    op_TSSpredator_parser = subparsers.add_parser(
        "optimize_tss_ps", help="Optimize TSSs or processing "
        "sites based on manual detected ones.")
    op_TSSpredator_basic = op_TSSpredator_parser.add_argument_group(
        'basic arguments')
    op_TSSpredator_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    op_TSSpredator_basic.add_argument(
        "--program", "-p", default="TSS",
        help="The feature for optimization. Please assign \"TSS\" or "
        "\"Processing_site\". Default is TSS.")
    op_TSSpredator_basic.add_argument(
        "--fasta_files", "-f", nargs='+', required=True,
        help="Paths of the fasta file that you want to optimize.")
    op_TSSpredator_basic.add_argument(
        "--annotation_files", "-g", nargs='+', required=True,
        help="Paths of the query genome annotation gff file.")
    op_TSSpredator_basic.add_argument(
        "--manual_files", "-m", nargs='+', required=True,
        help="Paths of the manual-checked gff files. It is the benchmark for "
        "training. Please detect the TSSs/processing sites at least "
        "200kb or 50 true TSSs/processing sites.")
    op_TSSpredator_basic.add_argument(
        "--genome_lengths", "-le", default=None, nargs='+',
        help="Please specify the genome length of input genomes in the "
        "manual-detected TSS gff files. If the genome was manual detected "
        "for compare whole genome, please type \"all\". The input format "
        "is $GENOME:SLENGTH. Multiple genomes "
        "can be accepted, please use spaces to separate them. For an example, "
        "test.gff contain two genomes (s1 and s2). s1 was manual checked "
        "100kb and s2 was checked whole genome. The value of this argument "
        "will be s1:100000 s2:all. Default setting will compute all genomes "
        "in manual-detected TSS gff files with whole length of genome.")
    op_TSSpredator_basic.add_argument(
        "--tex_notex_libs", "-tl", required=True, nargs='+',
        help="TEX+/- wig files for TSSpredator. The format is: "
        "wig_file_path:TEX+/-(tex or notex):condition_id(integer):"
        "replicate_id(alphabet):strand(+ or -). If multiple wig files need "
        "to be assigned, please use spaces to separate the wig files. "
        "For an example, $WIG_PATH_1:tex:1:a:+ $WIG_PATH_2:tex:1:a:-.")
    op_TSSpredator_basic.add_argument(
        "--replicate_tex", "-rt", default=["all_1"], nargs='+',
        help="This value is the minimal number of replicates that a TSS has "
        "to be detected. The format is $NUMBERofCONDITION_$NUMBERofREPLICATE. "
        "If different --replicate_tex values need to be assigned to "
        "different conditions, please use spaces to separate them. "
        "For an example, 1_2 2_2 3_3. It means that --replicate_tex is 2 in "
        "number 1 and number 2 conditions. In number 3 condition, "
        "--replicate_tex is 3. For assigning the same --replicate_tex to all "
        "conditions, just use like all_1 (--replicate_tex is 1 in all "
        "conditions). Default is all_1.")
    op_TSSpredator_basic.add_argument(
        "--condition_names", "-cn", required=True, nargs='+',
        help="The output prefixes of all conditions. "
        "If multiple conditions need to be assigned, please use spaces to "
        "separate them. For an example, prefix_condition1 prefix_condition2.")
    op_TSSpredator_add = op_TSSpredator_parser.add_argument_group(
        'additional arguments')
    op_TSSpredator_add.add_argument(
        "--tsspredator_path", default="/usr/local/bin/TSSpredator.jar",
        help="If you want to assign the path of TSSpredator, please "
        "assign here. Default is /usr/local/bin/TSSpredator.jar")
    op_TSSpredator_add.add_argument(
        "--max_height", "-he", default=2.5, type=float,
        help="This value relates to the minimum number of read starts at a "
        "certain genomic position to be considered as a TSS candidate. "
        "During optimization, --max_height will be never larger than this "
        "value. Default is 2.5.")
    op_TSSpredator_add.add_argument(
        "--max_height_reduction", "-rh", default=2.4, type=float,
        help="When comparing different genomes/conditions and the step "
        "height threshold is reached in at least one genome/condition, "
        "the threshold is reduced for the other genomes/conditions "
        "by the value set here. This value must be smaller than the step "
        "height threshold. During optimization, --max_height_reduction will "
        "be never larger than this value. Default is 2.4.")
    op_TSSpredator_add.add_argument(
        "--max_factor", "-fa", default=10, type=float,
        help="This is the minimum factor by which the TSS height has to "
        "exceed the local expression background. During optimization, "
        "--max_factor will be never larger than this value. Default is 10.")
    op_TSSpredator_add.add_argument(
        "--max_factor_reduction", "-rf", default=9.9, type=float,
        help="When comparing different genomes/conditions and the step factor "
        "threshold is reached in at least one genome/condition, "
        "the threshold is reduced for the other genomes/conditions "
        "by the value set here. This value must be smaller than the step "
        "factor threshold. During optimization, --max_factor_reduction will "
        "be never larger than this value. Default is 9.9.")
    op_TSSpredator_add.add_argument(
        "--max_base_height", "-bh", default=0.06, type=float,
        help="This is the minimum number of reads should be mapped on TSS. "
        "During optimization, --max_base_height will be never larger than "
        "this value. Default is 0.06.")
    op_TSSpredator_add.add_argument(
        "--max_enrichment_factor", "-ef", default=6.0, type=float,
        help="This is the minimum enrichment factor. "
        "During optimization, --max_enrichment_factor will be never larger "
        "than this value. Default is 6.0.")
    op_TSSpredator_add.add_argument(
        "--max_processing_factor", "-pf", default=6.0, type=float,
        help="This is the minimum processing factor. If untreated library is "
        "higher than the treated library and above which the TSS candidate "
        "is considered as a processing site and not annotated as detected. "
        "During optimization, --max_processing_factor will be never larger "
        "than this value. Default is 6.0")
    op_TSSpredator_add.add_argument(
        "--utr_length", "-u", default=300, type=int,
        help="The length of UTR. It is for Primary and Secondary TSSs. "
        "Default is 300.")
    op_TSSpredator_add.add_argument(
        "--cluster", "-cu", default=2, type=int,
        help="This value defines the maximal distance (nucleotides) between "
        "TSS candidates have to be clustered together. If the distance "
        "between these multiple TSSs is smaller or equal to this value, "
        "only one of them will be printed out. Default is 2.")
    op_TSSpredator_add.add_argument(
        "--parallels", "-c", type=int, default=4,
        help="Parallel runs for optimization. Default is 4.")
    op_TSSpredator_add.add_argument(
        "--steps", "-s", default=4000, type=int,
        help="The total runs for optimization. Default is 4000 runs.")
    op_TSSpredator_parser.set_defaults(func=optimize_TSSpredator)
    # Parameter of Terminator
    Terminator_parser = subparsers.add_parser(
        "terminator", help="Detect rho-independent terminators.")
    Terminator_basic = Terminator_parser.add_argument_group(
        'basic arguments')
    Terminator_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    Terminator_basic.add_argument(
        "--fasta_files", "-f", required=True, nargs='+',
        help="Paths of the genome fasta files.")
    Terminator_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of the genome annotation gff files.")
    Terminator_basic.add_argument(
        "--transcript_files", "-a", required=True, nargs='+',
        help="Paths of the transcript gff files.")
    Terminator_basic.add_argument(
        "--tex_notex_libs", "-tl", default=None, nargs='+',
        help="If the libraries of TEX+/- can be provided, please assign the "
        "name of TEX+/- library. The format is: wig_file_path:TEX+/-(tex or "
        "notex):condition_id(integer):replicate_id(alphabet):strand(+ or -). "
        "If multiple wig files need to be assigned, please use spaces to "
        "separate the wig files. For an example, "
        "$WIG_PATH_1:tex:1:a:+ $WIG_PATH_2:tex:1:a:-.")
    Terminator_basic.add_argument(
        "--frag_libs", "-fl", default=None, nargs='+',
        help="If the fragmented (or conventional) libraries can be provided, "
        "please assign the "
        "name of fragmented library. The format is: wig_file_path:fragmented("
        "frag):condition_id(integer):replicate_id(alphabet):strand(+ or -). "
        "If multiple wig files need to be assigned, please use spaces to "
        "separate the wig files. For an example, "
        "$WIG_PATH_1:frag:1:a:+ $WIG_PATH_2:frag:1:a:-.")
    Terminator_basic.add_argument(
        "--tex_notex", "-te", default=1, type=int,
        help="If the libraries of TEX+/- can be provided, please assign this "
        "value as well. This value is that the terminator should be detected "
        "in both (TEX+ and TEX-) or can be detected in only one library "
        "(TEX+ or TEX-). Please assign 1 or 2. Default is 1.")
    Terminator_basic.add_argument(
        "--replicate_tex", "-rt", default=None, nargs='+',
        help="This value (for TEX+/- libraries) is the minimal number of "
        "replicates that a terminator has to be detected. "
        "The format is $NUMBERofCONDITION_$NUMBERofREPLICATE. "
        "If different --replicate_tex values need to be assigned to different "
        "conditions, please use spaces to separate them. For an example, "
        "1_2 2_2 3_3. It means that --replicate_tex is 2 in number 1 and "
        "number 2 conditions. In number 3 condition, --replicate_tex is 3. "
        "For assigning the same --replicate_tex to all conditions, "
        "just use ""like all_1 (--replicate_tex is 1 in all conditions). "
        "Default is all_1.")
    Terminator_basic.add_argument(
        "--replicate_frag", "-rf", default=None, nargs='+',
        help="The meaning and input type is the same as --replicates_tex. "
        "This value is for fragmented (or conventional) libraries.")
    Terminator_add = Terminator_parser.add_argument_group(
        'additional arguments')
    Terminator_add.add_argument(
        "--transterm_path", default="transterm",
        help="Please assign the path of \"transterm\" in TransTermHP.")
    Terminator_add.add_argument(
        "--expterm_path", default="/usr/local/bin/expterm.dat",
        help="Please assign the path of expterm.dat for TransTermHP. "
        "Default is /usr/local/bin/expterm.dat")
    Terminator_add.add_argument(
        "--rnafold_path", default="RNAfold",
        help="If you want to assign the path of \"RNAfold\" of Vienna package, "
        "please assign here.")
    Terminator_add.add_argument(
        "--srna_files", "-sr", default=None, nargs='+',
        help="If you want to include sRNA information to detect terminator, "
        "please assign the paths of sRNA gff files.")
    Terminator_add.add_argument(
        "--decrease", "-d", default=0.5, type=float,
        help="This value is maximum ratio -- (lowest coverage / highest "
        "coverage) within (or nearby) the terminator. If the ratio is smaller "
        "than --decrease, the candidate will be considered as the terminator "
        "which has coverage dramatic decreasing. Default is 0.5.")
    Terminator_add.add_argument(
        "--fuzzy_detect_coverage", "-fc", default=30, type=int,
        help="This value is the extended region (nucleotides) of the "
        "terminators for detecting coverage significant decreasing. "
        "Ex: the location of terminator is 300-400, and "
        "--fuzzy_detect_coverage is 30. If the coverage decrease is detected "
        "within 270-430, this candidate will be still considered as the "
        "terminator which have coverage dramatic decrease. Default is 30.")
    Terminator_add.add_argument(
        "--fuzzy_within_transcript", "-fut", default=30, type=int,
        help="If the candidates are within transcript and the distance "
        "(nucleotides) between the end of gene/transcript and terminator is "
        "within this value, the candidate will be considered as a terminator. "
        "Otherwise, it will be removed. Default is 30.")
    Terminator_add.add_argument(
        "--fuzzy_downstream_transcript", "-fdt", default=30, type=int,
        help="The meaning is similar to --fuzzy_within_transcript. "
        "This value ""is for the candidates which are downstream of "
        "transcript. Default is 30.")
    Terminator_add.add_argument(
        "--fuzzy_within_gene", "-fuc", default=10, type=int,
        help="The meaning is similar to --fuzzy_within_transcript. "
        "This value is for gene in stead of transcript. Default is 10.")
    Terminator_add.add_argument(
        "--fuzzy_downstream_gene", "-fdg", default=310, type=int,
        help="The meaning is similar to --fuzzy_downstream_transcript. "
        "This value is for gene in stead of transcript. Default is 310.")
    Terminator_add.add_argument(
        "--highest_coverage", "-hc", default=10, type=float,
        help="The highest coverage of terminator must be higher than this "
        "value. The low expressed terminator will not be included in "
        "\"best_candidates\", but still in \"all_candidates\". Default is 10.")
    Terminator_add.add_argument(
        "--table_best", "-tb", default=False, action="store_true",
        help="Output table only contains the information of the library which "
        "has most significant coverage decrease. Default is False.")
    Terminator_add.add_argument(
        "--window_size", "-wz", default=100, type=int,
        help="Window size for searching secondary structure of intergenic "
        "region. Default is 100 nts.")
    Terminator_add.add_argument(
        "--window_shift", "-ws", default=20, type=int,
        help="The number of nucleotides for window shift. Default is 20 nts.")
    Terminator_add.add_argument(
        "--min_loop_length", "-ml", default=3, type=int,
        help="The minimum loop length of terminator. Default is 3 nts.")
    Terminator_add.add_argument(
        "--max_loop_length", "-Ml", default=10, type=int,
        help="The maximum loop length of terminator. Default is 10 nts.")
    Terminator_add.add_argument(
        "--min_stem_length", "-ms", default=4, type=int,
        help="The minimum stem length of terminator. Default is 4 nts.")
    Terminator_add.add_argument(
        "--max_stem_length", "-Ms", default=20, type=int,
        help="The maximum stem length of terminator. Default is 20 nts.")
    Terminator_add.add_argument(
        "--miss_rate", "-mr", default=0.25, type=float,
        help="The percentage of nucleotides which can be no pair in the stem. "
        "Default is 0.25.")
    Terminator_add.add_argument(
        "--min_u_tail_length", "-mu", default=3, type=int,
        help="The minimum U-tail length of terminator. Default is 3 nts.")
    Terminator_add.add_argument(
        "--range_u_tail", "-ru", default=6, type=int,
        help="The range (nucleotides) for detection of U-tail. For an example, "
        "if --range_u_tail is 6 and --min_u_tail_length is 3, "
        "and there are 3 Us within 6 nts, This candidate will be assigned as "
        "the terminator which has poly U-tail. Default is 6.")
    Terminator_add.add_argument(
        "--keep_multi_term", "-kp", default=False, action="store_true",
        help="Sometimes, one gene is associated with more terminator "
        "candidates. In default, it will only keep the high confident one. "
        "This function can keep all terminators which associated with the "
        "same gene. Default is False.")
    Terminator_parser.set_defaults(func=run_Terminator)

    # Parameter of Transcript
    Transcript_parser = subparsers.add_parser(
        "transcript", help="Detect transcripts based on "
        "coverage file.")
    Transcript_basic = Transcript_parser.add_argument_group(
        'basic arguments')
    Transcript_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    Transcript_basic.add_argument(
        "--annotation_files", "-g", default=None, nargs='+',
        help="If paths of the genome annotation gff files.")
    Transcript_basic.add_argument(
        "--modify_transcript", "-mt", default=["merge_overlap"], nargs='+',
        help="If --annotation_files is provided, you can assign how to "
        "modify the transcripts by genome annotations. There are five "
        "opetions. 1. \"merge_overlap\": if multiple transcripts overlap "
        "the same gene, they will be merged as one complete transcript. "
        "2. \"extend_3end\": if the transcript starts at the "
        "upstream of the gene and ends within the gene, the end point of the "
        "transcript will be extended to the end point of gene. "
        "3. \"extend_5end\": if the transcript starts within the gene and "
        "ends at the downstream of gene, the starting point of the "
        "transcript will be extended to the starting point of the gene. "
        "4. \"within_extend_ends\": if the transcript is within the gene, "
        "the two ends of the transcript will be extended to the two ends of "
        "gene. 5. \"none\": the transcript will not be modified by the genome "
        "annotations. If you want to assign mutliple modifications to this "
        "function, please use spaces to separated them. "
        "Default is merge_overlapped.")
    Transcript_basic.add_argument(
        "--tex_notex_libs", "-tl", default=None, nargs='+',
        help="If the TEX+/- libraries can be provided, please assign the "
        "name of TEX+/- library. The format is: wig_file_path:TEX+/-(tex or "
        "notex):condition_id(integer):replicate_id(alphabet):strand(+ or -). "
        "If multiple wig files need to be assigned, please use spaces to "
        "separate the wig files. For an example, "
        "$WIG_PATH_1:tex:1:a:+ $WIG_PATH_2:tex:1:a:-.")
    Transcript_basic.add_argument(
        "--frag_libs", "-fl", default=None, nargs='+',
        help="If the fragmented (or conventional) libraries can be provided, "
        "please assign the "
        "name of fragmented library. The format is: wig_file_path:fragmented("
        "frag):condition_id(integer):replicate_id(alphabet):strand(+ or -). "
        "If multiple wig files need to be assigned, please use spaces to "
        "separate the wig files. For an example, "
        "$WIG_PATH_1:frag:1:a:+ $WIG_PATH_2:frag:1:a:-.")
    Transcript_basic.add_argument(
        "--replicate_tex", "-rt", default=None, nargs='+',
        help="This value (for TEX+/- libraries) is the minimal number of "
        "replicates that a transcript has to be detected. "
        "The format is $NUMBERofCONDITION_$NUMBERofREPLICATE. "
        "If different --replicate_tex values need to be assigned to different "
        "conditions, please use spaces to separate them. For an example, "
        "1_2 2_2 3_3. It means that --replicate_tex is 2 in number 1 and "
        "number 2 conditions. In number 3 condition, --replicate_tex is 3. "
        "For assigning the same --replicate_tex to all conditions, just use "
        "like all_1 (--replicate_tex is 1 in all conditions). "
        "Default is all_1.")
    Transcript_basic.add_argument(
        "--replicate_frag", "-rf", default=None, nargs='+',
        help="The meaning and input type is the same to --replicates_tex. "
        "This value is for fragmented (or conventional) libraries.")
    Transcript_basic.add_argument(
        "--tex_notex", "-te", default=1, type=int,
        help="If the libraries of TEX+/- need to be provided, please assign "
        "this value as well. This value is that a transcript should be "
        "detected in both (TEX+ and TEX-) or can be detected in only one "
        "library (TEX+ or TEX-). Please assign 1 or 2. Default is 1.")
    Transcript_add = Transcript_parser.add_argument_group(
        'additional arguments')
    Transcript_add.add_argument(
        "--length", "-l", default=20, type=int,
        help="The minimum length of the transcript after modifying by genome "
        "annotation. If --annotation_files is assigned, this value will be "
        "for the final output. Otherwise, --width will be the minimum length "
        "for the final output. Default is 20.")
    Transcript_add.add_argument(
        "--height", "-he", default=10, type=int,
        help="The minimum coverage of the transcript. If --tex_notex is 1, "
        "coverage of TEX+ or TEX- libraries should higher than this value. "
        "If --tex_notex is 2, the function will compute the average of "
        "coverage of TEX+ and TEX- libraries, and the average should higher "
        "than the minimum coverage. The default is 10.")
    Transcript_add.add_argument(
        "--width", "-w", default=20, type=int,
        help="The minimum length of the transcript without modifying by "
        "genome annotation. This value will be for the final output if "
        "--annotation_files is not provided. Otherwise, --length would be "
        "the minimum length of the transcript for the final output. "
        "The default is 20.")
    Transcript_add.add_argument(
        "--tolerance", "-t", default=5, type=int,
        help="This value defines the number of nucleotides that coverages "
        "drop below --height can be ignore in one transcript. "
        "The default is 5.")
    Transcript_add.add_argument(
        "--tolerance_coverage", "-tc", default=0, type=int,
        help="If the coverage is lower than tolerance_coverage, even the "
        "length is within --tolerance, the algorithm will still divide the "
        "current transcript to two parts. Default is 0.")
    Transcript_add.add_argument(
        "--tss_files", "-ct", default=None, nargs='+',
        help="If the paths of TSS files are assigned here, this function will "
        "compare transcripts with TSSs to detect the overlap.")
    Transcript_add.add_argument(
        "--compare_feature_genome", "-cf", default=None, nargs='+',
        help="If --compare_genome_annotation is provided, please assign the "
        "feature which you want to compare. Default is None. "
        "If multiple features need to be assigned, just insert spaces "
        "between each feature, such as gene CDS.")
    Transcript_add.add_argument(
        "--tss_fuzzy", "-tf", default=5, type=int,
        help="If --compare_TSS is assigned, please type the fuzzy for "
        "comparing TSS with transcript here. Default is 5.")
    Transcript_add.add_argument(
        "--table_best", "-tb", default=False, action="store_true",
        help="The output table only includes the information of the highest "
        "expressed library. Default is False.")
    Transcript_add.add_argument(
        "--terminator_files", "-e", default=None, nargs='+',
        help="If the paths of terminator gff files are assigned here, "
        "this function will compare transcripts with terminators to detect "
        "the parent transcript of terminator. Default is None.")
    Transcript_add.add_argument(
        "--terminator_fuzzy", "-ef", default=30, type=int,
        help="If --terminator_files is assigned, please assign the fuzzy "
        "here. Default is 30.")
    Transcript_add.add_argument(
        "--max_length_distribution", "-mb", default=2000, type=int,
        help="For generating the figure of distribution of transcript length, "
        "please assign the maximum length that you want to include. "
        "Default is 2000.")
    Transcript_parser.set_defaults(func=run_Transcript_Assembly)

    # Parameter of UTR detection
    UTR_parser = subparsers.add_parser(
        "utr", help="Detect 5'UTRs and 3'UTRs.")
    UTR_basic = UTR_parser.add_argument_group(
        'basic arguments')
    UTR_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    UTR_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of the genome annotation gff files.")
    UTR_basic.add_argument(
        "--tss_files", "-t", required=True, nargs='+',
        help="Paths of the TSS files.")
    UTR_basic.add_argument(
        "--transcript_files", "-a", required=True, nargs='+',
        help="Paths of the transcript gff files.")
    UTR_basic.add_argument(
        "--terminator_files", "-e", default=None, nargs='+',
        help="If the paths of terminator files are assigned here, "
        "this function will also apply terminator to detect 3'UTR.")
    UTR_add = UTR_parser.add_argument_group(
        'additional arguments')
    UTR_add.add_argument(
        "--tss_source", "-s", default=True, action="store_false",
        help="The TSS gff file is generated by ANNOgesic or not. "
        "If the TSS file is not generated by ANNOgesic, this function will "
        "classify the TSSs for detecting UTRs. Default is True "
        "(from ANNOgesic).")
    UTR_add.add_argument(
        "--base_5utr", "-b5", default="both",
        help="Please assign the information for detection of 5'UTR. "
        "It can be \"TSS\" or \"transcript\" or \"both\". Default is both.")
    UTR_add.add_argument(
        "--utr_length", "-l", default=300, type=int,
        help="The maximum UTR length. Default is 300.")
    UTR_add.add_argument(
        "--base_3utr", "-b3", default="transcript",
        help="please assign the information for detection of 3'UTR. It can "
        "be \"transcript\" or \"terminator\" or \"both\". "
        "Default is transcript.")
    UTR_add.add_argument(
        "--terminator_fuzzy", "-ef", default=30, type=int,
        help="This is only for --base_3utr which is assigned by \"transcript\" "
        "or \"both\", and terminator file are provided. "
        "If the distance (nucleotides) between terminator and the end of "
        "transcript is lower than this value, the terminator is consider to "
        "be associated with the 3'UTR. Default is 30.")
    UTR_add.add_argument(
        "--fuzzy_3utr", "-f3", default=10, type=int,
        help="If --base_3utr includes transcript, please assign the fuzzy of "
        "3'UTR. Default is 10 nucleotides.")
    UTR_add.add_argument(
        "--fuzzy_5utr", "-f5", default=5, type=int,
        help="If --base_5utr includes transcript, please assign the fuzzy of "
        "5'UTR. Default is 5 nucleotides.")
    UTR_parser.set_defaults(func=run_UTR_detection)

    # Parameter of sRNA detection
    sRNA_parser = subparsers.add_parser(
        "srna", help="Detect intergenic, antisense and UTR-derived sRNAs.")
    sRNA_basic = sRNA_parser.add_argument_group(
        'basic arguments')
    sRNA_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    sRNA_basic.add_argument(
        "--utr_derived_srna", "-u", default=False, action="store_true",
        help="The function is for detecting UTR-derived sRNA. "
        "Default is False.")
    sRNA_basic.add_argument(
        "--filter_info", "-d",
        default=["tss", "sec_str", "blast_nr", "blast_srna"], nargs='+',
        help="There are several filters that you can use to improve sRNA "
        "detection: 1. tss (sRNA has to start with TSS), 2. sec_str "
        "(free energy change of secondary structure (normalized by length) "
        "has to be smaller than --cutoff_energy), 3. blast_nr (the number "
        "of the homology can not be found more than --cutoff_nr_hit in the "
        "non-redundant database), 4. blast_srna (as long as the homology "
        "can be found in sRNA database, the candidates will be included to "
        "best candidtes without considering other filters), 5. sorf (sRNA can "
        "not overlap sORF), 6. term (sRNA has to be associated with a "
        "terminator), 7. promoter (sRNA has to be associated with a promoter "
        "motif). ATTENTION: without importing any information, the results "
        "may include many false positives. If multiple filters needs to be "
        "assigned, please use spaces to separated them. "
        "ex: tss sec_str blast_nr - means it used 1. TSS, 2. free energy "
        "change of secondary structure and 3. blast to nr database to detect "
        "sRNA. If you want to use blast_srna as a filter, "
        "please follow the format: $ID|$GENOME|$SRNANAME. \"tss sec_str "
        "blast_nr blast_srna\" is recommended to be assigned. If you don't "
        "want to use any filters, please assign \"none\". "
        "Default is tss sec_str blast_nr blast_srna.")
    sRNA_basic.add_argument(
        "--transcript_files", "-a", required=True, nargs='+',
        help="Paths of the transcript files.")
    sRNA_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of the genome annotation gff files.")
    sRNA_basic.add_argument(
        "--tss_files", "-t", default=None, nargs='+',
        help="If the paths of TSS gff files are assigned here, TSS "
        "information will be used for detecting sRNA. "
        "If you want to detect UTR-derived sRNA or \"tss\" in --filter_info, "
        "TSS gff files MUST be provided.")
    sRNA_basic.add_argument(
        "--processing_site_files", "-p", default=None, nargs='+',
        help="If the paths of processing site gff files are assigned here, "
        "processing site information will be used for detecting sRNA. "
        "For detection of UTR-derived sRNA, processing site information can "
        "improve the results.")
    sRNA_basic.add_argument(
        "--terminator_files", "-e", default=None, nargs='+',
        help="If terminator information can be provided, please assign the paths "
        "of gff files of terminators. If \"term\" in --filter_info, "
        "terminator gff files MUST be provided.")
    sRNA_basic.add_argument(
        "--fasta_files", "-f", default=None, nargs='+',
        help="If \"sec_str\" or \"blast_nr\" or \"blast_srna\" is assigned to "
        "--filter_info, fasta files MUST be assigned here. ")
    sRNA_basic.add_argument(
        "--compute_sec_structures", "-cs", default=False, action="store_true",
        help="Compute secondary structures of sRNAs. Default is False.")
    sRNA_basic.add_argument(
        "--promoter_tables", "-pt", default=None, nargs='+',
        help="If the paths of promoter tables can be provided, please assign "
        "the paths of promoter tables here. If \"promoter\" in --filter_info, "
        "the promoter tables MUST be assigned. "
        "The format of table is "
        "$GENOME\t$TSS_POSITION\t$TSS_STRAND\t$PROMOTER_NAME. "
        "TSS information is also required.")
    sRNA_basic.add_argument(
        "--promoter_names", "-pn", default=None, nargs='+',
        help="If --promoter_tables is provided, please assign the promoter "
        "name (the last column of promoter table) which you want to compare. "
        "If multiple promoters need to be assigned, please put spaces "
        "between the promoters. Default is None.")
    sRNA_basic.add_argument(
        "--sorf_files", "-O", default=None, nargs='+',
        help="If the paths of sORF gff files can be provided, please assign "
        "the paths of sORF gff files here. If \"sorf\" in --filter_info, "
        "sORF gff files MUST is assigned.")
    sRNA_basic.add_argument(
        "--srna_database_path", "-sd", default=None,
        help="If sRNA database can be provided, please assign here. "
        "If \"blast_srna\" is included in --filter_info, "
        "please assign the path of sRNA database with proper header. "
        "Format of the header should be $ID|$GENOME|$NAME "
        "For an example of the proper header, please check "
        "https://github.com/Sung-Huan/ANNOgesic/blob/"
        "master/database/sRNA_database_BSRD.fa")
    sRNA_basic.add_argument(
        "--nr_database_path", "-nd", default=None,
        help="If nr database can be provided, please assign here. "
        "If \"blast_nr\" is included in --filter_info, "
        "please assign the path of nr database.")
    sRNA_basic.add_argument(
        "--tex_notex_libs", "-tl", default=None, nargs='+',
        help="If TEX+/- libraries can be provided, please assign the "
        "name of TEX+/- libraries here. The format is: "
        "wig_file_path:TEX+/-(tex or notex):condition_id(integer):"
        "replicate_id(alphabet):strand(+ or -). "
        "If multiple wig files need to be assigned, please use spaces to "
        "separate the wig files. For an example, "
        "$WIG_PATH_1:tex:1:a:+ $WIG_PATH_2:tex:1:a:-.")
    sRNA_basic.add_argument(
        "--frag_libs", "-fl", default=None, nargs='+',
        help="If fragmented (or conventional) libraries can be provided, "
        "please assign the name "
        "of fragmented libraries here. The format is: "
        "wig_file_path:fragmented(frag):condition_id(integer):replicate_id("
        "alphabet):strand(+ or -). If multiple wig files need to be assigned, "
        "please use spaces to separate the wig files. For an example, "
        "$WIG_PATH_1:frag:1:a:+ $WIG_PATH_2:frag:1:a:-.")
    sRNA_basic.add_argument(
        "--tex_notex", "-te", default=2, type=int,
        help="If TEX+/- libraries is assigned, this value is that a sRNA "
        "should be detected in both (TEX+ and TEX-) or can be detected in "
        "only one library (TEX+ or TEX-). "
        "Please assign 1 or 2. Default is 2.")
    sRNA_basic.add_argument(
        "--replicate_tex", "-rt", default=None, nargs='+',
        help="This value (for TEX+/- libraries) is the minimal number of "
        "replicates that a sRNA has to be detected. "
        "The format is $NUMBERofCONDITION_$NUMBERofREPLICATE. "
        "If different --replicate_tex values need to be assigned to different "
        "conditions, please use spaces to separate them. For an example, "
        "1_2 2_2 3_3. It means that --replicate_tex is 2 in number 1 and "
        "number 2 conditions. In number 3 condition, --replicate_tex is 3. "
        "For assigning the same --replicate_tex to all conditions, just use "
        "like all_1 (--replicate_tex is 1 in all conditions). "
        "Default is all_1.")
    sRNA_basic.add_argument(
        "--replicate_frag", "-rf", default=None, nargs='+',
        help="The meaning and input type is the same as --replicates_tex. "
        "This value is for fragmented (or conventional) libraries.")
    sRNA_add = sRNA_parser.add_argument_group(
        'additional arguments')
    sRNA_add.add_argument(
        "--rnafold_path", default="RNAfold",
        help="Please assign RNAfold path.")
    sRNA_add.add_argument(
        "--relplot_path", default="relplot.pl",
        help="Please assign the path of relplot.pl in Vienna package.")
    sRNA_add.add_argument(
        "--mountain_path", default="mountain.pl",
        help="Please assign the path of mountain.pl in Vienna package.")
    sRNA_add.add_argument(
        "--blastn_path", default="blastn",
        help="Please assign the path of blastn in blast+ package.")
    sRNA_add.add_argument(
        "--blastx_path", default="blastx",
        help="Please assign the path of blastx in blast+ package.")
    sRNA_add.add_argument(
        "--makeblastdb_path", default="makeblastdb",
        help="Please assign the path of makeblastdb in blast+ package.")
    sRNA_add.add_argument(
        "--ps2pdf14_path", default="ps2pdf14",
        help="Please assign the path of ps2pdf14.")
    sRNA_add.add_argument(
        "--parallel_blast", "-pb", type=int, default=10,
        help="How many parallels that you want to use for blast. "
        "Default is 10.")
    sRNA_add.add_argument(
        "--tss_source", "-ts", default=True, action="store_false", 
        help="If the TSS gff file is not generated by ANNOgesic, "
        "please use this function to classify TSSs and generate the proper "
        "format for sRNA prediction. Default is True (from ANNOgesic).")
    sRNA_add.add_argument(
        "--tss_intergenic_fuzzy", "-ft", default=3, type=int,
        help="If --tss_files is provided, please assign the fuzzy for "
        "comparing TSS with transcript. It is for intergenic sRNA. "
        "Default is 3.")
    sRNA_add.add_argument(
        "--tss_5utr_fuzzy", "-f5", default="n_3", type=str,
        help="If --tss_files is provided, please assign the fuzzy for "
        "comparing TSS with transcript. It is for 5'UTR-derived sRNA."
        "The input type can be percentage (\"p\") or the real amount of reads "
        "(\"n\"). Ex: p_0.05 means the fuzzy is 5 percent of the length of "
        "5'UTR. n_10 means the fuzzy is 10 base pair. Default is n_3.")
    sRNA_add.add_argument(
        "--tss_3utr_fuzzy", "-f3", default="p_0.04", type=str,
        help="The meaning is similar to --tss_5utr_fuzzy. This value is for "
        "3'UTR-derived sRNA instead of 5'UTR-derived sRNA. Default is p_0.04.")
    sRNA_add.add_argument(
        "--tss_intercds_fuzzy", "-fc", default="p_0.04", type=str,
        help="The meaning is similar to --tss_5utr_fuzzy. This value is for "
        "interCDS-derived sRNA instead of 5'UTR-derived sRNA. "
        "Default is p_0.04.")
    sRNA_add.add_argument(
        "--terminator_fuzzy_in_srna", "-efi", default=30, type=int,
        help="If --terminator_files is provided, please assign the fuzzy for "
        "comparing terminator with transcript. "
        "This value is for the terminator which is within sRNA. Default is 30.")
    sRNA_add.add_argument(
        "--terminator_fuzzy_out_srna", "-efo", default=30, type=int,
        help="The meaning is the same as --terminator_fuzzy_in_sRNA. "
        "This value is for the terminator which is outside of sRNA. "
        "Default is 30.")
    sRNA_add.add_argument(
        "--min_length", "-lm",default=30, type=int,
        help="Please assign the minimum sRNA length. Default is 30.")
    sRNA_add.add_argument(
        "--max_length", "-lM",default=500, type=int,
        help="Please assign the maximum sRNA length. Default is 500.")
    sRNA_add.add_argument(
        "--run_intergenic_tex_coverage", "-it",default="0,0,0,40,20",
        help="The minimum average coverage of intergenic sRNA candidates in "
        "TEX+ libraries. This value is based on different types of TSSs. "
        "The order of numbers is \"Primary,Secondary,Internal,Antisense,"
        "Orphan\". Ex: The input is 0,0,0,50,10. It means that antisense TSS "
        "(minimum coverage is 50) and orphan TSS (minimum coverage is 10) "
        "are used for sRNA prediction. The other types of TSSs will not be "
        "used for sRNA detection (assign to 0). If TSS information is not "
        "provided, it will choose the lowest one as a general cutoff for "
        "prediction. Ex: if the input is 0,0,0,50,10 and --tss_files is not "
        "provided, 10 will be the general cutoff for prediction. "
        "Default is 0,0,0,40,20 and each number is separated by commas.")
    sRNA_add.add_argument(
        "--run_intergenic_notex_coverage", "-in",default="0,0,0,30,10",
        help="The meaning is the same as --run_intergenic_tex_coverage. "
        "This value is for TEX- libraries. Default is 0,0,0,30,10 and each "
        "number is separated by commas.")
    sRNA_add.add_argument(
        "--run_intergenic_fragmented_coverage", "-if",default="400,200,0,50,20",
        help="The meaning is the same as --run_intergenic_tex_coverage. "
        "This value is for fragmented (or conventional) libraries. "
        "Default is 400,200,0,50,20 and each number is separated by commas.")
    sRNA_add.add_argument(
        "--run_break_transcript", "-ib",default="30,20,30",
        help="Several primary/secondary TSSs are associated with transcripts "
        "which has no CDSs/tRNA/rRNA inside (perhaps associated with ncRNA). "
        "In order to detect the sRNA candidates in these transcripts, please "
        "assign the minimum average coverage of the sRNA candidates. "
        "The format is $TEX,$NOTEX,$FRAG, ex: 200,100,100 is means that "
        "the minimum average coverage is 200 for TEX+ libraries, 100 for TEX- "
        "and fragmented (or conventional) libraries. Default is 30,20,30 "
        "and each number is separated by commas.")
    sRNA_add.add_argument(
        "--run_antisense_tex_coverage", "-at",default="0,0,0,40,20",
        help="The meaning is the same as --run_intergenic_tex_coverage. "
        "This value is for antisense in stead of intergenic. "
        "Default is 0,0,0,40,20 and each number is separated by commas.")
    sRNA_add.add_argument(
        "--run_antisense_notex_coverage", "-an",default="0,0,0,30,10",
        help="The meaning is the same as --run_intergenic_notex_coverage. "
        "This value is for antisense in stead of intergenic. "
        "Default is 0,0,0,30,10 and each number is separated by commas.")
    sRNA_add.add_argument(
        "--run_antisense_fragmented_coverage", "-af",default="400,200,0,50,20",
        help="The meaning is the same as --run_intergenic_fragmented_coverage. "
        "This value is for antisense in stead of intergenic. "
        "Default is 400,200,0,50,20 and each number is separated by commas.")
    sRNA_add.add_argument(
        "--run_utr_tex_coverage", "-ut",default="p_0.8,p_0.6,p_0.7",
        help="The minimum average coverage of UTR-derived sRNA candidates in "
        "TEX+ libraries. The input can be assigned by the percentile (\"p\") "
        "or real number of coverage (\"n\"). The order of numbers is "
        "\"5'UTR,3'UTR,interCDS\". Ex: if the input is \"p_0.7,p_0.5,p_0.5\", "
        "it will use 70 percentile of 5'UTR coverage as minimum coverage for "
        "5'UTR-derived sRNA, median of 3'UTR and interCDS coverage as minimum "
        "coverage for 3'UTR and interCDS-derived sRNA. Ex: if the input is "
        "\"n_30,n_10,n_20 \" it will use 30 as minimum coverage for "
        "5'UTR-derived sRNA, 10 as minimum coverage for 3'UTR-derived sRNA "
        "and 20 as minimum coverage for interCDS-derived sRNA. "
        "Default is p_0.8,p_0.6,p_0.7 and each number is separated by commas.")
    sRNA_add.add_argument(
        "--run_utr_notex_coverage", "-un",default="p_0.7,p_0.5,p_0.6",
        help="The meaning is the same as --run_utr_tex_coverage. "
        "This value is for TEX- libraries. Default is p_0.7,p_0.5,p_0.6 and "
        "each number is separated by commas.")
    sRNA_add.add_argument(
        "--run_utr_fragmented_coverage", "-uf",default="p_0.7,p_0.5,p_0.6",
        help="The meaning is the same as --run_utr_tex_coverage. "
        "This value is for fragmented (or conventional) libraries. "
        "Default is p_0.7,p_0.5,p_0.6 and each number is separated by commas.")
    sRNA_add.add_argument(
        "--min_utr_coverage", "-mu", default=50, type=float,
        help="The minimum general coverage of UTR-derived sRNA. "
        "The coverage of UTR-derived sRNA should not only fit the "
        "--run_utr_TEX_coverage, --run_utr_noTEX_coverage and "
        "--run_utr_fragmented_coverage, "
        "but also this value. Default is 50.")
    sRNA_add.add_argument(
        "--cutoff_energy", "-ce", default=-0.05, type=float,
        help="If \"sec_str\" is included in --filter_info, please assign the "
        "maximum folding energy change (normalized by length of gene). "
        "Default is -0.05.")
    sRNA_add.add_argument(
        "--mountain_plot", "-m", default=False, action="store_true",
        help="This function will generate mountain plot of sRNA candidate. "
        "Default is False.")
    sRNA_add.add_argument(
        "--nr_format", "-nf", default=False, action="store_true",
        help="This function will format nr database. If the nr database has "
        "formatted, the step can be skip. Default is False.")
    sRNA_add.add_argument(
        "--srna_format", "-sf", default=False, action="store_true",
        help="The meaning is the same as --nr_format. It is for sRNA database "
        "in stead of nr database. Default is False.")
    sRNA_add.add_argument(
        "--table_best", "-tb", default=False, action="store_true",
        help="The output table of sRNA candidates only contains the "
        "information of the highest expressed library. Default is False.")
    sRNA_add.add_argument(
        "--decrease_intergenic_antisense","-di", default=0.1, type=float,
        help="This value is for detecting the coverage decrease in "
        "intergenic/antisense transcript. "
        "If the length of intergenic transcript is longer than the max_length, "
        "it will check the sRNA candidates based on coverage. If the ratio "
        "-- (the lowest coverage / the highest coverage) of the sRNA region "
        "is smaller than this value, the spot of lowest coverage will be "
        "considered as the end point of the sRNA. If the new sRNA length is "
        "suitable for a sRNA candidate, "
        "this candidate will be included in output. Default is 0.1.")
    sRNA_add.add_argument(
        "--decrease_utr","-du", default=0.05, type=float,
        help="This value is for detecting the coverage decrease in UTR region. "
        "The end point of UTR-derived sRNA is defined by processing site or "
        "the end of transcript (3'UTR-derived sRNA). "
        "If there is no processing sites in 5'UTR or interCDS, the algorithm "
        "will check the coverage to detect the end point of sRNA. "
        "If the ratio -- (the lowest coverage / the highest coverage) of the "
        "sRNA region is smaller than this value, "
        "the spot of lowest coverage will be considered as the end point of "
        "the sRNA. If the new sRNA length is suitable for a sRNA candidate, "
        "this candidate will be included in output. Default is 0.05.")
    sRNA_add.add_argument(
        "--fuzzy_intergenic_antisense", "-fi", default=10, type=int,
        help="If the situation is like --decrease_intergenic_antisense "
        "mentioned, This value is the fuzzy nucleotides for detecting the "
        "coverage decrease. Ex: the location of intergenic sRNA is 300-400, "
        "and --fuzzy_intergenic_antisense is 30. The algorithm will search "
        "the coverage decrease within 270-430. Default is 10.")
    sRNA_add.add_argument(
        "--fuzzy_utr", "-fu", default=10, type=int,
        help="It is similar with --fuzzy_intergenic_antisense. "
        "This is for UTR-derived sRNAs. Default is 10.")
    sRNA_add.add_argument(
        "--cutoff_nr_hit", "-cn", default=0, type=int,
        help="The maximum hits number in nr database. Default is 0.")
    sRNA_add.add_argument(
        "--blast_e_nr", "-en", default=0.0001, type=float,
        help="The maximum e value for blast in nr database. Default is 0.0001.")
    sRNA_add.add_argument(
        "--blast_e_srna", "-es", default=0.0001, type=float,
        help="The maximum e value for blast in sRNA database. "
        "Default is 0.0001.")
    sRNA_add.add_argument(
        "--detect_srna_in_cds", "-ds", default=False, action="store_true",
        help="This function will search sRNA in CDS (ex: the genome "
        "annotation is not correct). More sRNA candidates which overlap "
        "with CDS will be detected. Default is False.")
    sRNA_add.add_argument(
        "--overlap_percent_cds", "-oc", default=0.5,
        help="If --detect_srna_in_cds is True, please assign the maximum "
        "ratio of overlap between CDS and sRNA candidates. Default is 0.5")
    sRNA_add.add_argument(
        "--ignore_hypothetical_protein", "-ih", default=False,
        action="store_true",
        help="This function is for ignoring the hypothetical proteins in "
        "genome annotation file. Default is False.")
    sRNA_add.add_argument(
        "--ranking_time_promoter", "-rp", default=2, type=float,
        help="If --promoter_tables is provided, the information of promoter "
        "can be use for ranking sRNA candidates as well. "
        "The ranking score is --ranking_time_promoter * average coverage. "
        "For an example, a sRNA candidate which is associated with promoter and "
        "its average coverage is 10. If --ranking_time_promoter is 2, "
        "the ranking score will be 20 (2*10). "
        "For the candidate which are not associated with promoter, the "
        "--ranking_time_promoter will be 1. Therefore, --ranking_time_promoter "
        "can not be smaller than 1. Default is 2.")
    sRNA_parser.set_defaults(func=run_sRNA_detection)
    # Parameters of small ORF
    sORF_parser = subparsers.add_parser(
        "sorf", help="Detect expressed sORFs.")
    sORF_basic = sORF_parser.add_argument_group(
        'basic arguments')
    sORF_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    sORF_basic.add_argument(
        "--utr_derived_sorf", "-u", default=False, action="store_true",
        help="This function will detect UTR-derived sORF. Default is False.")
    sORF_basic.add_argument(
        "--fasta_files", "-f", required=True, nargs='+',
        help="The paths of genome fasta files. ")
    sORF_basic.add_argument(
        "--transcript_files", "-a", required=True, nargs='+',
        help="Paths of the transcript gff files.")
    sORF_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of the genome annotation gff files.")
    sORF_basic.add_argument(
        "--tss_files", "-t", default=None, nargs='+',
        help="If the paths of TSS gff files are assigned here, "
        "this function will use the TSS information to detect sORF. "
        "If running without TSS, the results may be influenced.")
    sORF_basic.add_argument(
        "--srna_files", "-s", default=None, nargs='+',
        help="If the paths of sRNA gff files can be provided, "
        "this function will compare sORF and sRNA to detect the overlap.")
    sORF_basic.add_argument(
        "--tex_notex_libs", "-tl", default=None, nargs='+',
        help="If the TEX+/- libraries can be provided, please assign the name "
        "of TEX+/- library here. The format is: wig_file_path:TEX+/-(tex or "
        "notex):condition_id(integer):replicate_id(alphabet):strand(+ or -). "
        "If multiple wig files need to be assigned, please use spaces to "
        "separate the wig files. For an example, "
        "$WIG_PATH_1:tex:1:a:+ $WIG_PATH_2:tex:1:a:-.")
    sORF_basic.add_argument(
        "--frag_libs", "-fl", default=None, nargs='+',
        help="If the fragmented (or conventional) libraries can be provided, "
        "please assign the "
        "name of fragmented library here. The format is: "
        "wig_file_path:fragmented(frag):condition_id(integer):replicate_id("
        "alphabet):strand(+ or -). If multiple wig files need to be assigned, "
        "please use spaces to separate the wig files. For an example, "
        "$WIG_PATH_1:frag:1:a:+ $WIG_PATH_2:frag:1:a:-.")
    sORF_basic.add_argument(
        "--tex_notex", "-te", default=2, type=int,
        help="If the TEX+/- libraries is provided, this value is that a "
        "sORF should be detected in both (TEX+ and TEX-) or "
        "can be detected in only one library (TEX+ or TEX-). "
        "Please assign 1 or 2. Default is 2.")
    sORF_basic.add_argument(
        "--replicate_tex", "-rt", default=None, nargs='+',
        help="This value (for TEX+/- libraries) is the minimal number of "
        "replicates that a sORF has to be detected. The format is "
        "$NUMBERofCONDITION_$NUMBERofREPLICATE. If different --replicate_tex "
        "values need to be assigned to different conditions, please use spaces "
        "to separate them. For an example, 1_2 2_2 3_3. It means that "
        "--replicate_tex is 2 in number 1 and number 2 conditions. "
        "In number 3 condition, --replicate_tex is 3. "
        "For assigning the same --replicate_tex to all conditions, just use "
        "like all_1 (--replicate_tex is 1 in all conditions). "
        "Default is all_1.")
    sORF_basic.add_argument(
        "--replicate_frag", "-rf", default=None, nargs='+',
        help="The meaning and input type is the same as --replicates_tex. "
        "This value is for fragmented (or conventional) libraries.")
    sORF_add = sORF_parser.add_argument_group(
        'additional arguments')
    sORF_add.add_argument(
        "--utr_length", "-ul", default=300, type=int,
        help="If --tss_files is provided, please assign the utr length "
        "for comparing TSS with sORF. The default number is 300.")
    sORF_add.add_argument(
        "--min_length", "-lm",default=30,
        help="Please assign the minimum residue length of sORF. Default is 30.")
    sORF_add.add_argument(
        "--max_length", "-lM",default=150,
        help="Please assign the maximum residue length of sORF. "
        "Default is 150.")
    sORF_add.add_argument(
        "--cutoff_intergenic_coverage", "-ci", default=10, type=float,
        help="The minimum coverage of intergenic sORF candidates.")
    sORF_add.add_argument(
        "--cutoff_antisense_coverage", "-ai", default=10, type=float,
        help="The minimum coverage of antisense sORF candidates.")
    sORF_add.add_argument(
        "--cutoff_5utr_coverage", "-cu5", default="p_0.5",
        help="The minimum coverage of 5'UTR derived sORF candidates. "
        "This value can be assigned by percentage (\"p\") or the amount of "
        "reads (\"n\"). Ex: p_0.05 means that the coverage of sORF candidates "
        "should be higher than 5 percentile of all 5'UTR transcripts. "
        "n_10 means that the coverage of sORF candidates should be higher "
        "than 10. Default is p_0.5.")
    sORF_add.add_argument(
        "--cutoff_3utr_coverage", "-cu3", default="p_0.5",
        help="The meaning is the same as --cutoff_5utr_coverage. "
        "This value is for 3'UTR. Default is p_0.5.")
    sORF_add.add_argument(
        "--cutoff_intercds_coverage", "-cuf", default="p_0.5",
        help="The meaning is the same as --cutoff_5utr_coverage. "
        "This value is for interCDS. Default is p_0.5.")
    sORF_add.add_argument(
        "--cutoff_background", "-cub", default=10, type=float,
        help="The general minimum coverage of all sORF candidates. "
        "All candidates should fit this condition as well. Default is 10.")
    sORF_add.add_argument(
        "--table_best", "-tb", default=False, action="store_true",
        help="The output table of sORF candidates only includes information "
        "of the highest expressed library. Default is False.")
    sORF_add.add_argument(
        "--start_codon", "-ac", default=["ATG"], nargs='+',
        help="The types of start coden. If multiple types of start codon "
        "need to be assigned, please use spaces to separate them. "
        "Default is ATG.")
    sORF_add.add_argument(
        "--stop_codon", "-oc", default=["TAA", "TAG", "TGA"], nargs='+',
        help="The types of stop codon. If multiple types of stop codon need "
        "to be assigned, please use spaces to separate them. "
        "Default is TTA TAG TGA.")
    sORF_add.add_argument(
        "--min_rbs_distance", "-mr", default=3, type=int,
        help="The minimum distance (nucleotides) between the ribosome binding "
        "site (Shine-Dalgarno sequence) and start codon. Default is 3.")
    sORF_add.add_argument(
        "--max_rbs_distance", "-Mr", default=15, type=int,
        help="The maximum distance (nucleotides) between the ribosome binding "
        "site (Shine-Dalgarno sequence) and start codon. Default is 15.")
    sORF_add.add_argument(
        "--rbs_not_after_tss", "-at", default=False, action="store_true",
        help="For generating best results, if the ribosome binding site "
        "(Shine-Dalgarno sequence) of "
        "sORF is not associated with TSS, this function will include this "
        "candidate as well. Default is False.")
    sORF_add.add_argument(
        "--fuzzy_rbs", "-zr", default=2, type=int,
        help="The number of nucleotides of Shine-Dalgarno sequence allow be "
        "different with AGGAGG. Default is 2.")
    sORF_add.add_argument(
        "--print_all_combination", "-pa", default=False, action="store_true",
        help="Non-annotated transcript may has many start codons and "
        "stop codons. This function can print all combinations of start "
        "codons and stop codons. Default is False.")
    sORF_add.add_argument(
        "--best_no_srna", "-bs", default=False, action="store_true",
        help="For generating best results, this function can exclude the "
        "sORFs which overlap with sRNA. Default is False.")
    sORF_add.add_argument(
        "--best_no_tss", "-bt", default=False, action="store_true",
        help="For generating best results, this function can include the "
        "sORFs which are not associated with TSS. Default is False.")
    sORF_add.add_argument(
        "--ignore_hypothetical_protein", "-ih", default=False,
        help="This function is for ignoring hypothetical protein in genome "
        "annotation file. Default is False.")
    sORF_parser.set_defaults(func=run_sORF_detection)
    # Parameters of promoter detection
    promoter_parser = subparsers.add_parser(
        "promoter", help="Discover promoter motifs.")
    promoter_basic = promoter_parser.add_argument_group(
        'basic arguments')
    promoter_basic.add_argument(
        "--program", "-p", default="both",
        help="Please assign the program -- meme or glam2 or both. Default is both")
    promoter_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    promoter_basic.add_argument(
        "--fasta_files", "-f", required=True, nargs='+',
        help="Paths of genome fasta files.")
    promoter_basic.add_argument(
        "--tss_files", "-t", required=True, nargs='+',
        help="Paths of TSS gff files.")
    promoter_basic.add_argument(
        "--motif_width", "-w", default=[50], nargs='+',
        help="The length for motif detection. "
        "For detecting a range of length, please insert \"-\" between "
        "two values. Moreover, if multiple motif length need to be assigned, "
        "please use spaces to separate them. For an example, 50 2-10. It means "
        "that the length of motif for detection is 50 and within 2 to 10. "
        "The number should be less or equal than --nt_before_TSS. "
        "Default is 50.")
    promoter_basic.add_argument(
        "--num_motifs", "-n", default=10,
        help="The number of motifs that you want to detect. Default is 10.")
    promoter_basic.add_argument(
        "--nt_before_tss", "-b", default=50, type=int,
        help="The number of upstream nucleotides of TSS for promoter "
        "prediction. Default is 50.")
    promoter_add = promoter_parser.add_argument_group(
        'additional arguments')
    promoter_add.add_argument(
        "--meme_path", default="meme",
        help="path of MEME.")
    promoter_add.add_argument(
        "--glam2_path", default="glam2",
        help="path of GLAM2.")
    promoter_add.add_argument(
        "--e_value", "-e", default=0.05, type=int,
        help="The maximum e value for running MEME. Default is 0.05.")
    promoter_add.add_argument(
        "--end_run", "-er", default=10000,
        help="If the result of GLAM2 is not improved after running this "
        "number of iteration, it will be ended. Default is 10000.")
    promoter_add.add_argument(
        "--parallels", "-pl", default=None,
        help="This function can run MEME by parallel. Please input the "
        "number of parallel runs.")
    promoter_add.add_argument(
        "--tss_source", "-s", default=True, action="store_false",
        help="If the TSS gff file is not generated by ANNOgesic, "
        "this function can classify TSS and generate the proper format for "
        "promoter detection. Default is True (from ANNOgesic)")
    promoter_add.add_argument(
        "--tex_libs", "-tl", default=None, nargs='+',
        help="If --tss_source is False, please assign the name of "
        "TEX+/- library. The format is: wig_file_path:TEX+/-(tex or notex):"
        "condition_id(integer):replicate_id(alphabet):strand(+ or -). "
        "If multiple wig files need to be assigned, please use spaces to "
        "separate the wig files. For an example, "
        "$WIG_PATH_1:tex:1:a:+ $WIG_PATH_2:tex:1:a:-.")
    promoter_add.add_argument(
        "--annotation_files", "-g", default=None, nargs='+',
        help="If --tss_source is False, please assign the paths of genome "
        "annotation gff files.")
    promoter_add.add_argument(
        "--combine_all", "-c", default=False, action="store_true",
        help="This function will combine all TSS files in \"tss_files\" "
        "to generate global promoter motifs. Default is False.")
    promoter_parser.set_defaults(func=run_MEME)
    # Parameters of operon detection
    operon_parser = subparsers.add_parser(
        "operon", help="Detect operons and sub-operons.")
    operon_basic = operon_parser.add_argument_group(
        'basic arguments')
    operon_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    operon_basic.add_argument(
        "--tss_files", "-t", required=True, nargs='+',
        help="Paths of the TSS gff files.")
    operon_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of the genome annotation gff files.")
    operon_basic.add_argument(
        "--transcript_files", "-a", required=True, nargs='+',
        help="Paths of the transcript gff files.")
    operon_basic.add_argument(
        "--utr5_files", "-u5", required=True, nargs='+',
        help="Paths of the 5'UTR gff files.")
    operon_basic.add_argument(
        "--utr3_files", "-u3", required=True, nargs='+',
        help="Paths of the 3'UTR gff files.")
    operon_basic.add_argument(
        "--terminator_files", "-e", default=None, nargs='+',
        help="If terminator information can be provided, please assign the "
        "paths of terminator gff files here.")
    operon_add = operon_parser.add_argument_group(
        'additional arguments')
    operon_add.add_argument(
        "--tss_fuzzy", "-tf", default=5, type=int,
        help="The fuzzy for comparing between TSS and transcript. "
        "Default is 5.")
    operon_add.add_argument(
        "--terminator_fuzzy", "-ef", default=30, type=int,
        help="The fuzzy for comparing between terminator and "
        "transcript. Default is 30.")
    operon_add.add_argument(
        "--min_length", "-l", default=20, type=int,
        help="The minimum length of operon. Default is 20.")
    operon_parser.set_defaults(func=run_operon)
    # Parameters of CircRNA detection
    circrna_parser = subparsers.add_parser(
        "circrna", help="Detect circular RNAs.")
    circrna_basic = circrna_parser.add_argument_group(
        'basic arguments')
    circrna_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    circrna_basic.add_argument(
        "--read_files", "-rp", default=None, nargs='+',
        help="If this argument is given, ANNOgesic will map the reads via "
        "segemehl (with -S). BE CAREFUL, this function only use default "
        "parameters of segemehl to map the reads. If some specific functions "
        "of segemehl need to be implemented, "
        "please directly run segemehl (MUST run with -S). "
        "please assign the fasta files. "
        "The input format is $SET_NAME:$READ1,$READ2,... "
        "For an example, set1:read1.fa,read2.fa means these two fasta files need "
        "to be compute together. .bz2 and .gz compressed fasta files can be "
        "accepted as well.")
    circrna_basic.add_argument(
        "--bam_files", "-b", default=None, nargs='+',
        help="You can want assign the paths of Bam files to skip mapping. "
        "The input format is $SET_NAME:$BAM1,$BAM2,... "
        "For an example, set1:bam1.bam,bam2.bam means these two bam files need "
        "to be compute together. BE CAREFUL, the bam files must be generated "
        "via segemehl with -S.")
    circrna_basic.add_argument(
        "--fasta_files", "-f", required=True, nargs='+',
        help="Paths of the genome fasta files. ")
    circrna_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of the genome annotation gff files.")
    circrna_add = circrna_parser.add_argument_group(
        'additional arguments')
    circrna_add.add_argument(
        "--segemehl_path", default="segemehl.x",
        help="Please assign the path of segemehl.x in segemehl package.")
    circrna_add.add_argument(
        "--testrealign_path", default="testrealign.x",
        help="Please assign the path of testrealign.x in segemehl package.")
    circrna_add.add_argument(
        "--samtools_path", default="samtools",
        help="Please assign the path of samtools.")
    circrna_add.add_argument(
        "--parallels", "-p", default=10, type=int,
        help="The number of parallels processes for --align. Default is 10.")
    circrna_add.add_argument(
        "--support_reads", "-s", default=10, type=int,
        help="The minimum supported reads of circular RNA. Default is 10.")
    circrna_add.add_argument(
        "--start_ratio", "-sr", default=0.5, type=float, 
        help="The minimum ratio -- (supported reads of circRNA / all reads) "
        "at starting point of candidate. Default is 0.5.")
    circrna_add.add_argument(
        "--end_ratio", "-er", default=0.5, type=float, 
        help="The meaning is similar to --start_ratio. "
        "This value is for end point of candidate. Default is 0.5.")
    circrna_add.add_argument(
        "--ignore_hypothetical_proteins", "-ih", default=False,
        help="This function is for ignoring hypothetical protein in "
        "genome annotation file. Default is False.")
    circrna_parser.set_defaults(func=run_circrna)
    # Parameters of GO term
    goterm_parser = subparsers.add_parser(
        "go_term", help="Extract GO terms from Uniprot.")
    goterm_basic = goterm_parser.add_argument_group(
        'basic arguments')
    goterm_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    goterm_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of the genome annotation gff files.")
    goterm_basic.add_argument(
        "--transcript_files", "-a", default=None, nargs='+',
        help="If paths of the transcript gff files are provided, "
        "GO term can be retrieved based on expressed CDS and all CDS.")
    goterm_basic.add_argument(
        "--uniprot_id", "-u", required=True,
        help="Path of the UniProt ID mapping database.")
    goterm_basic.add_argument(
        "--go_obo", "-go", required=True,
        help="The path of go.obo.")
    goterm_basic.add_argument(
        "--goslim_obo", "-gs", required=True,
        help="The path of goslim.obo.")
    goterm_parser.set_defaults(func=run_goterm)
    # Parameters of sRNA target prediction
    starget_parser = subparsers.add_parser(
        "srna_target", help="Detect sRNA-mRNA interactions.")
    starget_basic = starget_parser.add_argument_group(
        'basic arguments')
    starget_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    starget_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of the genome annotation gff files.")
    starget_basic.add_argument(
        "--fasta_files", "-f", required=True, nargs='+',
        help="Paths of the genome fasta files.")
    starget_basic.add_argument(
        "--srna_files", "-s", required=True, nargs='+',
        help="Paths of the sRNA gff files.")
    starget_basic.add_argument(
        "--query_srnas", "-q", default=["all"], nargs='+',
        help="Please assign the query sRNA. The input format is "
        "$GENOME:$START:$END:$STRAND. If multiple sRNAs need to be assigned, "
        "please use spaces to separate them. For an example, "
        "NC_007795.1:200:534:+ NC_007795.1:6767:6900:-. If you want to detect "
        "all sRNAs in gff file, please assign \"all\". Default is all.")
    starget_basic.add_argument(
        "--program", "-p", default="both",
        help="The program for detecting sRNA-mRNA interaction. "
        "Please assign \"RNAplex\" or \"RNAup\" or \"both\". Default is both.")
    starget_basic.add_argument(
        "--top", "-t", default=20, type=int,
        help="The minimum ranking number of targets which will be included "
        "to final output. The ranking is based on the binding energy. "
        "Default is 20.")
    starget_add = starget_parser.add_argument_group(
        'additional arguments')
    starget_add.add_argument(
        "--rnaplfold_path", default="RNAplfold",
        help="Please assign the path of RNAplfold in Vienna package.")
    starget_add.add_argument(
        "--rnaplex_path", default="RNAplex",
        help="Please assign the path of RNAplex in Vienna package.")
    starget_add.add_argument(
        "--rnaup_path", default="RNAup",
        help="Please assign the path of RNAup in Vienna package.")
    starget_add.add_argument(
        "--interaction_length", "-i", default=30, type=int,
        help="Maximum length of an interaction. Default is 30.")
    starget_add.add_argument(
        "--window_size_target", "-wt", default=240, type=int,
        help="This value is the average of the pair probabilities over "
        "windows for mRNA target. This function only works for \"RNAplex\". "
        "Default is 240.")
    starget_add.add_argument(
        "--span_target", "-st", default=160, type=int,
        help="This value is the maximum allowed separation of a base pair to "
        "span for mRNA target. This function only works for \"RNAplex\". "
        "Default is 160.")
    starget_add.add_argument(
        "--window_size_srna", "-ws", default=30, type=int,
        help="The meaning is similar to --window_size_target. "
        "This value is for sRNA. Default is 30.")
    starget_add.add_argument(
        "--span_srna", "-ss", default=30, type=int,
        help="The meaning is similar to --span_target. "
        "This value is for sRNA. Default is 30.")
    starget_add.add_argument(
        "--unstructured_region_rnaplex_target", "-ut", default=30, type=int,
        help="Calculate the mean probability that from length 1 to this "
        "value are unpaired for mRNA target. This function only works for "
        "\"RNAplex\". Default is 30.")
    starget_add.add_argument(
        "--unstructured_region_rnaplex_srna", "-us", default=30, type=int,
        help="The meaning is similar to --unstructured_region_rnaplex_target. "
        "This value is for sRNA. Default is 30.")
    starget_add.add_argument(
        "--unstructured_region_rnaup", "-uu", default=30, type=int,
        help="Compute the mean probability that from "
        "length 1 to this value are unpaired. This function only works for "
        "\"RNAup\". Default is 30.")
    starget_add.add_argument(
        "--energy_threshold", "-e", default=-8, type=float,
        help="The minimum energy for a duplex. This function only works for "
        "\"RNAplex\". Default is -8.")
    starget_add.add_argument(
        "--duplex_distance", "-d", default=20, type=int,
        help="Distance between target 3' ends of two consecutive duplexes. "
        "This function only works for \"RNAplex\". Default is 20.")
    starget_add.add_argument(
        "--parallels_rnaplex", "-pp", default=5, type=int,
        help="The number of parallels for running RNAplex. "
        "Default is 5.")
    starget_add.add_argument(
        "--parallels_rnaup", "-pu", default=20, type=int,
        help="The number of parallel processes for running RNAup. "
        "Default is 20.")
    starget_add.add_argument(
        "--continue_rnaup", "-cr", default=False, action="store_true",
        help="The running time of RNAup is long if numerous sRNAs are "
        "assigned. This function can continue to run RNAup based on the "
        "previous intermediate results if the previous process was crushed. "
        "Default is False.")
    starget_add.add_argument(
        "--potential_target_start", "-ps", default=200, type=int,
        help="--potential_target_start and --potential_target_end will be "
        "applied to extract the potential target. This value indicates the "
        "number of nucleotides at the upstream of --target_feature starting "
        "point which will be extracted as part of the potential target. "
        "Default is 200.")
    starget_add.add_argument(
        "--potential_target_end", "-pe", default=150, type=int,
        help="--potential_target_start and --potential_target_end will be "
        "applied to extract the potential target. This value indicates the "
        "number of nucleotides at the downstream of --target_feature "
        "starting point which will be extracted as part of the potential "
        "target. Default is 150.")
    starget_add.add_argument(
        "--target_feature", "-tf", default=["CDS"], nargs='+',
        help="This is the feature name for extracting as potential targets. "
        "If multiple features need to be assigned, please use spaces to "
        "separate them. Ex: CDS tRNA. Default is CDS.")
    starget_parser.set_defaults(func=sRNA_target)
    # Parameters of SNP transcript
    snp_parser = subparsers.add_parser(
        "snp", help="Detect SNP/mutation and generate fasta file if mutations "
        "were found.")
    snp_basic = snp_parser.add_argument_group(
        'basic arguments')
    snp_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    snp_basic.add_argument(
        "--bam_type", "-t", required=True,
        help="Please assign the type of BAM. "
        "If the BAM files are produced by mapping to a related genome "
        "of the query genome, please key in \"related_genome\". "
        "the mutations between the related genome and the query genome can be "
        "detected for generating sequence of the query "
        "genome. If the BAM files are produced by mapping to "
        "query genome, please use the key \"query_genome\". "
        "By that mutations of query genome can be detected.")
    snp_basic.add_argument(
        "--program", "-p", required=True, nargs='+',
        help="Please assign the program for detecting SNP of transcript: "
        "\"with_BAQ\", \"without_BAQ\", \"extend_BAQ\". "
        "Multi-programs can be executed at the same time (separated "
        "by spaces). For an example: with_BAQ without_BAQ extend_BAQ.")
    snp_basic.add_argument(
        "--fasta_files", "-f", required=True, nargs='+',
        help="Paths of the genome fasta files.")
    snp_basic.add_argument(
        "--bam_files", "-b", required=True, nargs='+',
        help="The input format is "
        "$SET_NAME:$SAMPLE_NUM:$BAMFILE1,$BAMFILE2,... "
        "$SAMPLE_NUM means the input bam files (samples/replicates) should be "
        "considered as the given number of samples. "
        "$SAMPLE_NUM also influences --dp4_cutoff, "
        "--indel_fraction, and --read_depth_range."
        "For an example, if sample1.bam, sample2.bam, and "
        "sample3.bam are three samples/replicates of one condition. "
        "You can assign set1:2:sample1.bam,sample2.bam,sample3.bam. "
        "This means these three bam files should be computed together. "
        "And these bam files (samples/replicates) should be considered as "
        "2 samples. If multiple samples need to be assigned, please use "
        "spaces to separate the input.")
    snp_add = snp_parser.add_argument_group(
        'additional arguments')
    snp_add.add_argument(
        "--samtools_path", default="samtools",
        help="If you want to assign the path of samtools, please assign here.")
    snp_add.add_argument(
        "--bcftools_path", default="bcftools",
        help="If you want to assign the path of bcftools, please assign here.")
    snp_add.add_argument(
        "--quality", "-q", default=40, type=int,
        help="The minimum quality of a real mutation. Default is 40.")
    snp_add.add_argument(
        "--read_depth_range", "-d", default="n_10,none",
        help="Range of the read depth of a real mutation. The format is "
        "$MIN,$MAX. This value can be assigned by different types: "
        "1. real number (\"r\"), 2. times of $SAMPLE_NUM "
        "(assigned by --bam_files) (\"n\") "
        "or 3. times of the average read depth (\"a\"). For an example, "
        "n_10,a_3 is assigned, the average read depth is 70 and the "
        "$SAMPLE_NUM is 4. Then, n_10 will be 40 (10 * "
        "$SAMPLE_NUM) and a_3 will be 140 (average read depth * 3). "
        "Based on the same example, if this value is r_10,a_3, the minimum "
        "read depth will become exact 10 reads. If you don't want to set "
        "maximum read depth, you can assign \"none\". Default is n_10,none.")
    snp_add.add_argument(
        "--ploidy", "-pl", default="haploid",
        help="The query bacteria is haploid or diploid. Default is haploid.")
    snp_add.add_argument(
        "--rg_tag", "-R", default=False, action="store_true",
        help="This function is for one BAM file which includes multi samples "
        "(opposite of --ignore-RG in samtools). Default is False.")
    snp_add.add_argument(
        "--caller", "-c", default="m",
        help="The types of caller - consensus-caller or multiallelic-caller. "
        "For details, please check bcftools. \"c\" represents "
        "consensus-caller. \"m\" represents multiallelic-caller. "
        "Default is m.")
    snp_add.add_argument(
        "--dp4_cutoff", "-D", default="n_10,0.8",
        help="The cutoff of DP4. DP4 is compose of four numbers: the reads "
        "covering the reference forward bases (number 1), reference reverse "
        "bases (number 2), alternate forward bases (number 3) and alternate "
        "reverse bases (number 4). Two values need to be assigned, "
        "ex: n_10,0.8. The first value is for (number 3 + number 4). "
        "This value can be assigned based on 1. real number (\"r\"), 2. times "
        "of $SAMPLE_NUM (assigned by --bam_files) (\"n\") or "
        "3. times of average read depth "
        "(\"a\"). The second value is for (number 3 + number 4) / (number 1 + "
        "number 2 + number 3 + number 4). These two values are split by "
        "commas. For an example, n_10,0.8 is assigned and the average read depth "
        "is 70 and $SAMPLE_NUM is 4. It means "
        "that the sum of number 3 and number 4 should be higher than 40 "
        "(10 * $SAMPLE_NUM), and the fraction "
        "-- (number 3 + number 4) / "
        "(number 1 + number 2 + number 3 + number 4) should be higher than "
        "0.8. Based on the same example, if r_10,0.8 is assigned, the sum of "
        "read depth of number 3 and number 4 will become exact 10 reads. "
        "Default is n_10,0.8.")
    snp_add.add_argument(
        "--indel_fraction", "-if", default="n_10,0.8",
        help="This value is the minimum IDV and IMF which supports insertion "
        "of deletion. The minimum IDV can be assigned by different types: "
        "1. real number (\"r\"), 2. times of $SAMPLE_NUM "
        "(assigned by --bam_files) (\"n\") or "
        "3. times of the average read depth (\"a\"). For an example, n_10,0.8 "
        "is assigned, the average read depth is 70 and $SAMPLE_NUM "
        "is 4. It means that IDV should be higher than 40 (10 * "
        "$SAMPLE_NUM), and IMF should be higher than 0.8. "
        "Based on the same example, if r_10,0.8 is assigned, "
        "the minimum IDV will become "
        "exact 10 reads. Default is n_10,0.8 and the two numbers are "
        "separated by commas.")
    snp_add.add_argument(
        "--filter_tag_info", "-ft",
        default=["RPB_b0.1", "MQSB_b0.1", "MQB_b0.1", "BQB_b0.1"], nargs='+',
        help="This function can set more filters to improve the results. "
        "Please assign 1. the tag, 2. bigger (\"b\") or smaller (\"s\") and "
        "3. value for filters. For an example, \"RPB_b0.1,MQ0F_s0\" "
        "means that RPB should be bigger than 0.1 and MQ0F should be smaller "
        "than 0. Default is RPB_b0.1,MQSB_b0.1,MQB_b0.1,BQB_b0.1.")
    snp_parser.set_defaults(func=SNP)
    # Parameters of protein-protein interaction network
    ppi_parser = subparsers.add_parser(
        "ppi_network", help="Detect protein-protein interactions suported by "
        "literature.")
    ppi_basic = ppi_parser.add_argument_group(
        'basic arguments')
    ppi_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    ppi_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of the genome annotation gff files. BE CAREFUL: The gff "
        "files MUST have proper locus_tag item in the attributes. "
        "The locus_tag items can be assigned by a real locus tag like "
        "locus_tag=SAOUHSC_00003, or a gene name, such as, locus_tag=dnaA. ")
    ppi_basic.add_argument(
        "--species_string", "-d", required=True,
        help="Please assign path of the species table of STRING "
        "(species.$VERSION.txt).")
    ppi_basic.add_argument(
        "--query_strains", "-s", nargs='+', required=True,
        help="This is for query strain and filename. "
        "In order to retrieve the data from STRING and Pubmed, The strain "
        "name must be assigned. If the query strain is not available in "
        "database, you can assign the close strain of your query strain. "
        "For an example, the query strain is Staphylococcus aureus HG003, but "
        "there is no Staphylococcus aureus HG003 in STRING database. "
        "Therefore, Staphylococcus aureus NCTC 8325 (close strain) can be "
        "used as reference. The input format can be: "
        "Staphylococcus_aureus_HG003.gff:Staphylococcus_aureus_HG003:"
        "\"Staphylococcus aureus 8325\":\"Staphylococcus aureus\". "
        "or Staphylococcus_aureus_HG003.gff:Staphylococcus_aureus_HG003:"
        "\"93061\":\"Staphylococcus aureus\". "
        "or Staphylococcus_aureus_HG003.gff:Staphylococcus_aureus_HG003:"
        "\"Staphylococcus aureus NCTC 8325\":\"Staphylococcus aureus\". "
        "(gff_filename:gff_strain_name:STRING_name:Pubmed_name). "
        "First one is the gff file name. Second one is the strain name in "
        "gff files. Third one is from STRING (please check the "
        "species.vXXX.txt of STRING, taxon_id, STRING_name_compact or "
        "official_name_NCBI can be assigned here), and the fourth one is for "
        "searching Pubmed. If you want to detect for multiple strains, just "
        "put spaces between these strains. Before running it, please check the "
        "species table (species.v$VERSION.txt) which should be downloaded. "
        "If the file was not downloaded before, please download it. "
        "BE CAREFUL, if the assigned name is with spaces, please put "
        "\"\" at two ends. For searching Pubmen, if a specific name is "
        "assigned, it may not be able to find the related literature.")
    ppi_basic.add_argument(
        "--query", "-q", default=["all"], nargs='+',
        help="Please assign the query protein here. The format is "
        "$GENOME_NAME_OF_GFF:$START_POINT:$END_POINT:$STRAND. If multiple proteins "
        "need to be assigned, please use spaces to separate them. "
        "For an example, Staphylococcus_aureus_HG003:345:456:+ "
        "Staphylococcus_aureus_HG003:2000:3211:-. For computing all protein, "
        "just type \"all\". Default is all.")
    ppi_basic.add_argument(
        "--without_strain_pubmed", "-n", default=False, action="store_true",
        help="This function will retrieve the literature from Pubmed without "
        "assigning strains as well. Default is False.")
    ppi_add = ppi_parser.add_argument_group(
        'additional arguments')
    ppi_add.add_argument(
        "--score", "-ps", default=0.0, type=float,
        help="Please assign minimum PIE score for searching literature. "
        "The value is from -1 (worst) to 1 (best). Default is 0.")
    ppi_add.add_argument(
        "--node_size", "-ns", default=4000, type=int,
        help="Please assign the size of nodes in figure, default is 4000.")
    ppi_parser.set_defaults(func=PPI)
    # Parameters of subcellular localization
    sub_local_parser = subparsers.add_parser(
        "localization", help="Predict subcellular localization "
        "of proteins.")
    sub_local_basic = sub_local_parser.add_argument_group(
        'basic arguments')
    sub_local_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    sub_local_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of genome annotation gff files.")
    sub_local_basic.add_argument(
        "--fasta_files", "-f", required=True, nargs='+',
        help="Paths of genome fasta files.")
    sub_local_basic.add_argument(
        "--transcript_files", "-a", default=None, nargs='+',
        help="If paths of the transcript gff files are provided, "
        "it can get the results based on expressed CDS and all CDS.")
    sub_local_basic.add_argument(
        "--bacteria_type", "-b", required=True,
        help="The type of bacteria (Gram-positive or Gram-negative). "
        "Please assign 'positive' or 'negative'.")
    sub_local_add = sub_local_parser.add_argument_group(
        'additional arguments')
    sub_local_add.add_argument(
        "--psortb_path", default="psort",
        help="If you want to assign the path of Psortb, please assign here.")
    sub_local_add.add_argument(
        "--difference_multi", "-d", default=0.5,
        help="For the protein which have multiple locations, "
        "if the difference of psorb scores is smaller than "
        "--difference_multi, it will be printed out as well. Default is 0.5. "
        "The maximum value is 10.")
    sub_local_add.add_argument(
        "--merge_to_gff", "-m",  default=False, action="store_true",
        help="Merging the information to genome annotation gff file. "
        "Default is False.")
    sub_local_parser.set_defaults(func=Sub_Local)
    # Parameters of riboswitch and RNA thermometer
    ribos_parser = subparsers.add_parser(
        "riboswitch_thermometer", help="Predict riboswitches and "
        "RNA thermometers.")
    ribos_basic = ribos_parser.add_argument_group(
        'basic arguments')
    ribos_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    ribos_basic.add_argument(
        "--program", "-p", default="both",
        help="Please assign the feature that you want to detect. "
        "The options can be \"riboswitch\", \"thermometer\", \"both\". "
        "Default is both.")
    ribos_basic.add_argument(
        "--riboswitch_id_file", "-ri",
        help="If --program is \"riboswitch\" or \"both\", please assign the "
        "file path of riboswitch ID in Rfam. The file should include the "
        "Rfam ID, riboswitch name, and Description of the riboswitch. "
        "For an example, please check "
        "https://github.com/Sung-Huan/ANNOgesic/blob/master/"
        "database/Rfam_riboswitch_ID.csv")
    ribos_basic.add_argument(
        "--rna_thermometer_id_file", "-ti",
        help="If --program is \"thermometer\" or \"both\", please assign "
        "the file path of RNA thermometer ID of Rfam. The file should "
        "include the Rfam ID, RNA thermometer name and Description of "
        "the RNA thermometer. For an example, please check "
        "https://github.com/Sung-Huan/ANNOgesic/blob/master/"
        "database/Rfam_RNA_thermometer_ID.csv")
    ribos_basic.add_argument(
        "--annotation_files", "-g", required=True, nargs='+',
        help="Paths of the annotation gff files.")
    ribos_basic.add_argument(
        "--tss_files", "-t", required=True, nargs='+',
        help="Paths of the TSS gff files.")
    ribos_basic.add_argument(
        "--transcript_files", "-a", required=True, nargs='+',
        help="Paths of the transcript gff files.")
    ribos_basic.add_argument(
        "--fasta_files", "-f", required=True, nargs='+',
        help="Paths of the genome fasta files.")
    ribos_basic.add_argument(
        "--rfam_path", "-R", required=True,
        help="Path of the Rfam CM database.")
    ribos_add = ribos_parser.add_argument_group(
        'additional arguments')
    ribos_add.add_argument(
        "--cmscan_path", "-cs", default="cmscan",
        help="Please assign the path of cmscan in Infernal package.")
    ribos_add.add_argument(
        "--cmpress_path", "-cp", default="cmpress",
        help="Please assign the path of cmpress in Infernal package.")
    ribos_add.add_argument(
        "--utr_length", "-u", default=300, type=int,
        help="The UTR length. Default is 300.")
    ribos_add.add_argument(
        "--e_value", "-e", default=0.001, type=float,
        help="The maximum e value. Default is 0.001.")
    ribos_add.add_argument(
        "--output_all", "-o", default=False, action="store_true",
        help="One query sequence may fit multiple riboswitches or "
        "RNA thermometers. If --output_all is True, all results will be "
        "printed out. Otherwise, only the best one will be printed out. "
        "Default is False.")
    ribos_add.add_argument(
        "--fuzzy", "-z", default=10, type=int,
        help="The fuzzy (nucleotides) for extracting the sequences of "
        "potential riboswitches or RNA thermometers. Default is 10.")
    ribos_add.add_argument(
        "--fuzzy_rbs", "-zr", default=2, type=int,
        help="The number of nucleotides of Shine-Dalgarno sequence "
        "allow to be different with AGGAGG. Default is 2.")
    ribos_add.add_argument(
        "--start_codon", "-ac", default=["ATG"], nargs='+',
        help="The types of start codon. If multiple types need to be "
        "assigned, please use spaces to separate them. Default is ATG.")
    ribos_add.add_argument(
        "--max_dist_rbs", "-Mr", default=14, type=int,
        help="The maximum distance (nucleotides) between ribosome binding "
        "site (Shine-Dalgarno sequence) and start codon. Default is 14.")
    ribos_add.add_argument(
        "--min_dist_rbs", "-mr", default=5, type=int,
        help="The minimum distance (nucleotides) between ribosome binding "
        "site (Shine-Dalgarno sequence) and start codon. Default is 5.")
    ribos_parser.set_defaults(func=Ribos)
    # Parameters of CRISPR finder
    crispr_parser = subparsers.add_parser(
        "crispr", help="Predict CRISPR related RNAs.")
    crispr_basic = crispr_parser.add_argument_group(
        'basic arguments')
    crispr_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    crispr_basic.add_argument(
        "--fasta_files", "-f", required=True, nargs='+',
        help="Path of the genome fasta files.")
    crispr_basic.add_argument(
        "--annotation_files", "-g", default=None, nargs='+',
        help="If paths of the genome gff files are provided, "
        "this function will compare CRISPRs with the genome annotation for "
        "removing the false positives. Default is None.")
    crispr_add = crispr_parser.add_argument_group(
        'additional arguments')
    crispr_add.add_argument(
        "--crt_path", default="/usr/local/bin/CRT.jar",
        help="If you want to assign the path of CRT.jar, please assign here. "
        "Default is /usr/local/bin/CRT.jar")
    crispr_add.add_argument(
        "--window_size", "-w", default=8, type=int,
        help="Length of the window size for searching CRISPR (range: 6-9). "
        "Default is 8.")
    crispr_add.add_argument(
        "--min_number_repeats", "-mn", default=3, type=int,
        help="Minimum number of repeats that a CRISPR must contain. "
        "Default is 3.")
    crispr_add.add_argument(
        "--min_length_repeat", "-ml", default=23, type=int,
        help="Minimum length of CRISPR repeats. Default is 23.")
    crispr_add.add_argument(
        "--Max_length_repeat", "-Ml", default=47, type=int,
        help="Maximum length of CRISPR repeats. Default is 47.")
    crispr_add.add_argument(
        "--min_length_spacer", "-ms", default=26, type=int,
        help="Minimum length of CRISPR spacers. Default is 26.")
    crispr_add.add_argument(
        "--Max_length_spacer", "-Ms", default=50, type=int,
        help="Maximum length of CRISPR spacers. Default is 50.")
    crispr_add.add_argument(
        "--ignore_hypothetical_protein", "-in", default=False,
        action="store_true",
        help="This function is for ignoring the hypothetical proteins. "
        "Default is False.")
    crispr_parser.set_defaults(func=Crispr)
    # Parameters of merge features
    merge_parser = subparsers.add_parser(
        "merge_features", help="Merge all features to one gff file.")
    merge_basic = merge_parser.add_argument_group(
        'basic arguments')
    merge_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    merge_basic.add_argument(
        "--output_prefix", "-op", required=True,
        help="Please assign the prefix name of output gff file. "
        "The filename will be $OUTPUT_PREFIX_merge_features.gff.")
    merge_basic.add_argument(
        "--transcript_file", "-a", default=None,
        help="If transcript gff file is provided. The parent transcripts "
        "(\"Parent\" in gff attributes) of all features will be generated. "
        "If there is no transcript, this function will just simply combine "
        "all input gff files.")
    merge_basic.add_argument(
        "--other_features_files", "-of", default=None, nargs='+',
        help="Please assign the gff files (besides transcript gff file) "
        "which you want to merge. You can use spaces to separate multiple "
        "gff files.")
    merge_add = merge_parser.add_argument_group(
        'additional arguments')
    merge_add.add_argument(
        "--terminator_fuzzy", "-ef", default=30, type=int,
        help="For merging terminators, please assign the fuzzy nucleotides "
        "between transcript and terminator. ATTENTION, the third column of "
        "gff file of terminator should be exact \"terminator\". "
        "Default is 30.")
    merge_add.add_argument(
        "--tss_fuzzy", "-tf", default=5, type=int,
        help="For merging TSSs, please assign the fuzzy between TSS and "
        "transcript. ATTENTION, the third column of gff file of terminator "
        "should be exact \"TSS\". Default is 5.")
    merge_parser.set_defaults(func=Merge)

    # Parameters of generate screenshots
    screen_parser = subparsers.add_parser(
        "screenshot", help="Generate screenshots for selected features using IGV.")
    screen_basic = screen_parser.add_argument_group(
        'basic arguments')
    screen_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    screen_basic.add_argument(
        "--fasta_file", "-f", required=True,
        help="Path of the genome fasta file.")
    screen_basic.add_argument(
        "--main_gff", "-mg", required=True,
        help="Screenshot will be generated based on the position of "
        "--main_gff file.")
    screen_basic.add_argument(
        "--side_gffs", "-sg", default=None, nargs='+',
        help="If you want to compare other features with the --main_gff, "
        "please assign the path of other gff files here. "
        "If multiple gff files need to be assigned, just use spaces to "
        "separate them.")
    screen_basic.add_argument(
        "--tex_notex_libs", "-tl", default=None, nargs='+',
        help="If TEX+/- wig file is required, please also assign the proper "
        "format here. The format is: wig_file_path:TEX+/-(tex or notex):"
        "condition_id(integer):replicate_id(alphabet):strand(+ or -). "
        "If multiple wig files need to be assigned, please use spaces to "
        "separate the wig files. For an example, "
        "$WIG_PATH_1:tex:1:a:+ $WIG_PATH_2:tex:1:a:-.")
    screen_basic.add_argument(
        "--frag_libs", "-fl", default=None, nargs='+',
        help="If the fragmented (or conventional) wig file is required, "
        "please also assign the "
        "proper format here. The format is: wig_file_path:fragmented(frag):"
        "condition_id(integer):replicate_id(alphabet):strand(+ or -). "
        "If multiple wig files need to be assigned, please use spaces to "
        "separate the wig files. For an example, "
        "$WIG_PATH_1:frag:1:a:+ $WIG_PATH_2:frag:1:a:-.")
    screen_basic.add_argument(
        "--output_folder", "-o", required=True,
        help="Please assign the output folder. It will create a sub-folder "
        "\"screenshots\" in --output_folder to store the results.")
    screen_add = screen_parser.add_argument_group(
        'additional arguments')
    screen_add.add_argument(
        "--height", "-he", default=1500, type=int,
        help="Please assign the height of the screenshot. "
        "Default is 1500.")
    screen_add.add_argument(
        "--present", "-p", default="expand",
        help="The presentation type of the features in the screenshot. "
        "expand/collapse/squish. Default is expand.")
    screen_parser.set_defaults(func=Screen)

    # Parameter of generating color png
    color_parser = subparsers.add_parser(
        "colorize_screenshot_tracks", help="Add color information to "
        "screenshots (e.g. useful for dRNA-Seq based TSS and PS "
        "detection. It only works after running \"screenshot\" "
        "(after running batch script).")
    color_basic = color_parser.add_argument_group(
        'basic arguments')
    color_basic.add_argument(
        "--project_path", "-pj", required=True,
        help="Path of the project folder.")
    color_basic.add_argument(
        "--screenshot_folder", "-f", required=True,
        help="The folder which stores \"screenshots\" "
        "(a folder generated by subcommand \"screenshot\").")
    color_basic.add_argument(
        "--track_number", "-t", type=int, required=True,
        help="The number of tracks.")
    color_add = color_parser.add_argument_group(
        'additional arguments')
    color_add.add_argument(
        "--imagemagick_covert_path", "-m", default="convert",
        help="Please assign the path of \"convert\" in "
        "ImageMagick package.")
    color_parser.set_defaults(func=color_png)

    args = parser.parse_args()
    
    if args.version is True:
        print("ANNOgesic version " + __version__)
    elif "func" in dir(args):
        controller = Controller(args)
        args.func(controller)
    else:
        parser.print_help()



def create_project(controller):
    controller.create_project(__version__)

def get_input(controller):
    controller.get_input()

def get_target_fasta(controller):
    controller.get_target_fasta()

def run_RATT(controller):
    controller.ratt()

def run_expression(controller):
    controller.expression()

def multiparser(controller):
    controller.multiparser()

def run_TSSpredator(controller):
    controller.tsspredator()

def optimize_TSSpredator(controller):
    controller.optimize()

def color_png(controller):
    controller.color()

def run_Terminator(controller):
    controller.terminator()

def run_Transcript_Assembly(controller):
    controller.transcript()

def run_UTR_detection(controller):
    controller.utr_detection()

def run_sRNA_detection(controller):
    controller.srna_detection()

def run_sORF_detection(controller):
    controller.sorf_detection()

def run_MEME(controller):
    controller.meme()

def run_operon(controller):
    controller.operon()

def run_circrna(controller):
    controller.circrna()

def run_goterm(controller):
    controller.goterm()

def sRNA_target(controller):
    controller.srna_target()

def SNP(controller):
    controller.snp()

def PPI(controller):
    controller.ppi()

def Sub_Local(controller):
    controller.sublocal()

def Ribos(controller):
    controller.ribos()

def Crispr(controller):
    controller.crispr()

def Merge(controller):
    controller.merge()

def Screen(controller):
    controller.screen()
if __name__ == "__main__":
    main()
