← Files Biological Sequence & Alignment ViewerARCHIVED FILE
src/msa/formats/pir.ts
2.4 KB · Sep 30, 2026 · 23:01 UTC
import { normalizeGapSymbol } from "../residue-alphabet";
import type { MsaFormatDraft, MsaParseWarning } from "../types";
export function looksLikePir(contents: string): boolean {
return /^[\t\n\r ]*>[A-Za-z0-9]{2};[^\r\n]+/u.test(contents);
}
export function parsePir(contents: string): MsaFormatDraft {
const rows: MsaFormatDraft["rows"] = [];
const warnings: Array<MsaParseWarning> = [];
const lines = contents.split(/\r?\n/);
let active: {
description?: string;
id: string;
sequenceParts: Array<string>;
sawDescription: boolean;
startLine: number;
} | null = null;
const flush = (terminated: boolean): void => {
if (active == null) {
return;
}
if (!terminated) {
warnings.push({
code: "pir-terminator-missing",
line: active.startLine,
message: `PIR record ${active.id} ended without a * terminator.`,
severity: "error",
});
}
rows.push({
alignedSequence: active.sequenceParts.join(""),
...(active.description == null
? {}
: { description: active.description }),
id: active.id,
label: active.id,
});
};
lines.forEach((line, index) => {
const trimmed = line.trim();
if (trimmed.startsWith(">")) {
flush(false);
const header = /^>[A-Za-z0-9]{2};(.+)$/.exec(trimmed);
const id = header?.[1]?.trim() || `sequence-${rows.length + 1}`;
if (header == null) {
warnings.push({
code: "pir-header-invalid",
line: index + 1,
message: "PIR headers must use the >type;identifier form.",
severity: "error",
});
}
active = {
id,
sawDescription: false,
sequenceParts: [],
startLine: index + 1,
};
return;
}
if (active == null || trimmed.length === 0) {
return;
}
if (!active.sawDescription) {
active.description = trimmed;
active.sawDescription = true;
return;
}
const terminatorIndex = trimmed.indexOf("*");
const sequencePart =
terminatorIndex >= 0 ? trimmed.slice(0, terminatorIndex) : trimmed;
active.sequenceParts.push(
Array.from(sequencePart.replaceAll(/\s+/g, ""))
.map((symbol) => normalizeGapSymbol(symbol))
.join(""),
);
if (terminatorIndex >= 0) {
flush(true);
active = null;
}
});
flush(false);
return { format: "pir", rows, warnings };
}
SHA-256: 4cc71ad476f650bd2612b1a8b801c5da7657e1f09dd1ee2f377f167e9f54f81e