SYNOPSIS

use Bioinf::Basic ':all';

my $seqs = fasta2hash('proteome.fa.gz');        # { defline => sequence }
my $one  = fasta2hash('proteome.fa', 'P12345'); # just that sequence
hash2fasta_file($seqs, 'copy.fa');

my $hits = get_best_alignment_hit('blast.json', 'bit_score');

# one clustalo run: plot_msa keeps the guide tree, and plot_phylo draws it
plot_msa(
	fasta       => 'orthologs.fa',     # or { name => sequence }
	filename    => 'msa.svg',          # .png, .pdf, ... too
	'tree.file' => 'orthologs.newick',
	title       => 'EF-3',
);
plot_phylo('tree.file' => 'orthologs.newick', 'output.file' => 'tree.svg', title => 'EF-3');

DESCRIPTION

FASTA I/O in XS, BLAST hit ranking, and multiple-sequence-alignment plots and LaTeX tables, taken from the maintainer's bioinf.pm.

Nothing is exported by default; ask for functions by name or with :all. Every function dies (via Carp::croak) on bad arguments, with a message that starts with the name of the function that raised it, as in fasta2hash: couldn't find "four" in x.fa. plot_msa, plot_phylo, msa_quality_table and clustal_view_residues take name => value pairs, not a hash ref.

Alien::Bioinf

Clustal Omega, BLAST+ and the Python that draws the plots come from Alien::Bioinf, which installs them module-locally and never uses PATH. It is recommended rather than required, because it can only be installed where NCBI builds BLAST+ (Linux and macOS on x86_64 and aarch64, and Windows on x86_64) and it needs the network. fasta2hash, hash2fasta_file and get_best_alignment_hit work without it; plot_msa, plot_phylo, msa_quality_table, and clustal_view_residues given an unaligned file, die saying that they need it. From this repository, install it first:

cpanm ./alien/Alien-Bioinf
cpanm .

That downloads nothing it can reuse: archives are cached (ALIEN_BIOINF_CACHE, default ~/.cache/alien-bioinf), a clustalo or BLAST+ already on the machine at the newest version is copied instead (ALIEN_BIOINF_CLUSTALO, ALIEN_BIOINF_BLAST, or PATH), and pip installs only what the base Python lacks. To check for and apply updates:

perl -MAlien::Bioinf -MData::Dumper -e 'print Dumper(Alien::Bioinf->check_updates)'
perl -MAlien::Bioinf -e 'print "$_\n" for Alien::Bioinf->update'

Provenance in the images

Every PNG, SVG, PDF, PS or EPS image these functions draw carries its provenance as Creator metadata: the calling script (as the working directory plus the script's name, like Matplotlib::Simple), the function, this file and its version, the computer it ran on (hostname, operating system and perl version), and what drew it: msa_plot.py and the matplotlib version, and for a tree the Biopython version too. For example:

/home/me/work/run.pl called using "plot_msa" in /.../Bioinf/Basic.pm
version 0.01 on host myhost (linux, perl 5.44.0), drawn by /.../msa_plot.py
with matplotlib 3.10.0

An SVG holds it in <dc:creator>; exiftool or identify -verbose shows it in a PNG or PDF.

FUNCTIONS

fasta2hash($file, $key)

Reads a FASTA file (gzip-compressed if its name ends in .gz). Returns a hash ref of defline (without the >) => sequence, or, with $key, just the sequence of that defline, reading no further than the record after it. A defline that appears twice is warned about and its sequences concatenated; with $key, only a repeat of $key is looked for. Line endings may be \n or \r\n. A .gz that gzip cannot read to its end, such as a truncated one, dies rather than returning the part that was read.

my $h = fasta2hash('DEG20010421.fa');

hash2fasta_file($hash, $filename, $order, $width)

Writes $hash as FASTA: the keys in @$order (default: sorted), sequences wrapped at $width columns (default 80; 0 for one line each). Returns $filename.

get_best_alignment_hit($json_file, $sort_criterion)

For a BLAST -outfmt 15 JSON report, a hash ref of query title => array ref of that query's hits, best first. Each hit is its best hsp plus accession, hit_len, id and title. $sort_criterion is an hsp field (default evalue): align_len, bit_score, evalue, gaps, identity, positive or score. Ties are broken on the bit score, then on BLAST's order. A report with two queries of one title dies, since only one of them could be returned.

plot_msa(%args)

Aligns sequences with Clustal Omega and draws the alignment. Returns a hash ref of the files made: filename, msa.file, and tree.file if it was given. Once the image is written it prints wrote and its file name to STDOUT, the name in black on yellow when STDOUT is a terminal.

plot_msa(
	fasta      => 't/data/DEG20010421.fa',
	filename   => 'DEG20010421.msa.svg',
);

With fewer than two sequences it warns and returns an empty hash ref.

plot_phylo(%args)

Draws a guide tree, with Biopython's Bio.Phylo, from a FASTA (aligned with Clustal Omega first) or from a newick file that plot_msa kept. Returns a hash ref of the files made or used: output.file, and tree.file and msa.file as below.

plot_phylo(fasta => 't/data/DEG20010421.fa');   # writes phylo.svg
plot_phylo(
	'tree.file'   => 'DEG20010421.newick',
	'output.file' => 'DEG20010421.tree.png',
);

With fasta of fewer than two sequences it warns and returns an empty hash ref.

Besides the Creator every image carries, a tree records where it came from in the image's own metadata, so the file can be traced and checked without the script that made it. An SVG holds all of this as Dublin Core in its <metadata>, and a PNG as text chunks:

A PDF keeps the Title, the Description (as its Subject) and the Keywords; PS and EPS keep only the Creator, and other formats nothing.

msa_quality_table(%args)

Draws an all-against-all BLAST score table with matplotlib, and returns filename. The simplest call is

msa_quality_table(
	fasta      => 't/data/DEG20010421.fa',  # or { name => sequence }, aligned or not
	filename   => 'DEG20010421.scores.png',
);

msa.file is accepted and ignored, for old callers.

clustal_view_residues(%args)

Writes an alignment as LaTeX tables with chosen residues coloured, and returns output.tex.file, printing wrote and that file name to STDOUT, the name in black on cyan when STDOUT is a terminal. Protein names are written so that LaTeX prints them as they are, _, ^, { and the like included.

Thanks

A lot of this work (not all!) used Claude AI, which was paid for by the University of Idaho's IMCI