#!/usr/bin/env bash

# Created by argbash-init v2.10.0
# DEFINE_SCRIPT_DIR([])
# INCLUDE_PARSING_CODE([polap-parsing.sh])
# ARGBASH_GO()
# needed because of Argbash --> m4_ignore([
### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
# Argbash is a bash code generator used to get arguments parsing right.
# Argbash is FREE SOFTWARE, see https://argbash.io for more info

# OTHER STUFF GENERATED BY Argbash
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || {
	echo "Couldn't determine the script's running directory, which probably matters, bailing out" >&2
	exit 2
}
. "$script_dir/polap-parsing.sh" # '.' means 'source'

### END OF CODE GENERATED BY Argbash (sortof) ### ])
# [ <-- needed because of Argbash

# vvv  PLACE YOUR CODE HERE  vvv

################################################################################
# utilities
################################################################################

###############################################################################
# Checks if required commands are available.
# called early in the code such as reset menu.
###############################################################################
function run_check1() {
	command -v bc >/dev/null 2>&1 || {
		echo >&2 "bc: not installed"
		return $RETURN_FAIL
	}
	command -v seqkit >/dev/null 2>&1 || {
		echo >&2 "seqkit: not installed"
		return $RETURN_FAIL
	}
	command -v minimap2 >/dev/null 2>&1 || {
		echo >&2 "minimap2: not installed"
		return $RETURN_FAIL
	}
	command -v flye >/dev/null 2>&1 || {
		echo >&2 "flye: not installed"
		return $RETURN_FAIL
	}
	command -v makeblastdb >/dev/null 2>&1 || {
		echo >&2 "makeblastdb: not installed"
		return $RETURN_FAIL
	}
	command -v tblastn >/dev/null 2>&1 || {
		echo >&2 "tblastn: not installed"
		return $RETURN_FAIL
	}
	command -v bedtools >/dev/null 2>&1 || {
		echo >&2 "bedtools: not installed"
		return $RETURN_FAIL
	}
	command -v prefetch >/dev/null 2>&1 || {
		echo >&2 "prefetch: not installed"
		return $RETURN_FAIL
	}
	command -v jellyfish >/dev/null 2>&1 || {
		echo >&2 "jellyfish: not installed"
		return $RETURN_FAIL
	}
	command -v csvtk >/dev/null 2>&1 || {
		echo >&2 "csvtk: not installed"
		return $RETURN_FAIL
	}
	return $RETURN_SUCCESS
}

###############################################################################
# Checks if FMLRC related commands are available.
# called by prepare-polishing menu.
###############################################################################
function run_check2() {
	command -v msbwt >/dev/null 2>&1 || {
		echo >&2 "msbwt: not installed"
		return $RETURN_FAIL
	}
	command -v ropebwt2 >/dev/null 2>&1 || {
		echo >&2 "ropebwt2: not installed"
		return $RETURN_FAIL
	}
	command -v fmlrc >/dev/null 2>&1 || {
		echo >&2 "fmlrc: not installed"
		return $RETURN_FAIL
	}
	return $RETURN_SUCCESS
}

###############################################################################
# Checks if ncbitools related commands are available.
# called by fetch
###############################################################################
function run_check3() {
	command -v prefetch >/dev/null 2>&1 || {
		echo >&2 "prefetch: not installed"
		return $RETURN_FAIL
	}
	command -v vdb-validate >/dev/null 2>&1 || {
		echo >&2 "vdb-validate: not installed"
		return $RETURN_FAIL
	}
	command -v fasterq-dump >/dev/null 2>&1 || {
		echo >&2 "fasterq-dump: not installed"
		return $RETURN_FAIL
	}
	return $RETURN_SUCCESS
}

###############################################################################
# You could use this function template to create a new menu.
# Rename template and delete x in the name. You could execute such menu
# but such menus are not created as empty files by make-menus menu.
###############################################################################
function _x_run_polap_template() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	echoall "$0"
	echoall "$FUNCNAME"
	echoall "$1"
	echoall "$2"

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

###############################################################################
# Feteches SRA data file.
# Arguments:
#   --sra SRR10190639
# Outputs:
#   SRR10190639.fastq
###############################################################################
function _run_polap_x-ncbi-fetch-sra() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Feteches SRA data file.
# Arguments:
#   --sra SRR10190639
# Outputs:
#   SRR10190639.fastq
Example: $(basename $0) ${_arg_menu[0]} --sra <arg>
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if ! run_check1; then
		echoerr "ERROR: change your conda environment to polap-dev."
		echoerr "INFO: (base) $ conda env create -f src/environment.yaml"
		echoerr "INFO: (base) $ conda activate polap-dev"
		exit $EXIT_ERROR
	fi

	if [ -z "$_arg_sra" ]; then
		echoerr "ERROR: no --sra option is used."
		exit $EXIT_SUCCESS
	fi

	SRA=$_arg_sra
	"$script_dir"/run-polap-ncbitools fetch sra "$SRA"

	echoerr You have a file called "$SRA".fastq and a folder named "$SRA"
	echoerr if your download try is successful. Then, you would want to delete
	echoerr the folder because we need only the fastq file.

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Makes menu commands as empty files.
################################################################################
function _run_polap_make-menus() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	grep "^function _run_polap" "$WDIR"/polap.sh |
		grep run_polap | grep -v run_polap_x |
		sed 's/function _run_polap_//' | sed 's/() {//' |
		parallel touch {}

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Makes menu commands as empty files.
# Creates menus prefixed with x.
################################################################################
function _run_polap_make-menus-all() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	grep "^function _run_polap" "$WDIR"/polap.sh | grep run_polap | sed 's/function _run_polap_//' | sed 's/() {//' | parallel touch {}

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Deletes menu commands as empty files.
# Leaves make-menus command.
################################################################################
function _run_polap_clean-menus() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	grep "^function _run_polap" "$WDIR"/polap.sh | grep run_polap | sed 's/function _run_polap_//' | sed 's/() {//' | parallel rm -f {}
	touch make-menus

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Lists menu of POLAP.
# You need to execute make-menus menu if nothing is displayed.
################################################################################
function _run_polap_list() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Lists menu of POLAP.
# You need to execute make-menus menu if nothing is displayed.
Example: $(basename "$0") make-menus
         $(basename "$0") ${_arg_menu[0]} [all|main|assemble1|annotate|assemble2|polish]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [[ ${_arg_menu[1]} == "all" ]]; then
		find . -maxdepth 1 -type f -empty -exec basename {} \; |
			sort >&2
	elif [[ ${_arg_menu[1]} == "main" ]]; then
		echoerr assemble1
		echoerr annotate
		echoerr assemble2
		echoerr flye-polishing
		echoerr prepare-polishing
		echoerr polish
	elif [[ ${_arg_menu[1]} == "assemble1" ]]; then
		echoerr reset
		echoerr total-length-long
		echoerr find-genome-size
		echoerr reduce-data
		echoerr flye1
	elif [[ ${_arg_menu[1]} == "annotate" ]]; then
		echoerr blast-genome
		echoerr count-gene
	elif [[ ${_arg_menu[1]} == "assemble2" ]]; then
		echoerr select-reads
		echoerr flye2
	elif [[ ${_arg_menu[1]} == "polish" ]]; then
		echoerr flye-polishing
		echoerr prepare-polishing
		echoerr polish
	else
		echoerr "${help_message}"
	fi

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Runs the whole-genome assembly.
################################################################################

################################################################################
# Initializes polap analysis in a starting folder, creating an output folder.
# Arguments:
#   -o $ODIR
# Inputs: nothing
# Outputs:
#   $ODIR
################################################################################
function _run_polap_reset() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Initializes polap analysis in a starting folder, creating an output folder.
# Arguments:
#   -o $ODIR
# Inputs: nothing
# Outputs:
#   $ODIR
Example: $(basename "$0") ${_arg_menu[0]} [-o|--outdir <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if ! run_check1; then
		echoerr "ERROR: change your conda environment to polap-dev."
		echoerr "INFO: (base) $ conda env create -f src/environment.yaml"
		echoerr "INFO: (base) $ conda activate polap-dev"
		exit $EXIT_ERROR
	fi

	if [ -d "$ODIR" -a "${_arg_yes}" = "off" ]; then
		while true; do
			read -p "Folder [$ODIR] already exists. Do you want to delete it? [y/n] " yn
			case $yn in
			[Yy]*)
				rm -rf "$ODIR"
				break
				;;
			[Nn]*)
				exit $EXIT_FAIL
				;;
			*) echo "Please answer yes or no." ;;
			esac
		done
	else
		rm -rf "$ODIR"
	fi

	mkdir -p "$ODIR"
	echoall "DATA: Your output folder [$ODIR] is created."
	if [ "$ODIR" != "o" ]; then
		echoall "Use -o $ODIR option in all subsequent analysis"
		echoall "  because your output folder is not the default of 'o'."
	fi
	_run_polap_make-menus

	echoerr NEXT: $(basename "$0") total-length-long -o "$ODIR" -l ${_arg_long_reads}
	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Computes the total number of nucleotides of long-read data.
