Repository navigation
Releases
v1.11.1
v1.11.0
FASTag v1.11.0: faster mzML reading, mimalloc on Windows, MGF converter for timsTOF mzML
This release reads mzML faster on every platform, uses mimalloc as the heap of the Windows build, and lets tools/mzml_to_mgf.py convert diaTracer mzML and ddaPASEF runs with empty MS2. Output does not change: on the public gate every case is byte-identical to 1.10.0; only the software_version that -out_spectra writes reads 1.11.0. In the paired benchmarks below (1,042 runs on Linux, 24 on Windows), every run gave the same tags as 1.10.0.
Faster mzML reading
- Direct peak decoding. MS2 peaks are decoded by a small scanner over the spectrum's
<binaryDataArrayList>(strict base64, zlib through one reused stream, reused buffers) instead of through a libxml2 document. It handles exactly one m/z and one intensity array, 32- or 64-bit float, uncompressed or zlib. Anything else (numpress, zstd, integer or extra arrays, unknown or unit-carrying terms, userParams, malformed base64, broken zlib, a length other thandefaultArrayLength) goes through OpenMS as before, with its messages and exceptions.- The whole
<spectrum>element is checked for well-formedness, so malformed XML (unclosed or mismatched tags, attributes run together or repeated, undefined entities, invalid UTF-8) is handed to OpenMS and fails as in 1.10.0 instead of being tagged. The check reads each tag and each text run once (plain ASCII 16 bytes per step with SSE2) and costs about 2.5–3 µs per MS2 spectrum. Differential fuzzing (about 23 M mutated spectra against the first, slower version of the check, and about 12 M against OpenMS's libxml2 parser) found no input on which the decoder accepts what OpenMS rejects or reads a different native ID or different peaks. defaultArrayLengthis not trusted for allocation: a huge or wrong value can no longer make the reader allocate gigabytes; such spectra go through OpenMS.- Peaks are bit-identical to OpenMS on all 372,032 spectra of PXD063151
Proteome_EIF5A.mzMLand on the 116,713 MS2 of the five public gate mzMLs, all of which are decoded directly.FASTAG_OPENMS_DECODER=1forces the OpenMS path (it reproduces 1.10.0's tags in every benchmark cell).
- The whole
- Spectrum reads. Each reader thread reads a spectrum with one positioned call (
pread;ReadFilewith an offset on Windows) into a reused, page-aligned buffer. A failed read now says why (out of memory, end of file, or the system error). - Offset scan of unindexed mzML. Each 4 MB piece is read with one positioned call into a page-aligned per-thread buffer. On Windows the old stream split each piece into 4 KB reads that serialised on the file's cache lock above 4 threads.
Measured on Linux (ibminode05, AMD EPYC 7763, 1-64 threads, default and matched profiles, 3 paired reps against 1.10.0):
| change | PXD063151 (3.2 GB, uncompressed, unindexed) | gate files (zlib) |
|---|---|---|
| direct decoding | read time −80 to −83 %; wall −14 to −17 % (default), −21 to −44 % (matched) | read −56 to −67 %; wall −7 to −37 % |
| aligned scan buffers | index scan −51 % at 1 thread (1.79 → 0.88 s), −37 % at 4, −19 to −24 % at 12-64 | scan −7 to −51 % |
| one positioned read | read −5 to −8 %; wall −1 to −2 % | read −7 to +2 % |
| all together, before the well-formedness check | wall −16 to −18 % (default), −21 to −46 % (matched); CPU −17 to −19 % / −44 to −45 % | wall −7 to −16 % (default), −12 to −39 % (matched) |
| well-formedness check and other review fixes (release build vs the read path before them) | read +13 to +20 %; wall 0 to +3 % (one cell −6 %) | read +3 to +9 %; wall −1 to +1 % |
| 1.11.0 as released vs 1.10.0 | read −79 to −82 %; wall −16 to −17 % (default), −25 to −45 % (matched); CPU −17 to −18 % / −42 to −44 % | read −54 to −66 %; wall −8 to −15 % (default), −16 to −38 % (matched) |
The last row chains two paired series on the same node (release build vs the read path before the review fixes, 162 runs at 1/12/64 threads; that read path vs 1.10.0, 520 runs), as 1.10.0 was not rerun beside the final build. Peak memory is unchanged (±1 %) except one cell: PXD003531, matched, 64 threads, 211 → 234 MB.
mimalloc on Windows
-
The Windows build links mimalloc 2.2.4 and redirects the C runtime heap of the whole process (OpenMS and libxml2 included) to it.
mimalloc.dllandmimalloc-redirect.dllship next toFASTag.exein the zip and the desktop app; mimalloc's MIT notice is inTHIRD-PARTY-NOTICES.txt. Linux and macOS builds do not change. -
Reason: the Windows process heap slows down when several cores allocate at once, and the mzML read allocates many small blocks per spectrum. On a GitHub Windows runner (2 cores / 4 threads, 512 MiB prefix of PXD063151, matched profile, mimalloc vs the plain heap of the same build, before direct decoding):
threads read µs/spectrum wall 1 89.5 vs 118.1 (−24 %) 15.7 vs 17.9 s (−12 %) 2 93.0 vs 137.6 (−32 %) 8.3 vs 10.1 s (−18 %) 4 147.4 vs 224.5 (−34 %) 6.2 vs 7.7 s (−20 %) Tags were identical in all runs.
-
With direct decoding most of those allocations are gone, and so is most of mimalloc's read gain. The same check on the 1.11.0 release candidate (runner with Xeon Platinum 8370C, 2 cores / 4 threads): read 35.9 vs 36.7 µs/spectrum at 1 thread, 38.9 vs 40.1 at 2, 64.2 vs 65.5 at 4 (−2 to −3 %); tagging −4 to −5 %; wall 11.28 vs 11.69 s, 6.00 vs 6.31 s, 4.62 vs 4.82 s (−3 to −5 %). Tags identical in all 18 runs.
Measured on a Windows workstation (Ryzen 9 7900X, 12 cores / 24 threads, Windows 11; full PXD063151, 372,032 MS2; release candidate 4635430, the installer's CLI bundle; mimalloc off = the same binary with MIMALLOC_DISABLE_REDIRECT=1; all 24 tag digests equal the Linux reference):
| matched profile | 1 thread | 4 threads | 12 threads |
|---|---|---|---|
| wall 1.10.0 → 1.11.0, mimalloc off | 53.97 → 36.23 s (−33 %) | 15.14 → 9.76 s (−35 %) | 8.34 → 4.51 s (−46 %) |
| read µs/spectrum 1.10.0 → 1.11.0, mimalloc off | 61.6 → 18.4 | 69.9 → 19.9 | 121.0 → 31.9 |
| wall, mimalloc on vs off (1.11.0) | −2 % | −3 % | −8 % |
- 1.11.0 without mimalloc is faster than 1.10.0 with it at every point (matched: 36.2 vs 48.4 s, 9.8 vs 13.2 s, 4.51 vs 6.61 s).
- mimalloc now saves 2–8 % wall in the matched profile (every paired rep below 1) and 45 MB peak working set at 12 threads, mostly in tagging; its read gain is 0–5 %.
- Default-profile numbers are indicative only, because another user's job loaded the machine during most of those runs: wall 1.10.0 → 1.11.0 −13 % at 1 thread and −16 % at 12 threads (mimalloc off); mimalloc on vs off +3 % at 1 thread (one clean pair +1 %) and −3 % at 12 threads.
- The candidate measured here still had the first, slower version of the well-formedness check (about 11–13 µs per MS2 on Linux, now about 3 µs), so the released build reads slightly faster than shown.
MIMALLOC_DISABLE_REDIRECT=1switches back to the Windows heap;FASTAG_TIMING=1reports which heap is in use (FASTAG_ALLOC ... redirected=).
MGF converter (tools/mzml_to_mgf.py)
- diaTracer mzML (precursor m/z only in the isolation window target, no selected ion m/z) now converts. Precursor m/z is taken as FASTag's mzML reader takes it: the selected ion m/z, else the isolation window target if above 0. The charge is read from the selected ion even when it has no m/z.
- Precursors are counted as FASTag counts them. A
<precursor>counts only with a selected ion or an isolation target above 0; the first one that counts gives PEPMASS and CHARGE. An MS2 with none is left out, as FASTag ignores it in the mzML, so MS2 and uncharged counts agree between the two inputs. - MS2 without peaks (no binary arrays at all, as in some ddaPASEF conversions) no longer stop the converter. They become blocks without peak lines, which FASTag skips as it skips empty mzML spectra;
--skip-emptyleaves them out for tools that reject empty blocks (tags stay the same). - Negative charges are written as
CHARGE=2-, which FASTag reads (the former-2+made it refuse the file). FASTag's MGF reader takes this as charge 2 in negative mode, while its mzML reader counts a negative charge as no charge, so negative-mode spectra can tag differently from the two inputs. - No partial output: the MGF is written to a temporary file and renamed only when conversion succeeds; an existing destination is left unchanged on failure.
- TITLE holds the mzML native ID and is the stable key back to the mzML;
index=<k>counts the blocks written, so left-out MS2 shift it. Each left-out case is counted on stderr; m/z and intensity arrays of different length are an error. The mzML is read as a stream without its index, so a stale index does not matter. - Tags from the MGF equal those from the mzML (spectrum-ID column removed) on the fixtures, on PXD047793 run 001 (diaTracer, 2,303,274 MS2, 73,354,262 tag rows) and on PXD054073 (ddaPASEF via mzpeak-convert 0.18.0, 357,805 blocks, 7,309,985 tag rows).
Tests and CI
- New ctest
mzml_to_mgf_testwith two synthetic timsTOF-shaped fixtures (diatracer_like.mzML,ddapasef_empty.mzML, built from the BSD-3-Clause Ecoli example peaks bytest/fixtures/make_converter_fixtures.py). It checks counts, PEPMASS, negative charges and that a failed conversion leaves no file. It needs a Python with pyteomics and numpy (FASTAG_PYTHON) and skips otherwise. indexed_mzml_testcompares the direct decoder with OpenMS spectrum by spectrum on the fixtures, their raw/zlib x 32/64-bit re-encodings, the declined forms, 32 malformed spectra (an error on both paths; invalid UTF-8 and references, control characters,<and duplicates in attributes, unquoted or missing values, unterminated tags, many after long plain runs so the SSE2 path is exercised), 4 unusual but well-formed ones that must still be decoded directly, and an oversized `de...
v1.10.0
FASTag v1.10.0: MGF input, species ranking fix, new desktop app with built-in Help
This release reads MGF, fixes how spectra are counted in the species report, makes the tags identical on every platform, and brings a redesigned desktop app with built-in Help. The default species report changes (see below), and so does the digest report on input without instrument metadata whose intensities are ion counts. Tags and E-values do not change: on the public gate every tags.tsv, recon, delta and mzPeak output is byte-identical to 1.9.0 on Linux and Windows.
Changes to default output
- macOS: identical tags on every platform. FASTag is now built without fused multiply-add contraction (
-ffp-contract=off) on every compiler that does it. Apple clang had fused the precursor-mass formula into one FMA, 1 ulp off the Linux and Windows value; on PXD063151 scan=1201892 that flipped a complement-peak test exactly at the 0.02 Da tolerance and changed that spectrum's E-values 5-9x. macOS output now equals Linux and Windows; Linux x86-64 and Windows output does not change. - Species report (
-species): a spectrum now counts for the taxa of its best tag. Up to 1.9.0 a spectrum counted for every taxon that any of its reported tags supported. Most of the up to-max_tagstags of a spectrum are wrong readings, and each one added the taxa its 7-mer hits by chance. So a taxon's count grew with the number of tags reported per spectrum, large and widely shared proteomes collected most of those chance hits, and changes that only reorder lower-ranked tags moved the ranking. Now a spectrum counts for the taxa of its lowest-E-value tag that maps into the index (tags tied at that E-value all count). Observed counts drop and the order below the top taxa can change. On the public gate run (PXD003531, human), Homo stays first (14,732 → 12,006 spectra) and Macaca second; Equus moves from 7th to 4th. The new option-species_evidence best|allchooses the rule;allrestores the 1.9.0 report, byte for byte on the gate run. - Digest report (
-digest_out): new no-call ruleion_counts(checked afterms2_first_peak, beforefew_tags). When the input names no instrument and no vendor native-ID format, and at least half of the MS2 peak intensities above 0 are whole numbers (ion counts, as timsTOF data have), no protease is called. Native-ID formats that name no vendor (MS:1000774, MS:1000775, MS:1000776, MS:1000777, MS:1000824) count as no format, so mzML written from an MGF by OpenMS FileConverter or by FASTag-out_spectrais withheld as well. A newmetarow,ms2_whole_intensity_share, reports the share for every input. With instrument or native-ID metadata the rule readsnoand thetimstofrule decides, as before. On the 1.9.0 differential set (199 runs) the rule fires on none, and every other report row is unchanged. It also withholds the call for other TOF instruments that write ion counts (SCIEX, Agilent, Waters) when their metadata is missing, and for Orbitrap MGFs whose writer rounds intensities to integers. -out_spectramzML records the newspecies_evidenceparameter in its data-processing metadata. The spectra are unchanged.
New: MGF input
-in run.mgf(or.MGF) works with every option: all reports,-out_spectra(mzML or mzPeak),-recon_id_out,-usi_collection,-subsample_*and-progress. One parallel scan finds and checks every block before any output is opened. After that each thread reads its own blocks, so memory does not grow with the file, and every thread count gives the same output.- Spectra are named
index=<k>, the 0-based block position (PSI-MS MS:1000774), in every TSV and in-recon_id_out. TITLE and SCANS are kept as metadata. TITLE is never used as the ID, because it is free text and need not be unique. - Peaks and precursors are bit-identical to what OpenMS's
MascotGenericFilereads. This was checked block by block on the test fixture and on 164,059 blocks of three public MGFs. - FASTag gives the same tags from an MGF written by the new
tools/mzml_to_mgf.pyas from its source mzML. The tags, recon, delta, glyco and species TSVs are byte-identical once the spectrum-ID column is removed. This holds on the fixture and on four public runs (PXD003531, PXD014764, PXD040407, PXD004541). An AlphaTims MGF (PXD054073) and its FileConverter mzML give the sametags.tsv, ID column included. - Precursors with no charge, or with several (
CHARGE=2+ and 3+), are tagged as 2+ and counted in the no-charge warning. Negative charges (3-,-3,-3-) are tagged at their magnitude. OpenMS's reader refuses both forms. -usi_collectionnames<file>.mgfas the run, withscan:<n>from SCANS, or elseindex:<k>.- A truncated or structurally broken MGF fails before any output is written. A malformed block fails the run when it is reached. Both messages name the block, its byte offset and its TITLE.
- Compressed input (
.gz,.bz2,.zip, also.mzML.gz) is refused with a message that names the compression. - Warnings cover lost
BEGIN IONSlines, blocks without a usable PEPMASS, non-finite RT, TITLE or SCANS values that had to be cleaned, a file-levelCHARGE=(not applied, as in OpenMS) and a BOM.
Command line
- FASTA-index refusals (a seed length that can never beat the database's chance floor, an index over the size cap) now exit with rc 6 ("Invalid parameter"), like other parameter refusals, instead of rc 8.
- An unknown
-species_rank(for examplesuperkingdom; NCBI calls the top rankdomain) is refused with rc 6 in about 0.1 s, before tagging. Before, the run went on and wrote an empty species report. - A NaN or infinite
-fragment_toleranceis refused. TOPPBase's range check let NaN through. - If tagging, the report writer or a reader fails, the partial
-out,-recon_outand-glyco_outare removed, for every input format. Before, they were removed only when a run was refused for ion mobility. Only regular files are removed, so-out /dev/nullis safe. - The "ignored option" warning now also appears for
-glyco_*,-taxdb/-taxonomy_*and-species_*options when their switch is off, and compares against the registered defaults. -proformaleaves terminal fixed modifications out of the sequence prefix.-streamkeeps spectrum IDs of any length (they were cut at a fixed buffer size).-isobaric_toleranceand-min_filter_lengthreject negative values.- A new exit-code table in the README.
- Removed: the optional OpenMS fast-reader build probe (no released OpenMS has the patch it looked for) and the unused
tagfeatureshelper. - Corrected help texts:
-gap_penalty(under-max_tagsit decides which tags fill the capped slots),-isobaric_toleranceand-orientation(both also apply to-recon_fastareconciliation).
Desktop app
- Built-in Help (F1,
?or the Help button). In plain language it explains what tags and gapped tags are, how tags are scored, the Digest tab (terminal chemistry: protease call, labels, mass gaps, no-calls), the Species tab (how detection works, when to trust a call), input and output files, every setting, batch runs and common errors, with a glossary. "?" links next to every settings group, tab and panel open the matching section. Tests check that every link target exists and that Help agrees with the README and the design notes. - Plain labels for parameters, result columns and filters, and clearer run status and error messages.
- New design. IBM Plex is bundled with the app, so no font is fetched at run time. Colours pass contrast checks in light and dark mode, and below 720 px the columns stack. A sticky run bar shows a locked run summary with progress and elapsed time. A failure banner quotes FASTag's reason and offers Show full log and Copy command. Batches list each job's status, with "Run N remaining files" and "Retry failed". The Tags, Species and Digest panes are redesigned. Tags has labelled filters and a Database hit filter (All / In database / Entrapment / Not in database), and Export shown rows… writes the filtered rows in the shown columns. Species has call and evidence cards, and its Adjusted column appears only after
-species_deconvolve. Digest has protease figures, logos with a legend, a mass-gap histogram and a labels summary. - Run checks. Run and Run batch are disabled while a parameter is invalid or two conflict, and the reasons are listed next to Run. The species
tag_length/index precondition,-entrapment_fastawith-speciesor-tag_lengths, and-recon_outwithout a database are refused up front, as the CLI refuses them.-max_peaksabove 1,024 and non-integer values in integer fields are caught in the form. - Fixes. Outputs given as bare names are read beside the input, where the CLI writes them. A table that a failed or cancelled run may have truncated is held back as "Incomplete". Reports from different runs of inputs with the same name are no longer mixed. A file name starting with
-reaches the CLI. The backend readers refuse files that are not regular files. - Accessibility. A status line announces when a run starts, finishes, stops or fails. Focus returns to a sensible control after Reset, presets, Dismiss, Remove and Clear. The log, batch list and report rows take keyboard focus, and the tags table is a proper read-only table. Forced-colours mode keeps pressed buttons, progress and bars visible.
- MGF input: the file dialogs offer
.mgf. The new-species_evidenceoption is under Species detection.
Known issues
- MGF carries no ion mobility, instrument, scan-window or activation metadata. The digest report lists these as absent, and its
ion_countsrule judges timsTOF data from the intensities. timsTOF MGFs with scaled or averaged intensities are not caught by it. -subsample_*draws over MGF blocks, so on an MGF of a run's MS2 it picks different spectra than on the run's mzML, which counts MS1 too.
...
FASTag v1.9.0
FASTag v1.9.0: fixes from a full code review
An adversarial review of v1.8.0 confirmed 60 findings. This release fixes all critical and major ones. Default tags and E-values change, so results from 1.8.0 and 1.9.0 are not interchangeable.
Critical fixes
-specieshung after tagging on runs with more than about 20,000 evidence spectra.- Reconciliation dropped every reversed (b-ion) placement: its flanks were one water (18.011 Da) off.
-recon_out,-recon_id_out,-delta_outand-massgap_outnow include them (on a public test case, reversed placements went from 35 to 2,766). -out_spectraequal to-indestroyed the input file. Outputs that alias the input or each other are now refused.
Changed tags and scores
- A gap edge is only built where the intermediate peak is missing. Before, redundant re-spellings filled the
-max_tagsbudget; gapped rows drop by 16–21 % on default runs. - The m/z-fidelity score uses each peak's own ppm tolerance. Low-m/z tags kept too little evidence before.
- Deisotoping no longer depends on the intensity scale, and 1+/2+ copies of one fragment are merged, so tags are no longer emitted twice.
- In reconciliation the precursor-derived flank is judged at the peptide mass, and variable modifications inside the tag count for site localization.
Stricter input and options
- An unreadable MS2 spectrum fails the run instead of being skipped silently. A scan time without a unit is read as seconds, as in OpenMS.
- Unknown modification names, NaN or infinite precursors, duplicate
-digest_modelsrows and an entrapment database inside the target's key space are refused. - A species report that cannot be written fails the run.
-max_peaksis capped at 1,024 and-recon_missed_cleavagesat 10.
Reports
- The delta histogram counts a valley bin in one peak only.
- Species
adjustedcounts no longer double-count shared spectra.
Desktop app
- One non-UTF-8 output line no longer stops a run.
- No console window on Windows. FASTag.exe uses UTF-8 paths.
- Browse offers each parameter's own file types; clearing the fixed modifications reaches the CLI; a new input no longer overwrites the previous sample's reports.
Packaging
- Every bundle ships
LICENSEandTHIRD-PARTY-NOTICES.txt. - CI actions are pinned to commit SHAs.
Documentation
The README corrects nine claims, among them: -gap_penalty can change which tags are reported under -max_tags; the E-value is a ranking score, not a calibrated count; the memory bound and the scope of mzML/mzPeak identity are stated precisely.
Known issues
- On some timsTOF conversions, precursors with a selected-ion m/z of 0 get no tags from mzML but do get tags from mzPeak, so tags from the two containers can differ there.
- The mzPeak regressions listed for 1.8.0 remain.
FASTag v1.8.0
FASTag v1.8.0: digest, label and mass-gap reports; built on OpenMS develop
New: three opt-in reports
They describe how a run was digested and labelled, from the tags FASTag already finds. Each is a long-form TSV (section key value n description) with one factual sentence per row.
-digest_out: terminal residue counts (P4…P1 | P1′…P4′), a log-likelihood per protease model, the call, the runner-up of another enzyme class and the margin per tag.- When no call is possible, the file says
no_calland why:low_resolution,timstof,ms2_scan_window,ms2_first_peak,few_tags,nonfinite_scoreortie.
- When no call is possible, the file says
-label_out: N-terminal TMT, TMTpro and iTRAQ4 counts against a +0.5 Da background, and the heavy Lys8/Arg10 shares.-massgap_out(with-recon_out): the precursor-vs-peptide mass-gap distribution, Cys alkylation counts, and explanations of the gap peaks as combinations of up to three modifications from OpenMS's ModificationsDB, plus a SILAC call.-digest_models: your own model table (model class end residue freq) in place of the shipped cleavage-rule models.- The background is the run's FASTA composition when one is given, else a human UniProt background.
- Every threshold is an advanced option.
Without these options all existing outputs are unchanged. The counting reproduces prose-auto 0.1.3 bit for bit on 199 public runs; see doc/DESIGN-digest.md.
New in the desktop app: Digest tab
- The call or the no-call reason, with the runner-up, the margin and the report sentences.
- A sequence logo of the observed terminal residues against the background, next to the logos of the called model and the runner-up.
- The label and heavy-SILAC rows.
The tab also brings smaller GUI fixes: keyboard navigation, the colour legend, error messages, and options that are not sent when inactive.
Built on OpenMS develop
- FASTag is now built against OpenMS develop (3.7.0-dev, commit 70cebcd144, C++23).
- mzPeak is read and written through OpenMS's
MzPeakFile. FASTag's own mzPeak reader and the mzpeak-openms dependency are gone. -out_spectra *.mzpeakrefuses inputs with ion mobility per peak, before tagging starts; write.mzMLinstead.-mzpeak_read_memoryis accepted but has no effect.
Changed output
- Isobaric gap pairs in the tags: pairs of equal mass (e.g. EN/DQ, TV/LS) are now ordered by spelling.
- Before, their order depended on memory layout and could differ between runs on Windows.
- On wide-tolerance runs this changes which spellings the 8-spelling budget keeps: 344 of 155,939 rows on a 0.5 Da test case, in the tag column only.
-out_spectrawrites the same spectra and peaks. The metadata follows OpenMS develop:- mzML keeps the filter string, the injection time and every instrument configuration;
- mzPeak copies the input's RT, selected-ion and isolation-window values exactly.
Platforms
- Linux x64, Linux arm64, macOS on Apple silicon (macOS 13.4 or later) and Windows x64.
- Intel Macs are no longer supported. 1.6.1 is the last release for them.
- The Windows installer is not code-signed yet, so SmartScreen warns on first run.
Known regressions
Measured on PXD003531.
- mzPeak input is about 1.1× slower at 16–64 threads, and 1.4× slower on a chunked archive at 64 threads.
- At 1 thread mzPeak reading is as fast as before or faster.
- mzML reading is faster than in 1.6.1.
-subsample_*on mzPeak input reads the whole archive.-out_spectrafrom mzPeak reads the archive twice. Written to.mzpeak, it holds the spectra in memory (+330 MB here).- A
.mzpeakwritten by FASTag has no activation, chromatograms, instrument configuration, processing history or run references.
These will be fixed once OpenMS's mzPeak support is complete.
FASTag v1.6.1
FASTag v1.6.1: one row per tag across -tag_lengths
-tag_lengths now reports a tag only once.
- Two seed lengths can find the same tag, especially with
-extension. v1.6.0 then reported it once per length. - Now each tag, identified by spectrum, sequence, charge, flanking masses and gapped flag, is kept only from the length that gives it the lowest E-value. Ties go to the shorter length, and that length's rows are kept unchanged.
- This happens before anything else uses the tags, so
-recon_out,-recon_id_out,-delta_out,-speciesand-streamall see the deduplicated set.-recon_id_outno longer writes identical hits. - Masses are compared at full precision. Two different readings that only print alike are both kept.
-max_tagsstill caps each length before deduplication, so a spectrum can end up with fewer rows than the caps allow.
-tag_lengths 3 4 5 -extension 2 |
v1.6.0 rows | v1.6.1 rows |
|---|---|---|
| iPRG (49,514 MS2 spectra) | 2,056,180 | 1,448,349 |
| Tonsil (22,408 MS2 spectra) | 23,895 | 20,608 |
Without -extension, these runs had nothing to drop. Single-length runs and every run without -tag_lengths are byte-identical to v1.6.0.
FASTag v1.6.0
FASTag v1.6.0: multi-length tags, mass-shift localization, identification formats
Every new behaviour is opt-in. With none of the new options set, the output is byte-identical to v1.5.0.
New options
-tag_lengths 3 4 5: several seed lengths in one pass.
- The output equals the single-length runs joined per spectrum.
- Each length keeps its own E-values and its own
-max_tagscap. - The input is read once. On iPRG (49,514 MS2 spectra) this takes 1.4 s instead of 2.4 s for three separate runs, and with
-fastaand-recon_out21.6 s instead of 48.2 s.
-recon_localize: where in the peptide a reconciled mass shift sits.
-
It adds three columns to
-recon_out:loc_site, the residue and its protein position;loc_score, the number of matching b/y ions;loc_ties, the number of positions tied at the best score.
-
A fixed TMT or iTRAQ label is taken into account.
-
When a single site is called (
loc_ties= 1), it is the expected residue 95–99% of the time on DDA data and 85–94% on DIA pseudo-spectra. A tie reports the first position, so treatloc_ties> 1 as unlocalized. -
Rates on real data, where chance is the share of candidate residues that are the expected one:
Shift Data Hit rate Chance +57.021 to C Orbitrap Astral 0.96 0.24 +57.021 to C CPTAC 0.86 0.23 iTRAQ label + oxidation to M CPTAC 0.86 0.21
-recon_id_out <file>: reconciliation placements as identifications.
- The extension picks the format:
.idXML,.mzidor.mzTab. All three are written with OpenMS's own writers. - Each hit is the unmodified database window. The mass gap travels as metadata and is never turned into a localized modification.
- Hits are scored by the tag's E-value and marked
FDR_controlled = false. - The mzid output passes OpenMS's mzIdentML schema check.
- A run without placements writes an empty
.mzid.
-usi_collection <PXD…>: a USI per tag row, in the form mzspec:<collection>:<run>:scan:<n>. It uses the index or nativeId form when the spectrum has no scan number.
Faster, smaller proteome index for -recon_out
The suffix array is now built in parallel, and the index needs 6.5 bytes per residue instead of about 14. Placements are byte-identical.
| Index build, 64 threads | v1.5.0 | v1.6.0 |
|---|---|---|
| Human reference proteome, 11.4 M residues | 2.8 s / 231 MB | 0.13 s / 165 MB |
| UniProt bacterial proteomes, 3.38 G residues | 37 min / 55 GB | 55 s / 27 GB |
Windows
FASTag.exe now carries product name and version metadata. The installer is still unsigned.
FASTag v1.5.0
FASTag v1.5.0: mzPeak performance release
Reading mzPeak is 3.9× faster at 128 threads and uses a quarter of the memory. Tag output is byte-identical to v1.4.3.
CPTAC breast cancer, merged fractions — 931,325 MS2 spectra, 3.6 GB archive, 37,599,162 tags in every run — on two AMD EPYC 9654, at default parameters:
| v1.4.3 | v1.5.0 | |
|---|---|---|
| 16 threads | 71.1 s / 7.9 GB | 26.6 s / 1.8 GB |
| 128 threads | 18.8 s / 11.4 GB | 4.8 s / 2.8 GB |
Reading mzPeak is now faster than reading mzML at every thread count, and the run scales from 406 s on one thread to 4.0 s on 256. The README has the full ladder and the same measurement for five more public data sets.
What changed
- Tagging kernel:
- peak lookups use a prebuilt grid and residue-difference table instead of binary searches;
- the averagine deisotoper is a local port, bit-identical to OpenMS 3.5.0;
- the Fisher score is closed-form;
- numbers are formatted with
std::to_chars; - per-thread scratch memory is reused.
- Parallel loop:
- one parallel region with a resident writer and chunked output;
- threads decode row groups ahead instead of waiting on each other.
- mzPeak reading (mzpeak-openms a4345f7):
- decode memory is recycled across threads instead of stranding in per-thread allocator arenas;
- the per-point
spectrum_indexcolumn is held as verified runs rather than decoded; - spectrum metadata is read into a compact record;
- array access avoids a process-wide lock in Arrow;
- archive open is 3× faster.
- Library update: the mzPeak library also brings trunk's work. Written archives now carry SHA-512 member checksums, and
scan_start_timeis stored as double, as the specification now prefers. Promoted activation columns are read. - mzML with a missing or stale index: such a file used to be loaded whole into memory, serially. A stale index is common: any tool that patches an mzML in place without rewriting the index leaves it stale. FASTag now finds the spectra with a parallel scan and reads the file as usual. On a 6 GB file the scan takes 0.26 s, and the run takes 2.9 s and 0.5 GB instead of 52.9 s and 7.2 GB. FASTag prints a warning when it rebuilt an index.
- An unreadable file is now an error, not a crash. An archive FASTag could open but not decode reached
std::terminate: the process aborted with no exit code and the message buried in a runtime banner, which from the desktop app looked like the tool vanishing. Such a run now exits with an error code and prints the reason. The same applies to a failure inside a worker thread. - Stricter stale-index check: an index shifted by only a few bytes used to pass the check, and about half the spectra then decoded empty, silently. The check now requires offsets to point exactly at a spectrum tag, and samples 33 of them instead of 3.
- Packaging: the launchers on every platform and the desktop app default
OPENBLAS_NUM_THREADS=1. libOpenMS loads OpenBLAS, which otherwise starts a spinning thread per core (~2 s of CPU on a 128-thread machine, even for--help). A value you set yourself still wins.
Documentation
The README now carries FASTag's own scaling and runtime/memory figures for selected public data sets instead of comparisons with other tools, and the documents that only tracked the development process (backlogs, plans, readiness and review notes) are gone. What remains — the algorithm, install, options, formats, outputs, validation — was checked against the code.
Also in this release
- The ported deisotoper is built without fused multiply-add, so it reproduces OpenMS's arithmetic on arm64 exactly as it already did on x86-64.
- Roughly 1,400 lines of code removed, with output unchanged.
Compatibility
- macOS 13.3 or later is now required (was 12). The new number formatting needs libc++'s floating-point
std::to_chars, which macOS ships from 13.3. - Tag output is unchanged. Files written with
-out_spectradiffer from v1.4.3 only in the software version, in mzPeak's added checksums and in the double-precision scan start time.
v1.4.3
Automated binary upload; release notes pending.
v1.4.2
Automated binary upload; release notes pending.