.. _mfannot: ======= MFannot ======= .. contents:: In this section: :local: :depth: 2 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 ================== .. code-block:: bash # 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 ============== .. code-block:: bash :caption: 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 ======================================= .. code-block:: bash :caption: 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 ================================= .. code-block:: bash :caption: 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 ================================ .. code-block:: bash :caption: 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: .. code-block:: text # 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 =========================== .. code-block:: bash :caption: 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 ===================== .. code-block:: bash :caption: 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 - Database: http://megasun.bch.umontreal.ca/People/lang/FMGP/ .. seealso:: - :ref:`busco` - Completeness assessment - :ref:`trinity` - Transcriptome assembly - :ref:`running_simulations` - How to submit jobs