# Arguments:
#   -l $LR: a long-read fastq data file
# Inputs:
#   $LR: a long-read fastq data file
#   $ODIR
# Outputs:
#   $ODIR/long_total_length.txt
################################################################################
function _run_polap_total-length-long() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Computes the total number of nucleotides of long-read data.
# Arguments:
#   -l $LR: a long-read fastq data file
# Inputs:
#   $LR: a long-read fastq data file
#   $ODIR
# Outputs:
#   $ODIR/long_total_length.txt
Example: $(basename "$0") ${_arg_menu[0]} [-l|--long-reads <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ ! -d "$ODIR" ]; then
		echoall "ERROR: no such output directory [$ODIR]"
		echoerr "SUGGESTION: reset"
		exit $EXIT_ERROR
	fi

	if [ ! -s "$LR" ]; then
		echoall "ERROR: no long-read data file [$LR]"
		exit $EXIT_ERROR
	fi

	echoerr "counting the total number of bases in your long-read data [$LR] ... please, wait ..."
	seqkit stats -Ta "$LR" | csvtk cut -t -f "sum_len" | csvtk del-header >"$ODIR"/long_total_length.txt
	LONG_TOTAL_LENGTH=$(cat "$ODIR"/long_total_length.txt)
	echoall "DATA: total length of your long-read data (bases): $LONG_TOTAL_LENGTH bp"

	echoerr NEXT: $(basename "$0") find-genome-size -o "$ODIR" -a "${_arg_short_read1}" -b "${_arg_short_read2}"

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Estimates the whole genome size using short-read data.
# Arguments:
#   -a $SR1: a short-read fastq data file
#   -b $SR2: another short-read fastq data file
# Outputs:
#   $ODIR/jellyfish_out.histo
#   $ODIR/short_expected_genome_size.txt
################################################################################
function _run_polap_find-genome-size() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Estimates the whole genome size using short-read data.
# Arguments:
#   -a $SR1: a short-read fastq data file
#   -b $SR2: another short-read fastq data file
# Inputs:
#   $SR1: a short-read fastq data file
#   $SR2: another short-read fastq data file
# Outputs:
#   $ODIR/short_expected_genome_size.txt
Example: $(basename "$0") ${_arg_menu[0]} [-a|--short-read1 <arg>] [-b|--short-read2 <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ ! -s "$ODIR" ]; then
		echoall "ERROR: no such output directory [$ODIR]"
		echoerr "SUGGESTION: reset"
		exit $EXIT_ERROR
	fi

	echoerr "estimating the genome size using your short-read data [$SR1] and [$SR2] ... please, wait ..."
	# See https://bioinformatics.uconn.edu/genome-size-estimation-tutorial/
	if [ -s "$SR1" ]; then
		if [ -s "$SR2" ]; then
			jellyfish count -t "$NT" -C -m 19 -s 5G -o "$ODIR"/jellyfish_out --min-qual-char=? "$SR1" "$SR2"
		else
			jellyfish count -t "$NT" -C -m 19 -s 5G -o "$ODIR"/jellyfish_out --min-qual-char=? "$SR1"
		fi
	else
		echoerr "ERROR: no short-read data: $SR1"
		exit $EXIT_ERROR
	fi
	jellyfish histo -o "$ODIR"/jellyfish_out.histo "$ODIR"/jellyfish_out
	"$WDIR"/run-polap-jellyfish.R \
		"$ODIR"/jellyfish_out.histo \
		"$ODIR"/short_expected_genome_size.txt

	EXPECTED_GENOME_SIZE=$(cat "$ODIR"/short_expected_genome_size.txt)
	EXPECTED_GENOME_SIZE=${EXPECTED_GENOME_SIZE%.*}
	echoall "DATA: expected genome size using short-read data (bases): $EXPECTED_GENOME_SIZE bp"

	echoerr NEXT: $(basename "$0") reduce-data -o "$ODIR" -l "${_arg_long_reads}" [-m "${_arg_min_read_length}"]

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Checks if the long-read coverage is less than $COV.
# If so, keep the long read data.
# If not, sample long reads upto that coverage.
# Deletes long reads shorter than a sequence length threshold e.g., 3 kb.
# Arguments:
#   -l $LR: a long-read fastq data file
#   -m $MR: the long-read sequence length threshold
#   --reduction-reads (default) or --no-reduction-reads
# Inputs:
#   $ODIR/short_expected_genome_size.txt
#   $ODIR/long_total_length.txt
#   $LR
# Outputs:
#   $LRNK
################################################################################
function _run_polap_reduce-data() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Checks if the long-read coverage is less than $COV.
# If so, keep the long read data.
# If not, sample long reads upto that coverage.
# Deletes long reads shorter than a sequence length threshold e.g., 3 kb.
# Arguments:
#   -l $LR: a long-read fastq data file
#   -m $MR: the long-read sequence length threshold
#   --reduction-reads (default) or --no-reduction-reads
# Inputs:
#   $ODIR/short_expected_genome_size.txt
#   $ODIR/long_total_length.txt
#   $LR
# Outputs:
#   $LRNK
Example: $(basename $0) ${_arg_menu[0]} [-l|--long-reads <arg>] [-m|--min-read-length <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ ! -d "$ODIR" ]; then
		echoall "ERROR: no such output directory [$ODIR]"
		echoerr "SUGGESTION: reset"
		exit $EXIT_ERROR
	fi

	if [ ! -s "$LR" ]; then
		echoall "ERROR: no long-read data file [$LR]"
		exit $EXIT_ERROR
	fi

	if [ ! -s "$ODIR"/short_expected_genome_size.txt ]; then
		echoall "ERROR: no genome size estimate [$ODIR/short_expected_genome_size.txt]"
		echoerr "SUGGESTION: find-genome-size"
		exit $EXIT_ERROR
	fi

	if [ ! -s "$ODIR"/long_total_length.txt ]; then
		echoall "ERROR: no long read total length [$ODIR/long_total_length.txt]"
		echoerr "SUGGESTION: total-length-long"
		exit $EXIT_ERROR
	fi

	EXPECTED_GENOME_SIZE=$(cat "$ODIR"/short_expected_genome_size.txt)
	EXPECTED_GENOME_SIZE=${EXPECTED_GENOME_SIZE%.*}
	LONG_TOTAL_LENGTH=$(cat "$ODIR"/long_total_length.txt)

	EXPECTED_LONG_COVERAGE=$(echo "scale=3; $LONG_TOTAL_LENGTH/$EXPECTED_GENOME_SIZE" | bc)
	EXPECTED_LONG_COVERAGE=${EXPECTED_LONG_COVERAGE%.*}

	echoerr "reducing your long-read data [$LR] ... please, wait ..."
	nfq_file="$ODIR"/n.fq
	rm -f $nfq_file
	if [[ ${_arg_reduction_reads} == "off" ]]; then
		echoall "OPTION: --no-reduction-reads No reduction of the long-read data"
		ln -s $(realpath "$LR") "$nfq_file"
	else
		if [ "$EXPECTED_LONG_COVERAGE " -lt $COV ]; then
			echoall "LOG: No reduction of the long-read data because $EXPECTED_LONG_COVERAGE < $COV"
			ln -s $(realpath "$LR") "$nfq_file"
		else
			echoall "SUGGESTION: you might want to increase the minimum read lengths because you have enough long-read data."
			RATE=$(echo "scale=3; $COV/$EXPECTED_LONG_COVERAGE" | bc)
			echoall "LOG: long-read data reduction by rate of $RATE <= COV[$COV] / long-read coverage[$EXPECTED_LONG_COVERAGE]"
			echoall "sampling long-read data by $RATE ... wait ..."
			seqkit sample -p "$RATE" "$LR" -o "$nfq_file" >/dev/null 2>&1
			echoall "DATA: a reduced long-read data $nfq_file is created"
		fi
	fi
	LR=$nfq_file

	# step1
	echoall "LOG: keeps long reads of length being at least $MR bp ..."
	echo "LOG: deletes $LRNK"
	rm -f "$LRNK"
	# seqkit seq --quiet -m "$MR" --threads 4 "$LR" -o "$LRNK"
	seqkit seq --quiet -m "$MR" --threads 4 "$LR" -o "$LRNK" >/dev/null 2>&1
	rm "$nfq_file"
	echoall "DATA: long-read minimum $MR reads data $LRNK is created"

	echoerr "NEXT (for testing purpose only): $(basename "$0") flye1 -g 150000"
	echoerr "NEXT (for testing purpose only): $(basename "$0") flye1 --test"
	echoerr NEXT: $(basename "$0") flye1 -o "$ODIR" [-t $NT] [-c $COV]

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Executes Flye for a whole-genome assembly upto the contigger stage
# Arguments:
#   -t $NT: the number of CPU cores
#   -c $COV: the Flye's coverage option
#   -g <arg>: computed by find-genome-size menu or given by users
# Inputs:
#   $ODIR/short_expected_genome_size.txt (ignored with -g option)
#   $LRNK
# Outputs:
#   $FDIR/30-contigger/contigs.fasta
#   $FDIR/30-contigger/contigs_stats.txt
#   $FDIR/30-contigger/graph_final.fasta
#   $FDIR/30-contigger/graph_final.gfa
################################################################################
function _run_polap_flye1() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Executes Flye for a whole-genome assembly upto the contigger stage
# Arguments:
#   -t $NT: the number of CPU cores
#   -c $COV: the Flye's coverage option
#   -g <arg>: computed by find-genome-size menu or given by users
# Inputs:
#   $ODIR/short_expected_genome_size.txt (ignored with -g option)
#   $LRNK
# Outputs:
#   $FDIR/30-contigger/contigs.fasta
#   $FDIR/30-contigger/contigs_stats.txt
#   $FDIR/30-contigger/graph_final.fasta
#   $FDIR/30-contigger/graph_final.gfa
Example: $(basename $0) ${_arg_menu[0]} [-t|--threads <arg>] [-c|--coverage <arg>] [-g|--genomesize <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ ! -s "$ODIR"/short_expected_genome_size.txt ]; then
		echoall "ERROR: no genome size file [$ODIR/short_expected_genome_size.txt]"
		echoerr "SUGGESTION: find-genome-size"
		exit $EXIT_SUCCESS
	fi

	if [ ! -s "$LRNK" ]; then
		echoall "ERROR: no reduced long-read file [$LRNK]"
		echoerr "SUGGESTION: reduce-data"
		exit $EXIT_SUCCESS
	fi

	FDIR="$ODIR"/0
	EXPECTED_GENOME_SIZE=$(cat "$ODIR"/short_expected_genome_size.txt)
	EXPECTED_GENOME_SIZE=${EXPECTED_GENOME_SIZE%.*}
	echoall "DATA: the expected genome size based on short-read data (bases): $EXPECTED_GENOME_SIZE bp"
	if [[ ${_arg_test} == "on" ]]; then
		_arg_genomesize=150000
	fi
	if [ ! -z "$_arg_genomesize" ]; then
		EXPECTED_GENOME_SIZE=$_arg_genomesize
		echoall "OPTION: short reads expected genome size (bases) we use instead: $EXPECTED_GENOME_SIZE bp"
	fi

	echoall "INFO: executing the whole-genome assembly using flye ... be patient!"
	flye --nano-raw "$LRNK" \
		--out-dir "$FDIR" \
		--threads "$NT" \
		--asm-coverage "$COV" \
		--genome-size "$EXPECTED_GENOME_SIZE" \
		--stop-after contigger \
		>/dev/null 2>&1

	echo "INFO: assembly graph in the flye contigger stage: $PWD/$FDIR/30-contigger/graph_final.gfa"
	echoerr "NEXT: $(basename $0) blast-genome -o $ODIR [-i 0]"
	echoerr "NEXT: $(basename $0) annotate -o $ODIR [-i 0]"

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Called in the script not by users.
# -i or --inum option is ignored.
################################################################################
function _func_polap_blast-genome() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	if [ $# -eq 0 ]; then
		INUM=0
	elif [ $# -eq 1 ]; then
		INUM=$1
	fi

	_run_polap_blast-genome

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Blasts the genome assembly of a Flye run.
# Arguments:
#   -i $INUM: a Flye genome assembly number
# Inputs:
#   $assembly_contigs_fasta
# Outputs:
#   $CONTIGNAME
#   $MTGENECOUNT
#   $PTGENECOUNT
#   $ADIR/mtaa.blast
#   $ADIR/mtaa.blast.bed
#   $MTAABLAST.sorted.bed
#   $ADIR/mtaa.bed
#   $ADIR/ptaa.blast
#   $ADIR/ptaa.blast.bed
#   $PTAABLAST.sorted.bed
#   $ADIR/ptaa.bed
################################################################################
function _run_polap_blast-genome() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	ANUM=$INUM
	MTAA="$WDIR"/polap-mt.1.c70.3.faa
	PTAA="$WDIR"/polap-pt.2.c70.3.faa
	FDIR="$ODIR"/$ANUM
	assembly_contigs_stats="$FDIR"/30-contigger/contigs_stats.txt
	assembly_contigs_fasta="$FDIR"/30-contigger/contigs.fasta
	ADIR="$FDIR"/50-annotation
	CONTIGFILE="$ADIR"/contig.fasta
	CONTIGDB="$ADIR"/contig
	MTAABLAST="$ADIR"/mtaa.blast
	MTAABED="$ADIR"/mtaa.bed
	MTGENECOUNT="$ADIR"/mt.gene.count
	PTAABLAST="$ADIR"/ptaa.blast
	PTAABED="$ADIR"/ptaa.bed
	PTGENECOUNT="$ADIR"/pt.gene.count
	CONTIGNAME="$ADIR"/contig.name

	help_message=$(
		cat <<HEREDOC
# Blasts the genome assembly of a Flye run.
# Arguments:
#   -i $INUM: a Flye genome assembly number
# Inputs:
#   $assembly_contigs_fasta
# Outputs:
#   $CONTIGNAME
#   $MTGENECOUNT
#   $PTGENECOUNT
Example: $(basename "$0") ${_arg_menu[0]} [-i|--inum <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	echoall "please, wait for contig annotation with mitochondrial and plastid genes on $ANUM"

	if [ ! -s "$assembly_contigs_fasta" ]; then
		echoall "ERROR: no assembly file [$assembly_contigs_fasta]"
		exit $EXIT_ERROR
	fi

	if [ -d "$ADIR" ]; then
		rm -rf "$ADIR"
		echo "INFO: $ADIR is deleted."
	fi
	mkdir -p "$ADIR"
	echo "INFO: $ADIR is created."

	#src/run-polap-select.R o/30-contigger/contigs_stats.txt o/50-annotation/contig.name
	grep -v "#" "${assembly_contigs_stats}" | cut -f 1 >"$CONTIGNAME"
	echo "INFO: contig sequence names in file: $CONTIGNAME"

	# seqkit grep --threads $NT -f "$CONTIGNAME" \
	# 	"$assembly_contigs_fasta" \
	# 	-o "$ADIR"/contig.fasta \
	# 	>/dev/null 2>&1
	cp "$assembly_contigs_fasta" "$ADIR"/contig.fasta
	echo "INFO: contig sequence file: $ADIR/contig.fasta"

	makeblastdb -dbtype nucl \
		-in "$assembly_contigs_fasta" \
		-out "$ADIR"/contig \
		>/dev/null 2>&1
	echo "INFO: BLASTDB of the contig sequences: $ADIR/contig"

	# mtDNA gene annotation and counts
	echo "INFO: BLAST of the mitochondrial proteins againt $ADIR/contig"
	echo "INFO: executing the tblastn ... be patient!"
	tblastn -query "$MTAA" \
		-db "$ADIR"/contig \
		-out "$ADIR"/mtaa.blast \
		-evalue 1e-30 \
		-outfmt '6 qaccver saccver pident length mismatch gapopen qstart qend sstart send evalue bitscore stitle salltitles' \
		-num_threads "$NT" \
		>/dev/null 2>&1
	"$WDIR"/run-polap-genes.R "$ADIR"/mtaa.blast \
		"$ADIR"/mtaa.blast.bed \
		>/dev/null 2>&1
	sort -k1,1 -k2,2n "$ADIR"/mtaa.blast.bed >"$MTAABLAST".sorted.bed
	mkdir "$ADIR"/mtaa.bed

	echo "INFO: counting mitochondrial genes in the contigs"
	if [ "$DEBUG" -eq 1 ]; then set +x; fi
	while IFS= read -r contig; do
		grep -w "$contig" "$MTAABLAST".sorted.bed >"$MTAABED"/"$contig".bed
		bedtools merge -i "$MTAABED"/$contig.bed >"$MTAABED"/"$contig".bed.txt
		printf "%s\t%d\n" "$contig" $(wc -l <"$MTAABED"/$contig.bed.txt)
	done <"$CONTIGNAME" | sort -k2 -rn >"$MTGENECOUNT"
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	echo "INFO: compressing the BLAST results of mitochondrial gene annotation"
	tar zcf "$ADIR"/mtaa.bed.tar.gz "$ADIR"/mtaa.bed
	rm -rf "$ADIR"/mtaa.bed

	# Plastid gene annotation and counts
	echo "INFO: BLAST of the plastid proteins againt $ADIR/contig"
	echo "INFO: executing the tblastn ... be patient!"
	tblastn -query "$PTAA" \
		-db "$ADIR"/contig \
		-out "$ADIR"/ptaa.blast \
		-evalue 1e-30 -outfmt '6 qaccver saccver pident length mismatch gapopen qstart qend sstart send evalue bitscore stitle salltitles' \
		-num_threads $NT \
		>/dev/null 2>&1
	"$WDIR"/run-polap-genes.R "$ADIR"/ptaa.blast \
		"$ADIR"/ptaa.blast.bed \
		>/dev/null 2>&1
	sort -k1,1 -k2,2n "$ADIR"/ptaa.blast.bed >"$PTAABLAST".sorted.bed
	mkdir "$ADIR"/ptaa.bed

	echo "INFO: counting plastid genes in the contigs"
	if [ "$DEBUG" -eq 1 ]; then set +x; fi
	while IFS= read -r contig; do
		grep -w "$contig" "$PTAABLAST".sorted.bed >"$PTAABED"/$contig.bed
		bedtools merge -i "$PTAABED"/$contig.bed >"$PTAABED"/$contig.bed.txt
		printf "%s\t%d\n" "$contig" $(wc -l <"$PTAABED"/$contig.bed.txt)
	done <"$CONTIGNAME" | sort -k2 -rn >"$PTGENECOUNT"
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	echo "INFO: compressing the BLAST results of plastid gene annotation"
	tar zcf "$ADIR"/ptaa.bed.tar.gz "$ADIR"/ptaa.bed
	rm -rf "$ADIR"/ptaa.bed

	echoerr "NEXT (for testing purpose only): $(basename "$0") count-gene --test"
	echoerr "NEXT: $(basename $0) count-gene -o $ODIR [-i $INUM]"

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Called in the script not by users.
# -i or --inum option is ignored.
################################################################################
function _func_polap_count-gene() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	if [ $# -eq 0 ]; then
		INUM=0
	elif [ $# -eq 1 ]; then
		INUM=$1
	fi

	_run_polap_count-gene

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Counts genes annotated on a genome assembly.
# Arguments:
#   -i $INUM: a Flye genome assembly number
# Inputs:
#   $FDIR/30-contigger/contigs_stats.txt
#   $MTGENECOUNT
#   $PTGENECOUNT
# Outputs:
#   $FDIR/mt.contig.name-1
#   $FDIR/mt.contig.name-2
#   $FDIR/assembly_info_organelle_annotation_count.txt
#   $FDIR/assembly_info_organelle_annotation_count-all.txt
#   $FDIR/contig-annotation-table.txt
################################################################################
function _run_polap_count-gene() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	ANUM=$INUM
	FDIR="$ODIR"/$ANUM
	ADIR="$FDIR"/50-annotation
	MTGENECOUNT="$ADIR"/mt.gene.count
	PTGENECOUNT="$ADIR"/pt.gene.count

	help_message=$(
		cat <<HEREDOC
# Counts genes annotated on a genome assembly.
# Arguments:
#   -i $INUM: a Flye genome assembly number
# Inputs:
#   $FDIR/30-contigger/contigs_stats.txt
#   $MTGENECOUNT
#   $PTGENECOUNT
# Outputs:
#   $FDIR/mt.contig.name-1
#   $FDIR/mt.contig.name-2
#   $FDIR/assembly_info_organelle_annotation_count.txt
#   $FDIR/assembly_info_organelle_annotation_count-all.txt
#   $FDIR/contig-annotation-table.txt 
Example: $(basename "$0") ${_arg_menu[0]} [-i|--inum <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	echoall "INFO: count mitochondrial and plastid genes on $ANUM"

	"$WDIR"/run-polap-mtcontig.R "$FDIR" \
		"$FDIR"/mt.contig.name \
		"$FDIR"/assembly_info_organelle_annotation_count.txt \
		"$FDIR"/assembly_info_organelle_annotation_count-all.txt \
		--contigger \
		>/dev/null 2>&1

	echoall "USE: assembly graph: "$PWD"/"$FDIR"/30-contigger/graph_final.gfa"
	echoall "USE: the following three count tables"
	echoall "column -t "$FDIR"/assembly_info_organelle_annotation_count-all.txt | less -S"
	echoall "column -t "$FDIR"/assembly_info_organelle_annotation_count.txt | less -S"
	echoall "column -t "$FDIR"/contig-annotation-table.txt | less -S"
	if [[ ${_arg_test} == "on" ]]; then
		echoall "LOG: creating $FDIR/mt.contig.name-1 for testing purpose"
		echoall "LOG: you would have to edit it for a real data-set."
		echo edge_1 >"$FDIR"/mt.contig.name-1
		echo edge_2 >>"$FDIR"/mt.contig.name-1
		echo edge_3 >>"$FDIR"/mt.contig.name-1
	fi
	echoerr "Example file: $FDIR/mt.contig.name-1"
	echoerr "edge_1"
	echoerr "edge_2"
	echoerr "edge_3"
	echoall "INFO: edit $FDIR/mt.contig.name-1 for mtDNA contig candidates"
	echo "INFO: edit $FDIR/mt.contig.name-<destination flye number> for mtDNA contig candidates"

	ANUMNEXT=$((ANUM + 1))
	echoerr NEXT: $(basename "$0") select-reads -o "$ODIR" [-i $ANUM] [-j $ANUMNEXT]
	echoerr NEXT: $(basename "$0") assemble2 -o "$ODIR" [-i $ANUM] [-j $ANUMNEXT]
	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Called in the script not by users.
# -i or --inum option is ignored.
################################################################################
function _func_polap_select-reads() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	if [ $# -eq 0 ]; then
		INUM=0
		JNUM=1
	elif [ $# -eq 1 ]; then
		INUM=0
		JNUM=$1
	elif [ $# -eq 2 ]; then
		INUM=$1
		JNUM=$2
	fi

	_run_polap_select-reads

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Selects reads mapped on a genome assembly.
# Arguments:
#   -i $INUM: source Flye (usually whole-genome) assembly number
#   -j $JNUM: destination Flye organelle assembly number
#   -r $MPAIR: minimum minimap2 alignment length for a pair of contigs
#   -x $MBRIDGE: minimum long-read length for connecting the pair of contigs
#   -w $MSINGLE: minimum minimap2 alignment length for a single contig
# Inputs:
#   $MTCONTIGNAME
#   ${assembly_graph_final_fasta}
# Outputs:
#   $MTSEEDSDIR
#   $MTDIR/contig.fa
#   $MTDIR/contig_total_length.txt
#   $MTDIR/contig.paf
#   $MTDIR/contig.tab
#   $MTSEEDSDIR/1.names
#   $MTSEEDSDIR/1.fq.gz
#   $MTSEEDSDIR/2.fq.gz
################################################################################
function _run_polap_select-reads() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	MR=$_arg_min_read_length
	FDIR="$ODIR"/$INUM
	ADIR="$FDIR"/50-annotation
	MTDIR="$ODIR"/$JNUM
	MTSEEDSDIR="$MTDIR"/seeds

	MTCONTIGNAME="$FDIR"/mt.contig.name-$JNUM

	# for contigs
	#	assembly_graph_final_fasta=o/30-contigger/contigs.fasta
	#	for edges
	assembly_graph_final_fasta="$FDIR"/30-contigger/graph_final.fasta

	help_message=$(
		cat <<HEREDOC
# Selects reads mapped on a genome assembly.
# Arguments:
#   -i $INUM: source Flye (usually whole-genome) assembly number
#   -j $JNUM: destination Flye organelle assembly number
#   -r $MPAIR: minimum minimap2 alignment length for a pair of contigs
#   -x $MBRIDGE: minimum long-read length for connecting the pair of contigs
#   -w $MSINGLE: minimum minimap2 alignment length for a single contig
# Inputs:
#   $MTCONTIGNAME
#   ${assembly_graph_final_fasta}
# Outputs:
#   $MTDIR/contig.fa
#   $MTSEEDSDIR/1.names
#   $MTSEEDSDIR/2.fq.gz
Example: $(basename "$0") ${_arg_menu[0]} [-i|--inum <arg>] [-j|--jnum <arg>] [-r|--pair-min <arg>] [-x|--bridge-min <arg>] [-w|--single-min <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ ! -s "$MTCONTIGNAME" ]; then
		echoall "ERROR: no such mt.contig.name file: $MTCONTIGNAME"
		exit $EXIT_ERROR
	fi

	if [ ! -s "${assembly_graph_final_fasta}" ]; then
		echoall "ERROR: no assembly fasta file: ${assembly_graph_final_fasta}"
		exit $EXIT_ERROR
	fi

	if [ -d "$MTDIR" ] && [ "${_arg_yes}" = "off" ]; then
		while true; do
			read -r -p "Folder [$MTDIR] already exists. Do you want to replace it? [y/n] " yn
			case $yn in
			[Yy]*)
				rm -rf "$MTDIR"
				echo "INFO: $MTDIR is deleted."
				break
				;;
			[Nn]*)
				echoall "INFO: [$MTDIR] is not replaced."
				echoerr "you might want a new mt.contig.name file for flye2 step."
				exit $EXIT_FAIL
				;;
			*) echo "Please answer yes or no." ;;
			esac
		done
	else
		rm -rf "$MTDIR"
		echo "INFO: $MTDIR is deleted if there is one."
	fi

	echo "$CMD" >"$ODIR"/organelle-assembly_"${INUM}"-"${JNUM}"

	mkdir -p "$MTSEEDSDIR"
	ln -s "$PWD"/"$ODIR"/nk.fq.gz -t "$MTDIR"
	echoall "INFO: extracts contigs from the assembly ${assembly_graph_final_fasta}"
	echo "INFO: uses mt.contig.name at $MTCONTIGNAME"
	echoerr "FILE: reading contigs in $MTCONTIGNAME"
	cat "$MTCONTIGNAME" >&2
	echoerr "please, wait for a long-read data selection ... $INUM -> $JNUM ... bridge=$MBRIDGE p_mapping=$MPAIR s_mapping=$MSINGLE min_len_read=$MR"
	seqkit grep --threads "$NT" -f "$MTCONTIGNAME" "${assembly_graph_final_fasta}" -o "$MTDIR"/contig.fa >/dev/null 2>&1

	contig_count=$(wc -l <"$MTCONTIGNAME")
	if [[ $CIRCULARIZE == "on" ]]; then
		if [ "$contig_count" -eq 1 ]; then
			seqkit fx2tab --length --name "$MTDIR"/contig.fa -o "$MTDIR"/contig.fa.len >/dev/null 2>&1
			A=$(cut -f2 "$MTDIR"/contig.fa.len)
			B=$(echo "scale=0; $A/2" | bc)
			C=$((B + 1))
			seqkit subseq -r 1:"$B" "$MTDIR"/contig.fa -o "$MTDIR"/c1.fa >/dev/null 2>&1
			seqkit subseq -r "$C":"$A" "$MTDIR"/contig.fa -o "$MTDIR"/c2.fa >/dev/null 2>&1
			cat "$MTDIR"/c?.fa | seqkit replace -p '.+' -r 'edge_{nr}' -o "$MTDIR"/contig.fa >/dev/null 2>&1
			cp "$MTCONTIGNAME" "$MTCONTIGNAME"-backup
			echo -e "edge_1\nedge_2" >"$MTCONTIGNAME"
			echo "INFO: creates new $MTDIR/contig.fa and $MTCONTIGNAME"
		else
			echo "DEV: not implemented yet"
			exit $EXIT_ERROR
			# "$WDIR"/run-polap-single.R "$MTSEEDSDIR"/contig.tab "$MTSEEDSDIR" "$MSINGLE" >/dev/null 2>&1
			# cat "$MTSEEDSDIR"/single.names | sort | uniq >"$MTSEEDSDIR"/1.names
			# echo "INFO: creates long read single name in $MTSEEDSDIR/1.names"
		fi
	fi
	echo "DATA: $MTDIR/contig.fa is created."

	CONTIG_LENGTH=$(seqkit stats -Ta "$MTDIR"/contig.fa | csvtk cut -t -f "sum_len" | csvtk del-header)
	echo "$CONTIG_LENGTH" >"$MTDIR"/contig_total_length.txt
	echo "INFO: organelle genome size based on contig selection: $CONTIG_LENGTH"

	if [[ -s "$MTDIR"/contig.paf ]]; then
		echo "DATA: previously created $MTDIR/contig.paf is used without executing minimap2."
	else
		minimap2 -cx map-ont "$MTDIR"/contig.fa "$LRNK" -t "$NT" -o "$MTDIR"/contig.paf >/dev/null 2>&1
		echo "DATA: $LRNK is used to select reads."
		echo "DATA: $MTDIR/contig.paf is created."
	fi

	cut -f1-11 "$MTDIR"/contig.paf | awk -v minlength="$MR" '{if ($2>=minlength) {print}}' >"$MTDIR"/contig.tab
	echo "DATA: minimum length of long reads in the read selection: $MR"
	echo "DATA: $MTDIR/contig.tab is created."

	# MT: MPAIR=3000 MBRIDGE=3000 MSINGLE=3000
	# PT: MPAIR=1000 MBRIDGE=5000 MSINGLE=0
	Rscript --vanilla "$WDIR"/run-polap-pairs.R "$MTCONTIGNAME" "$MTDIR"/contig.tab "$MTSEEDSDIR" "$MPAIR" "$MBRIDGE" "$MSINGLE" >/dev/null 2>&1
	# "$WDIR"/run-polap-pairs.R "$MTCONTIGNAME" $MTDIR/contig.tab $MTSEEDSDIR $MPAIR $MBRIDGE $MSINGLE >/dev/null 2>&1
	echo "OPTION polap pairs alignment minimum: $MPAIR"
	echo "OPTION polap pairs bridge minimum: $MBRIDGE"
	echo "DATA: pair contig names in $MTSEEDSDIR are created."
	echo "DATA: single contig name in $MTSEEDSDIR is created."

	# cat "$MTSEEDSDIR/"*".name" "$MTSEEDSDIR"/single.names | sort | uniq >"$MTSEEDSDIR"/1.names
	cat "$MTSEEDSDIR"/single.names | sort | uniq >"$MTSEEDSDIR"/1.names
	echo "INFO: creates long read names and the single name in $MTSEEDSDIR/1.names"

	# seqkit grep --threads $NT -f "$MTSEEDSDIR"/1.names $LRNK -o "$MTSEEDSDIR"/1.fq.gz >/dev/null 2>&1
	seqtk subseq "$LRNK" "$MTSEEDSDIR"/1.names | gzip >"$MTSEEDSDIR"/1.fq.gz
	echo "DATA: organelle reads in $MTSEEDSDIR/1.fq.gz"

	TOTAL_LENGTH=$(seqkit stats -Ta "$MTSEEDSDIR"/1.fq.gz | csvtk cut -t -f "sum_len" | csvtk del-header)
	EXPECTED_ORGANELLE_COVERAGE=$((TOTAL_LENGTH / CONTIG_LENGTH))
	echo "INFO: expected coverage: ${EXPECTED_ORGANELLE_COVERAGE}x"

	if [[ "${_arg_coverage_check}" == "off" ]]; then
		echoall "OPTION: --no-coverage-check No reduction of the long-read data"
		ln -s "$(realpath 1.fq.gz)" "$MTSEEDSDIR"/2.fq.gz
	else
		if [ "$EXPECTED_ORGANELLE_COVERAGE" -lt "$COV" ]; then
			echoall "LOG: No reduction of the long-read data because $EXPECTED_ORGANELLE_COVERAGE < $COV"
			ln -s "$(realpath 1.fq.gz)" "$MTSEEDSDIR"/2.fq.gz
		else
			echoall "SUGGESTION: you might want to increase the minimum read lengths because you have enough long-read data."
			RATE=$(echo "scale=10; $COV/$EXPECTED_ORGANELLE_COVERAGE" | bc)
			echoall "LOG: long-read data reduction by rate of $RATE <= COV[$COV] / long-read organelle coverage[$EXPECTED_ORGANELLE_COVERAGE]"
			echoall "sampling long-read data by $RATE ... wait ..."
			seqkit sample -p "$RATE" "$MTSEEDSDIR/1.fq.gz" -o "$MTSEEDSDIR/2.fq.gz" >/dev/null 2>&1
			echoall "DATA: a reduced long-read data $MTSEEDSDIR/2.fq.gz is created"
		fi
	fi

	C=$(ls -1 "$MTSEEDSDIR/"*".name" 2>/dev/null | wc -l)
	if [ "$C" != 0 ]; then
		echo "INFO: bridging reads exist: combinations of $C."
		seqkit seq -n -i "$MTSEEDSDIR"/2.fq.gz >"$MTSEEDSDIR"/single.names.2
		cat "$MTSEEDSDIR/"*".name" "$MTSEEDSDIR"/single.names.2 | sort | uniq >"$MTSEEDSDIR"/1.names.2
		# seqkit grep --threads $NT -f "$MTSEEDSDIR"/1.names.2 $LRNK -o "$MTSEEDSDIR"/2.fq.gz >/dev/null 2>&1
		seqtk subseq "$LRNK" "$MTSEEDSDIR"/1.names.2 | gzip >"$MTSEEDSDIR"/2.fq.gz
	fi
	echo "DATA: organelle reads in $MTSEEDSDIR/2.fq.gz"

	# put the backup to the original
	if [[ $CIRCULARIZE == "on" ]]; then
		if [[ -s "$MTCONTIGNAME"-backup ]]; then
			mv "$MTCONTIGNAME"-backup "$MTCONTIGNAME"
		else
			echo "DEV: not implemented yet"
			exit $EXIT_ERROR
		fi
	fi

	echoerr NEXT: "$(basename "$0")" flye2 -o "$ODIR" -j "$JNUM" -t "$NT" -c "$COV"

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Called in the script not by users.
# -i or --inum option is ignored.
################################################################################
function _func_polap_flye2() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	if [ $# -eq 0 ]; then
		JNUM=1
	else
		JNUM=$1
	fi

	_run_polap_flye2

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Executes Flye for an organelle-genome assembly
# Arguments:
#   -j $JNUM: destination Flye organelle assembly number
#   -t $NT: the number of CPU cores
#   -c $COV: the Flye's coverage option
#   -g <arg>: computed by find-genome-size menu or given by users
# Inputs:
#   $MTDIR/contig.fa
#   $MTSEEDSDIR/2.fq.gz
# Outputs:
#   $MTDIR/contig_total_length.txt
#   $MTDIR/30-contigger/contigs.fasta
#   $MTDIR/30-contigger/contigs_stats.txt
#   $MTDIR/30-contigger/graph_final.fasta
#   $MTDIR/30-contigger/graph_final.gfa
################################################################################
function _run_polap_flye2() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	echo "INFO: organelle-genome assembly on $JNUM"

	MTDIR="$ODIR"/$JNUM
	MTSEEDSDIR="$MTDIR"/seeds

	help_message=$(
		cat <<HEREDOC
# Executes Flye for an organelle-genome assembly
# Arguments:
#   -j $JNUM: destination Flye organelle assembly number
#   -t $NT: the number of CPU cores
#   -c $COV: the Flye's coverage option
#   -g <arg>: computed by find-genome-size menu or given by users
# Inputs:
#   $MTDIR/contig.fa
#   $MTSEEDSDIR/2.fq.gz
# Outputs:
#   $MTDIR/contig_total_length.txt
#   $MTDIR/30-contigger/contigs.fasta
#   $MTDIR/30-contigger/contigs_stats.txt
#   $MTDIR/30-contigger/graph_final.fasta
#   $MTDIR/30-contigger/graph_final.gfa
Example: $(basename $0) ${_arg_menu[0]} [-j|--jnum <arg>] [-t|--threads <arg>] [-c|--coverage <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ ! -s "$MTDIR/contig.fa" ]; then
		echoall "ERROR: no selected-contig file [$MTDIR/contig.fa]"
		echoerr "SUGGESTION: select-reads"
		exit $EXIT_SUCCESS
	fi

	if [ ! -s "$MTSEEDSDIR/2.fq.gz" ]; then
		echoall "ERROR: no long-read file [$MTSEEDSDIR/2.fq.gz]"
		echoerr "SUGGESTION: select-reads"
		exit $EXIT_SUCCESS
	fi

	CONTIG_LENGTH=$(seqkit stats -Ta "$MTDIR"/contig.fa | csvtk cut -t -f "sum_len" | csvtk del-header)
	echo "$CONTIG_LENGTH" >"$MTDIR"/contig_total_length.txt
	echo "INFO: organelle genome size based on contig selection: $CONTIG_LENGTH"

	echo "INFO: executing the organelle-genome assembly using flye ... be patient!"
	echoerr "please, wait for an organelle-genome assembly on $JNUM ..."
	flye --nano-raw "$MTSEEDSDIR"/2.fq.gz \
		--out-dir "$MTDIR" \
		--threads "$NT" \
		--asm-coverage "$COV" \
		--genome-size "$CONTIG_LENGTH" \
		--stop-after contigger \
		>/dev/null 2>&1
	echoall "CHECK: assembly graph "$PWD/$MTDIR"/30-contigger/graph_final.gfa"
	# echo "column -t $ODIR/assembly_info_organelle_annotation_count.txt"

	jnum_next=$((JNUM + 1))
	echoall Create and edit $ODIR/$JNUM/mt.contig.name-${jnum_next}
	echoall NEXT: "$(basename "$0")" assemble2 -o "$ODIR" -j ${jnum_next}
	echoall or you could finish with Flye organelle-genome assembly with its polishing stage.
	echoall NEXT: "$(basename "$0")" flye-polishing -o "$ODIR" -j "$JNUM"

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Finishes the Flye organelle-genome assembly.
# Polishes an organelle-genome assembly using long-reads.
# Note: use the same options as flye2 menu.
# Arguments:
#   -j $JNUM: destination Flye organelle assembly number
#   -t $NT: the number of CPU cores
#   -c $COV: the Flye's coverage option
#   -g <arg>: computed by find-genome-size menu or given by users
# Inputs:
#   $MTDIR/contig.fa
#   $MTSEEDSDIR/2.fq.gz
#   $MTDIR/30-contigger
# Outputs:
#   $MTDIR/assembly_graph.gfa
################################################################################
function _run_polap_flye-polishing() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	echo "INFO: polishing organelle-genome assembly on $JNUM"

	MTDIR="$ODIR"/$JNUM
	MTSEEDSDIR="$MTDIR"/seeds

	help_message=$(
		cat <<HEREDOC
# Finishes the Flye organelle-genome assembly.
# Polishes an organelle-genome assembly using long-reads.
# Note: use the same options as flye2 menu.
# Arguments:
#   -j $JNUM: destination Flye organelle assembly number
#   -t $NT: the number of CPU cores
#   -c $COV: the Flye's coverage option
#   -g <arg>: computed by find-genome-size menu or given by users
# Inputs:
#   $MTDIR/contig.fa
#   $MTSEEDSDIR/2.fq.gz
#   $MTDIR/30-contigger
# Outputs:
#   $MTDIR/assembly_graph.gfa
Example: $(basename "$0") ${_arg_menu[0]} [-j|--jnum <arg>] [-t|--threads <arg>] [-c|--coverage <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ ! -s "$MTDIR/contig.fa" ]; then
		echoall "ERROR: no selected-contig file [$MTDIR/contig.fa]"
		echoerr "SUGGESTION: select-reads"
		exit $EXIT_SUCCESS
	fi

	if [ ! -s "$MTSEEDSDIR/2.fq.gz" ]; then
		echoall "ERROR: no long-read file [$MTSEEDSDIR/2.fq.gz]"
		echoerr "SUGGESTION: select-reads"
		exit $EXIT_SUCCESS
	fi

	CONTIG_LENGTH=$(seqkit stats -Ta "$MTDIR"/contig.fa | csvtk cut -t -f "sum_len" | csvtk del-header)
	echo "INFO: organelle genome size based on contig selection: $CONTIG_LENGTH"

	echo "INFO: polishing the organelle-genome assembly using flye ... be patient!"
	echoerr "please, wait for Flye long-read polishing the organelle-genome assembly on $JNUM ..."
	flye --nano-raw "$MTSEEDSDIR"/2.fq.gz \
		--out-dir "$MTDIR" \
		--threads "$NT" \
		--asm-coverage "$COV" \
		--genome-size "$CONTIG_LENGTH" \
		--resume \
		>/dev/null 2>&1
	echoall "CHECK: the long-read polished assembly graph $PWD/$MTDIR/assembly_graph.gfa"
	echoerr "DO: extract a draft organelle genome sequence (mt.0.fasta) from the polished assembly graph"
	# echo "column -t $ODIR/assembly_info_organelle_annotation_count.txt"
	# echoall NEXT: $(basename $0) check-coverage [-p $PA]
	echoall NEXT: "$(basename "$0")" prepare-polishing -a "$SR1" -b "$SR2"

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Fetches mtDNA genome sequence by species name.
# Arguments:
#   --sra SRR10190639
################################################################################
function _run_polap_x-ncbi-fetch-sra-runinfo() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Fetches mtDNA genome sequence by species name.
# Arguments:
#   --sra SRR10190639
# Outputs:
#   bases
Example: $(basename $0) ${_arg_menu[0]} --sra <arg>
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ -z "$_arg_sra" ]; then
		echoerr "ERROR: no --sra option is used."
		exit $EXIT_SUCCESS
	fi

	echoerr "counting bases in SRA database and its downloaded FASTQ files of SRA [${_arg_sra}] ..."
	bases=$(esearch -db sra -query "${_arg_sra}" |
		efetch -format runinfo |
		csvtk cut -f "bases" |
		csvtk del-header)
	echoall "SRA: ${_arg_sra}: ${bases} (bp)"

	bases2=$(seqkit stats -T "${_arg_sra}"*.fastq 2>/dev/null | csvtk cut -t -f "sum_len" | paste -s -d+ - | bc)
	echoall "FASTQ: ${_arg_sra}*.fastq: ${bases2} (bp)"

	if [ "${bases}" -eq "${bases2}" ]; then
		echoall "LOG: SRA ${_arg_sra} and its FASTQ files: total bases match."
	else
		echoall "ERROR: SRA ${_arg_sra} and its FASTQ files: total bases do not match."
	fi

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Fetches mtDNA genome sequence by species name.
# Arguments:
#   --species
################################################################################
function _run_polap_x-ncbi-fetch-mtdna-genbank() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Fetches mtDNA genome sequence by species name.
# Arguments:
#   --species species-name
# Inputs:
#   species-name
# Outputs:
#   species-name.mt.gb
Example: $(basename "$0") ${_arg_menu[0]} --species <arg>
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ -z "$_arg_species" ]; then
		echoerr "ERROR: no --species option is used."
	else
		S="${_arg_species// /-}"
		esearch -db nuccore -query "(mitochondrion[Title] AND complete[Title] AND genome[Title]) AND ${_arg_species}[Organism]" |
			efetch -format gb >"${S}".mt.gb
	fi

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Fetches mtDNA genome sequence by accession.
# Arguments:
#   --accession
# Inputs:
#   accession ID
# Outputs:
#   <accession>.fa
################################################################################
function _run_polap_x-ncbi-fetch-mtdna-nucleotide() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Fetches mtDNA genome sequence by species name.
# Arguments:
#   --accession <arg>
# Inputs:
#   accession ID
# Outputs:
#   <accession>.fa
Example: $(basename "$0") ${_arg_menu[0]} --accession <arg>
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ -z "$_arg_accession" ]; then
		echoerr "ERROR: no --accession option is used."
	else
		esearch -db nuccore -query "${_arg_accession}[ACCN]" </dev/null |
			efetch -format fasta >"${_arg_accession}".fa
		echoall "NEXT: $(basename "$0") align-two-dna-sequences --query mt.1.fa --subject ${_arg_accession}.fa"
	fi

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Uses BLAST to align two very similar DNA sequences.
# Before align the two sequences, rearrange the assembled query sequences
# so that they are alignable using multiple sequence alignment tools
# like ClustalW.
# Arguments:
#   --query ${_arg_query}
#   --subject ${_arg_subject}
# Inputs:
#   query: mt.1.fa or the assembled sequence
#   subject: a known mtDNA sequence
# Outputs:
#   pairwise-alignment.txt
################################################################################
function _run_polap_x-align-two-dna-sequences() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Uses BLAST to align two very similar DNA sequences.
# Before align the two sequences, rearrange the assembled query sequences
# so that they are alignable using multiple sequence alignment tools
# like ClustalW.
# Arguments:
#   --query ${_arg_query}
#   --subject ${_arg_subject}
# Inputs:
#   query: mt.1.fa or the assembled sequence
#   subject: a known mtDNA sequence
# Outputs:
#   pairwise-alignment.txt
Example: $(basename "$0") ${_arg_menu[0]} [--query <arg>] [--subject <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ -z "$_arg_query" -a -z "$_arg_subject" ]; then
		echoerr "ERROR: no --query and --subject option are used."
		echoerr "INFO: --query mt.1.fa --subject NCBI.fa"
		echoerr "INFO: seqkit seq -p -r mt.1.fa -o mt.1r.fa"
		echoerr "INFO: seqkit restart -i <POS> mt.1.fa -o mt.2.fa"
	else
		blastn -query "$_arg_query" -subject "$_arg_subject" >pairwise-alignment.txt
		echoerr "INFO: seqkit seq -p -r mt.1.fa -o mt.1r.fa"
		echoerr "INFO: seqkit restart -i <POS> mt.1.fa -o mt.2.fa"
		echoerr "INFO: $(basename "$0") clustal --query mt.2.fa --subject NCBI-ACC.fa"
		echoerr see pairwise-alignment.txt
	fi

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Uses clustalw to align two DNA sequences.
# After rearranging parts of a query assembled sequence,
# we use clustalw to align the two to check how similar they are.
# Arguments:
#   --query ${_arg_query}
#   --subject ${_arg_subject}
# Inputs:
#   query: mt.1.fa or the assembled sequence
#   subject: a known mtDNA sequence
################################################################################
function _run_polap_x-clustal() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Uses clustalw to align two DNA sequences.
# After rearranging parts of a query assembled sequence,
# we use clustalw to align the two to check how similar they are.
# Arguments:
#   --query ${_arg_query}
#   --subject ${_arg_subject}
# Inputs:
#   query: mt.1.fa or the assembled sequence
#   subject: a known mtDNA sequence
Example: $(basename "$0") ${_arg_menu[0]} [--query <arg>] [--subject <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [[ -s x.aln ]]; then
		echoall "INFO: clustalw alignemnt is found."
	else
		local MT1=$_arg_query
		shift
		local MT2=$_arg_subject
		shift
		command -v clustalw2 >/dev/null 2>&1 || {
			echo >&2 "clustalw2: not installed"
			exit 1
		}
		cat "$MT1" "$MT2" >x.fa
		clustalw2 x.fa
	fi
	# TODO: works for only Linux.
	GAP1=$(sed -n '4~4p' x.aln | tr -s ' ' | cut -d' ' -f2 | tr -d '\n' | tr -dc '-' | wc -c)
	GAP2=$(sed -n '5~4p' x.aln | tr -s ' ' | cut -d' ' -f2 | tr -d '\n' | tr -dc '-' | wc -c)
	MATCH=$(sed -n '6~4p' x.aln | tr -dc '*' | wc -c)
	TOTAL=$(sed -n '4~4p' x.aln | tr -s ' ' | cut -d' ' -f2 | tr -d '\n' | wc -c)
	GAP=$((GAP1 + GAP2))
	MISMATCH=$((TOTAL - MATCH - GAP))
	echoall "INFO: pairwise alignment:   length: $TOTAL"
	echoall "INFO: pairwise alignment:    match: $MATCH"
	echoall "INFO: pairwise alignment: mismatch: $MISMATCH"
	echoall "INFO: pairwise alignment:     gaps: $GAP"
	LENGTH1=$(seqkit stats -Ta "$_arg_subject" | csvtk cut -t -f "sum_len" | csvtk del-header)
	LENGTH2=$(seqkit stats -Ta "$_arg_query" | csvtk cut -t -f "sum_len" | csvtk del-header)
	NAME1=$(seqkit seq -n -i "$_arg_subject")
	NAME2=$(seqkit seq -n -i "$_arg_query")
	echoall "INFO: Sequence1: $NAME1"
	echoall "INFO: SequenceLen1: $LENGTH1"
	echoall "INFO: Sequence2: $NAME2"
	echoall "INFO: SequenceLen2: $LENGTH2"

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Checks the coverage using samtools.
# Arguments:
#   -p mt.0.fasta
# Inputs:
#   $LRNK
#   $PA
# Outputs:
#   $FA
################################################################################
function _run_polap_x-check-coverage() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# NOT IMPLEMENTED YET
# Checks the coverage on a draft genome using samtools.
# Arguments:
#   -p $PA: a draft genome
# Inputs:
#   $LRNK
#   $PA
# Outputs:
Example: $(basename "$0") ${_arg_menu[0]} [-p|--unpolished-fasta <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ -z "$PA" ] && [ -z "$LRNK" ]; then
		echoerr "ERROR: no -p option are used."
		echoerr "INFO: --p mt.0.fasta"
	else
		echo "INFO: executing minimap2 and samtools for checking the long reads coverage on the $PA ... be patient!"
		if [[ ! -s "$PA" ]]; then
			echoall "ERROR: no such file $PA"
			exit $EXIT_ERROR
		fi

		if [[ ! -s "$LRNK" ]]; then
			echoall "ERROR: no such file $LRNK"
			exit $EXIT_ERROR
		fi

		minimap2 -t "$NT" -ax map-ont "$PA" "$LRNK" 2>/dev/null |
			samtools view -u 2>/dev/null |
			samtools sort -o "$ODIR"/1.bam \
				>/dev/null 2>&1
		samtools coverage -A -w 32 "$ODIR"/1.bam 1>&2

		echoerr INFO: conda env create -f "$WDIR"/environment-fmlrc.yaml
		echoerr INFO: conda activate polap-fmlrc
		echoerr "NEXT: $(basename "$0") prepare-polishing [-a s1.fq] [-b s2.fq]"
	fi

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Prepares the polishing using FMLRC.
# Arguments:
#   -a s1.fq
#   -b s2.fq
# Inputs:
#   s1.fq
#   s2.fq
# Outputs:
#   $$ODIR/msbwt
################################################################################
function _run_polap_prepare-polishing() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Prepares the polishing using FMLRC.
# Arguments:
#   -a $SR1
#   -b $SR2
# Inputs:
#   $SR1
#   $SR2
# Outputs:
#   $ODIR/msbwt/comp_msbwt.npy
Example: $(basename "$0") ${_arg_menu[0]} [-a|--short-read1 <arg>] [-b|--short-read2 <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	source $HOME/miniconda3/bin/activate polap-fmlrc

	if ! run_check2; then
		echoerr "ERROR: change your conda environment to polap-fmlrc."
		echoerr "INFO: (base) $ conda env create -f src/environment-fmlrc.yaml"
		echoerr "INFO: (base) $ conda activate polap-fmlrc"
		exit $EXIT_ERROR
	fi

	if [[ ! -s $SR1 ]]; then
		echo "ERROR: no short-read data file found: $SR1"
		exit $EXIT_ERROR
	fi
	if [[ ! -s $SR2 ]]; then
		echo "ERROR: no short read-data file found: $SR2"
		exit $EXIT_ERROR
	fi

	echo "INFO: excuting ropebwt2 and msbwt on the short reads ... be patient!"
	if [[ $SR1 = *.fastq || $SR1 = *.fq ]]; then
		cat "$SR1" "$SR2" |
			awk 'NR % 4 == 2' | sort | tr NT TN | ropebwt2 -LR | tr NT TN |
			msbwt convert "$ODIR"/msbwt \
				>/dev/null 2>&1
	elif [[ $SR1 = *.fq.gz ]] || [[ $SR1 = *.fastq.gz ]]; then
		zcat "$SR1" "$SR2" |
			awk 'NR % 4 == 2' | sort | tr NT TN | ropebwt2 -LR | tr NT TN |
			msbwt convert "$ODIR"/msbwt \
				>/dev/null 2>&1
	fi

	echoerr "NEXT: $(basename $0) polish [-p mt.0.fasta] [-f mt.1.fa]"

	conda deactivate

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Polishes using FMLRC.
# Arguments:
#   -p mt.0.fasta
#   -f mt.1.fa
# Inputs:
#   $ODIR/msbwt/comp_msbwt.npy
#   $PA
# Outputs:
#   $FA
################################################################################
function _run_polap_polish() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Polishes using FMLRC.
# Arguments:
#   -p $PA: a long-read draft genome assembly
#   -f $FA: a final genome assembly sequence name
# Inputs:
#   $ODIR/msbwt/comp_msbwt.npy
#   $PA
# Outputs:
#   $FA
Example: $(basename "$0") ${_arg_menu[0]} [-p|--unpolished-fasta <arg>] [-f|--final-assembly <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	source $HOME/miniconda3/bin/activate polap-fmlrc

	if ! run_check2; then
		echoerr "ERROR: change your conda environment to polap-fmlrc."
		echoerr "INFO: (base) $ conda env create -f src/environment-fmlrc.yaml"
		echoerr "INFO: (base) $ conda activate polap-fmlrc"
		exit $EXIT_ERROR
	fi

	if [[ ! -s "$ODIR/msbwt/comp_msbwt.npy" ]]; then
		echoall "ERROR: no msbwt at $ODIR/msbwt/comp_msbwt.npy"
		echoall "HINT: $0 prepare-polishing [-a s1.fq] [-b s2.fq]"
		exit $EXIT_ERROR
	fi

	echo "INFO: executing fmlrc on the draft sequence $PA ... be patient!"
	if [[ -s $PA ]]; then
		fmlrc -p "$NT" "$ODIR"/msbwt/comp_msbwt.npy "$PA" "$FA" >/dev/null 2>&1
	else
		echo "ERROR: no unpolished fasta file: [$PA]"
		exit $EXIT_ERROR
	fi

	conda deactivate

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Runs the whole-genome assembly.
# Defaults:
#   l.fq
#   s1.fq
#   s2.fq
#   number of threads: $NT
#   assembly coverage: $COV
# Outputs:
#   $ODIR/long_total_length.txt
#   $ODIR/jellyfish_out.histo
#   $ODIR/short_expected_genome_size.txt
#   $LRNK
#   $FDIR
################################################################################
function _run_polap_assemble1() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	help_message=$(
		cat <<HEREDOC
# Runs the whole-genome assembly.
# Arguments:
#   -o $ODIR
#   -l $LR: a long-read fastq data file
#   -a $SR1: a short-read fastq data file
#   -b $SR2: another short-read fastq data file
#   -m $MR: the long-read sequence length threshold
#   -t $NT: the number of CPU cores
#   -c $COV: the Flye's coverage option
#   -g <arg>: computed by find-genome-size menu or given by users
# Inputs:
#   $LR: a long-read fastq 
#   $SR1: a short-read fastq data file
#   $SR2: another short-read fastq data file
ta file
# Outputs:
#   $ODIR/long_total_length.txt
#   $ODIR/short_expected_genome_size.txt
#   $LRNK
#   $FDIR/30-contigger/contigs.fasta
#   $FDIR/30-contigger/contigs_stats.txt
#   $FDIR/30-contigger/graph_final.fasta
#   $FDIR/30-contigger/graph_final.gfa
Example: $(basename $0) ${_arg_menu[0]} [-o|--outdir <arg>] [-l|--long-reads <arg>] [-a|--short-read1 <arg>] [-b|--short-read2 <arg>] [-t|--threads <arg>] [-c|--coverage <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [[ ! -s $LR ]]; then
		echo "ERROR: no long-read data file found: $LR"
		exit $EXIT_ERROR
	fi
	if [[ ! -s $SR1 ]]; then
		echo "ERROR: no short-read data file found: $SR1"
		exit $EXIT_ERROR
	fi
	if [[ ! -s $SR2 ]]; then
		echo "ERROR: no short read-data file found: $SR2"
		exit $EXIT_ERROR
	fi

	echoerr "NEXT: $(basename $0) reset -o $ODIR"
	_run_polap_reset
	_run_polap_total-length-long
	_run_polap_find-genome-size
	_run_polap_reduce-data
	_run_polap_flye1

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Called in the script not by users.
################################################################################
function _func_polap_annotate() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	if [ $# -eq 0 ]; then
		ANUM=0
	else
		ANUM=$1
	fi

	_func_polap_blast-genome "$ANUM"
	_func_polap_count-gene "$ANUM"

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Annotates the genome assembly.
# Defaults:
# Outputs:
################################################################################
function _run_polap_annotate() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	ANUM=$INUM
	FDIR="$ODIR"/$ANUM
	assembly_contigs_stats="$FDIR"/30-contigger/contigs_stats.txt
	assembly_contigs_fasta="$FDIR"/30-contigger/contigs.fasta
	ADIR="$FDIR"/50-annotation
	MTGENECOUNT="$ADIR"/mt.gene.count
	PTGENECOUNT="$ADIR"/pt.gene.count
	CONTIGNAME="$ADIR"/contig.name

	help_message=$(
		cat <<HEREDOC
# Annotates the genome assembly.
# Arguments:
#   -i $INUM: a Flye genome assembly number
# Inputs:
#   $assembly_contigs_stats
#   $assembly_contigs_fasta
# Outputs:
#   $CONTIGNAME
#   $MTGENECOUNT
#   $PTGENECOUNT
#   $FDIR/mt.contig.name-1
#   $FDIR/mt.contig.name-2
#   $FDIR/assembly_info_organelle_annotation_count.txt
#   $FDIR/assembly_info_organelle_annotation_count-all.txt
#   $FDIR"/contig-annotation-table.txt 
Example: $(basename $0) ${_arg_menu[0]} [-i|--inum <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	echoerr "NEXT: $(basename "$0") blast-genome -i $INUM"
	_run_polap_blast-genome
	_run_polap_count-gene

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# Selects and assembles long-read data.
# Arguments:
#   -i 0
#   -j 1
#   -o o
#   -t $NT
#   -m $MR
#   MPAIR
#   MBRIDGE
#   COV
#   CIRCULARIZE
# Inputs:
# Outputs:
################################################################################
function _run_polap_assemble2() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	MR=$_arg_min_read_length
	FDIR="$ODIR"/$INUM
	ADIR="$FDIR"/50-annotation
	MTDIR="$ODIR"/$JNUM
	MTSEEDSDIR="$MTDIR"/seeds

	MTCONTIGNAME="$FDIR"/mt.contig.name-"$JNUM"

	# for contigs
	#	assembly_graph_final_fasta=o/30-contigger/contigs.fasta
	#	for edges
	assembly_graph_final_fasta="$FDIR"/30-contigger/graph_final.fasta

	help_message=$(
		cat <<HEREDOC
# Selects reads mapped on a genome assembly and assembles an organelle genome.
# Arguments:
#   -i $INUM: source Flye (usually whole-genome) assembly number
#   -j $JNUM: destination Flye organelle assembly number
#   -r $MPAIR: minimum minimap2 alignment length for a pair of contigs
#   -x $MBRIDGE: minimum long-read length for connecting the pair of contigs
#   -w $MSINGLE: minimum minimap2 alignment length for a single contig
#   -t $NT: the number of CPU cores
#   -c $COV: the Flye's coverage option
#   -g <arg>: computed by find-genome-size menu or given by users
# Inputs:
#   $MTCONTIGNAME
#   ${assembly_graph_final_fasta}
# Outputs:
#   $MTDIR/contig.fa
#   $MTSEEDSDIR/1.names
#   $MTSEEDSDIR/2.fq.gz
#   $MTDIR/contig_total_length.txt
#   $MTDIR/30-contigger/contigs.fasta
#   $MTDIR/30-contigger/contigs_stats.txt
#   $MTDIR/30-contigger/graph_final.fasta
#   $MTDIR/30-contigger/graph_final.gfa
Example: $(basename $0) ${_arg_menu[0]} [-i|--inum <arg>] [-j|--jnum <arg>] [-r|--pair-min <arg>] [-x|--bridge-min <arg>] [-w|--single-min <arg>] [-t|--threads <arg>] [-c|--coverage <arg>]
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	if [ ! -s "$MTCONTIGNAME" ]; then
		echoall "ERROR: no such mt.contig.name file: $MTCONTIGNAME"
		exit $EXIT_ERROR
	fi

	if [ ! -s "${assembly_graph_final_fasta}" ]; then
		echoall "ERROR: no assembly fasta file: ${assembly_graph_final_fasta}"
		exit $EXIT_ERROR
	fi
	if [[ ! -s $LRNK ]]; then
		echoall "ERROR: no $LRNK long read-data file found: $LRNK"
		exit $EXIT_ERROR
	fi

	echoerr "NEXT: $(basename $0) select-reads -o $ODIR -i $INUM -j $JNUM"
	_run_polap_select-reads
	_run_polap_flye2

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# NOT IMPLEMENTED YET!
# because we need a manual long-read selection step.
# You could execute this menu with option --test.
#
# Runs the organelle-genome assembly.
# Arguments:
#   -o $ODIR
#   -l $LR: a long-read fastq data file
#   -a $SR1: a short-read fastq data file
#   -b $SR2: another short-read fastq data file
# Inputs:
#   $LR: a long-read fastq
#   $SR1: a short-read fastq data file
#   $SR2: another short-read fastq data file
# Outputs:
#   $MTDIR/assembly_graph.gfa
################################################################################
function _run_polap_assemble() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	MTDIR=$ODIR/$JNUM

	help_message=$(
		cat <<HEREDOC
# NOT IMPLEMENTED YET!
# because we need a manual long-read selection step.
# You could execute this menu with option --test.
#
# Runs the organelle-genome assembly.
# Arguments:
#   -o $ODIR
#   -l $LR: a long-read fastq data file
#   -a $SR1: a short-read fastq data file
#   -b $SR2: another short-read fastq data file
# Inputs:
#   $LR: a long-read fastq 
#   $SR1: a short-read fastq data file
#   $SR2: another short-read fastq data file
# Outputs:
#   $MTDIR/assembly_graph.gfa
Example: $(basename $0) ${_arg_menu[0]} --test
HEREDOC
	)

	if [[ ${_arg_menu[1]} == "help" ]]; then
		echoerr "${help_message}"
		exit $EXIT_SUCCESS
	fi

	_run_polap_assemble1
	_run_polap_annotate
	_run_polap_assemble2
	_run_polap_flye-polishing

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

function _run_polap_x-help() {
	if [ "$DEBUG" -eq 1 ]; then set -x; fi

	print_x-help 1>&2

	if [ "$DEBUG" -eq 1 ]; then set +x; fi
}

################################################################################
# utilities
################################################################################

################################################################################
# for the magic logit function
################################################################################
function logit() {
	while read; do
		# echo "$(date) $REPLY" >> ${LOG_FILE}
		# -1 means "current time"
		# printf "[%(%Y-%m-%d %T)T] %s\n" -1 "$REPLY" >> ${LOG_FILE}
		printf "[%s] %s\n" "$(date +"%Y-%m-%d %T")" "$REPLY" >>${LOG_FILE}
	done
}

function echoerr() { echo "$@" 1>&2; }

function echoall() {
	echo "$@" 1>&2
	echo "$@"
}

function yell() { echo "$0: $*" >&2; }
function die() {
	yell "$*"
	exit 111
}
function try() { "$@" || die "cannot $*"; }

################################################################################
# All of the variables at our disposal
################################################################################

# include and execute other BASH and R scripts
WDIR="$(dirname "$0")"
WDIR="${BASH_SOURCE%/*}"
if [[ ! -d "$WDIR" ]]; then
	WDIR="$PWD"
fi
WDIR=$script_dir

# variables for input data file names for flexible data processing.
LR=$_arg_long_reads       # long-read data file
SR1=$_arg_short_read1     # paired short-read data file 1
SR2=$_arg_short_read2     # paired short-read data file 2
PA=$_arg_unpolished_fasta # assembled draft sequence extracted from bandage
FA=$_arg_final_assembly   # polished sequence

# variables for output
ODIR=$_arg_outdir
INUM=$_arg_inum
JNUM=$_arg_jnum
FDIR="$ODIR"/0 # flye 1st output

# tuning variables for optimal performance
LRNK=$ODIR/nk.fq.gz
MR=$_arg_min_read_length
MPAIR=$_arg_pair_min     # 3000 for MT, 1000 for PT
MBRIDGE=$_arg_bridge_min # used to be 3000,
MSINGLE=$_arg_single_min # not used deprecated
COV=$_arg_coverage
# NT=$(cat /proc/cpuinfo | grep -c processor)
NT=$_arg_threads
if test -z "$DEBUG"; then
	DEBUG=0
fi
CIRCULARIZE=$_arg_circularize # "--circularize"
SPECIES=$_arg_species

################################################################
# Variables
SRA=$_arg_sra
SRALONG=""
SRASHORT=""
RESUME=$_arg_resume
ALL_ANNOTATE="--selective-annotate"
FLYE_CONTIGGER="--contigger"
USE_EDGES="--no-use-edges"
NO_REDUCTION_READS=$_arg_reduction_reads
NO_COVERAGE_CHECK=$_arg_coverage_check

# Constants
EXIT_SUCCESS=0
EXIT_FAIL=1
EXIT_ERROR=2
RETURN_SUCCESS=0
RETURN_FAIL=1

SECONDS=0

################################################################
# MAIN
#
if [ $# -eq 0 ]; then
	print_help
	touch make-menus
	exit $EXIT_SUCCESS
fi

# all message to a log file
# https://stackoverflow.com/questions/49851882/how-to-log-echo-statement-with-timestamp-in-shell-script
LOG_FILE="./polap.log"
exec 3>&1 1>> >(logit)
# exec 3>&1 1>> >(logit) 2>&1

CMD="$0 $*"
echo "CMD: $CMD"

# subcommand function call
if declare -f "_run_polap_${_arg_menu[0]}" >/dev/null 2>&1; then
	# invoke that function, passing arguments through
	_run_polap_"$@" # same as "$1" "$2" "$3" ... for full argument list
else
	echoerr "Menu: assemble1, annotate, assemble2,"
	echoerr "      reset, total-length-long, find-genome-size, reduce-data, flye1,"
	echoerr "      blast-genome, count-gene, select-reads, flye2,"
	echoerr "      flye-polishing, prepare-polishing, polish,"
	echoerr "      assemble,"
	echoerr "ERROR: no such menu of $1"
fi

ELAPSED="Time: $((SECONDS / 3600))hrs $(((SECONDS / 60) % 60))min $((SECONDS % 60))sec - $CMD"
echo "$ELAPSED"

# ^^^  TERMINATE YOUR CODE BEFORE THE BOTTOM ARGBASH MARKER  ^^^

# ] <-- needed because of Argbash
