MFannot
In this section:
Description
According to the documentation of MFannot, MFannot (Mitochondrial/Fungal ANNOTation) is a tool for annotating mitochondrial and fungal genomes. It uses Markov models (HMMs) and protein database similarity to identify and annotate genes, introns, and other features in DNA sequences.
Available Versions
mfannot/1.37 (default)
Loading the Module
# Load MFannot
module load mfannot/1.37
# Verify installation
mfannot -h
Required Input Files
MFannot requires:
FASTA format sequence file
Appropriate genetic code (default: 1 - universal)
Optional: reference file for comparison
Job Submission
submit_mfannot_basic.sh
#!/bin/bash
#SBATCH -J mfannot
#SBATCH -N 1
#SBATCH -n 1
#SBATCH -t 12:00:00
#SBATCH --mem=8G
export INPUT="mitogenome.fasta"
export OUTPUT="annotation.out"
module load mfannot/1.37
job-nanny mfannot -g 1 mitogenome.fasta > annotation.out 2> annotation.err
Annotation with Different Genetic Codes
submit_mfannot_gencode.sh
#!/bin/bash
#SBATCH -J mfannot_gencode
#SBATCH -N 1
#SBATCH -n 1
#SBATCH -t 12:00:00
#SBATCH --mem=8G
export INPUT="mitogenome.fasta"
export OUTPUT="annotation_*.out"
module load mfannot/1.37
# Genetic code 1: Universal (default)
job-nanny mfannot -g 1 mitogenome.fasta > annotation_universal.out
# Genetic code 2: Vertebrate mitochondrial
job-nanny mfannot -g 2 mitogenome.fasta > annotation_vert_mt.out
# Genetic code 3: Yeast mitochondrial
job-nanny mfannot -g 3 mitogenome.fasta > annotation_yeast_mt.out
# Genetic code 4: Protozoan mitochondrial + Mycoplasma
job-nanny mfannot -g 4 mitogenome.fasta > annotation_protozoa_mt.out
Annotation with Similarity Search
submit_mfannot_similarity.sh
#!/bin/bash
#SBATCH -J mfannot_sim
#SBATCH -N 1
#SBATCH -n 1
#SBATCH -t 24:00:00
#SBATCH --mem=16G
export INPUT="novel_sequence.fasta"
export OUTPUT="similarity_annotation.out"
module load mfannot/1.37
# Annotation with similarity search in database
job-nanny mfannot -g 1 -s novel_sequence.fasta > similarity_annotation.out
Job Array for Multiple Sequences
submit_mfannot_array.sh
#!/bin/bash
#SBATCH -J mfannot_array
#SBATCH --array=1-10
#SBATCH -N 1
#SBATCH -n 1
#SBATCH -t 12:00:00
#SBATCH --mem=8G
SEQUENCES=($(ls *.fasta))
SEQ=${SEQUENCES[$SLURM_ARRAY_TASK_ID-1]}
BASE=$(basename "$SEQ" .fasta)
export INPUT="$SEQ"
export OUTPUT="${BASE}_annot/"
module load mfannot/1.37
mkdir -p ${BASE}_annot
cd ${BASE}_annot
cp ../$SEQ .
job-nanny mfannot -g 1 $SEQ > ${BASE}_annot.out 2> ${BASE}_annot.err
# Extract basic statistics
echo "Sequence: $BASE" > stats.txt
grep -c "^>" ../$SEQ >> stats.txt
grep -c "gene" ${BASE}_annot.out >> stats.txt
grep -c "intron" ${BASE}_annot.out >> stats.txt
Results Interpretation
The MFannot output file contains:
# Annotation for sequence: mitogenome.fasta
# Length: 15894 bp
# Genetic code: 1 (Universal)
>Feature: gene
Position: 1..1500
Strand: +
Gene: cox1
Product: cytochrome c oxidase subunit I
>Feature: intron
Position: 1501..2100
Strand: +
Gene: cox1
Type: groupI
>Feature: gene
Position: 2101..3150
Strand: +
Gene: nad1
Product: NADH dehydrogenase subunit 1
Post-processing with Python
parse_mfannot.sh
#!/bin/bash
#SBATCH -J parse_mfannot
#SBATCH -N 1
#SBATCH -n 1
#SBATCH -t 01:00:00
#SBATCH --mem=2G
cat > parse_mfannot.py << 'EOF'
import re
import csv
from collections import defaultdict
def parse_mfannot_output(filename):
features = []
current_feature = {}
with open(filename, 'r') as f:
for line in f:
if line.startswith('>Feature:'):
if current_feature:
features.append(current_feature)
current_feature = {'type': line.split(':')[1].strip()}
elif line.startswith('Position:'):
current_feature['position'] = line.split(':')[1].strip()
elif line.startswith('Strand:'):
current_feature['strand'] = line.split(':')[1].strip()
elif line.startswith('Gene:'):
current_feature['gene'] = line.split(':')[1].strip()
elif line.startswith('Product:'):
current_feature['product'] = line.split(':')[1].strip()
elif line.startswith('Type:'):
current_feature['intron_type'] = line.split(':')[1].strip()
if current_feature:
features.append(current_feature)
return features
# Process all annotation files
import glob
import os
for annot_file in glob.glob("*_annot/*.out"):
sample = os.path.basename(annot_file).replace('_annot.out', '')
features = parse_mfannot_output(annot_file)
# Statistics per sample
gene_count = sum(1 for f in features if f.get('type') == 'gene')
intron_count = sum(1 for f in features if f.get('type') == 'intron')
with open(f'{sample}_summary.txt', 'w') as out:
out.write(f"Sample: {sample}\n")
out.write(f"Genes found: {gene_count}\n")
out.write(f"Introns found: {intron_count}\n")
out.write("\nDetails:\n")
for f in features:
out.write(f" {f.get('type')}: {f.get('gene', 'N/A')} "
f"[{f.get('position', 'N/A')}] "
f"({f.get('product', 'N/A')})\n")
EOF
python3 parse_mfannot.py
Results Visualization
visualize_mfannot.sh
#!/bin/bash
#SBATCH -J viz_mfannot
#SBATCH -N 1
#SBATCH -n 1
#SBATCH -t 01:00:00
#SBATCH --mem=2G
# Requires matplotlib
# Load Conda module
module load miniconda/25.x
# Create Conda environment
conda create -n matplotlib_env -y
source activate matplotlib_env
# Install matplotlib
conda install matplotlib -y
cat > plot_annotations.py << 'EOF'
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import glob
import re
def parse_coordinates(pos_str):
"""Extract coordinates from position (e.g., '1..1500')"""
match = re.match(r'(\d+)\.\.(\d+)', pos_str)
if match:
return int(match.group(1)), int(match.group(2))
return None, None
# Collect statistics per sample
samples = []
gene_counts = []
intron_counts = []
for summary in glob.glob("*_summary.txt"):
sample = summary.replace('_summary.txt', '')
with open(summary, 'r') as f:
content = f.read()
# Extract counts
genes = re.search(r'Genes found: (\d+)', content)
introns = re.search(r'Introns found: (\d+)', content)
if genes and introns:
samples.append(sample)
gene_counts.append(int(genes.group(1)))
intron_counts.append(int(introns.group(1)))
# Bar chart
if samples:
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))
x = range(len(samples))
ax1.bar(x, gene_counts, color='blue', alpha=0.7)
ax1.set_xlabel('Sample')
ax1.set_ylabel('Number of genes')
ax1.set_title('Genes annotated per sample')
ax1.set_xticks(x)
ax1.set_xticklabels(samples, rotation=45, ha='right')
ax2.bar(x, intron_counts, color='red', alpha=0.7)
ax2.set_xlabel('Sample')
ax2.set_ylabel('Number of introns')
ax2.set_title('Introns annotated per sample')
ax2.set_xticks(x)
ax2.set_xticklabels(samples, rotation=45, ha='right')
plt.tight_layout()
plt.savefig('mfannot_summary.png', dpi=150)
print("Plot saved as mfannot_summary.png")
else:
print("No data found for plotting")
EOF
python3 plot_annotations.py
References
Documentation: https://github.com/BFL-lab/Mfannot
Publication: https://academic.oup.com/nar/article/35/suppl_2/W620/2920130
See also
BUSCO - Completeness assessment
Trinity - Transcriptome assembly
Running Simulations - How to submit jobs