Repository navigation
Getting started
This page takes you from an empty project to a program that reads an mzML file. It assumes you know Zig; it does not assume you know mzML (that is mzML in brief).
- Zig 0.16.0.
- A little-endian target. zmz is tested on x86_64 and aarch64 Linux and on aarch64 macOS; big-endian targets are refused at build time.
Nothing else: no C library, no system packages. zlib support comes from zipir, a Zig package that zig fetch pins by hash.
From your project's directory:
zig fetch --save git+https://github.com/eneskemalergin/zmz#v0.1.0This adds zmz 0.1.0 to your build.zig.zon with a content hash. Then import its module in build.zig:
const zmz = b.dependency("zmz", .{ .target = target, .optimize = optimize });
executable.root_module.addImport("zmz", zmz.module("zmz"));Tip
Always fetch a release tag, as above. Without one, zig fetch takes whatever the default branch holds that day. To upgrade, run the same command with the newer tag. A program can read zmz.version to report which one it was built with.
This prints each record's ID, its MS level, and how many arrays it holds:
const std = @import("std");
const mzml = @import("zmz").mzml;
pub fn main(init: std.process.Init) !void {
const args = try init.minimal.args.toSlice(init.arena.allocator());
const file = try std.Io.Dir.cwd().openFile(init.io, args[1], .{});
defer file.close(init.io);
var buffer: [64 * 1024]u8 = undefined;
var input = file.reader(init.io, &buffer);
var reader = try mzml.StreamReader.init(init.gpa, &input.interface, .{});
defer reader.deinit();
const header = try reader.readHeader();
var arrays = mzml.DecodedArrays.init(init.gpa, .{});
defer arrays.deinit();
while (try reader.nextDecodedRecord(&arrays)) |record| {
const level = if (record.node.kind == .spectrum) try record.msLevel(header.groups) else null;
std.debug.print("{s} ms_level={?d} arrays={d}\n", .{ record.id, level, arrays.len() });
}
}Build it with zig build -Doptimize=ReleaseFast and run it on a file:
$ zig-out/bin/read-mzml run.mzML
scan=1 ms_level=1 arrays=2
scan=2 ms_level=2 arrays=2
scan=3 ms_level=2 arrays=2
What happens here, in order:
-
StreamReader.inittakes an allocator and astd.Io.Reader. It reads nothing yet. -
readHeaderreads everything before the first spectrum: vocabulary declarations, instruments, software, processing, and the parameter groups that records refer to (header.groups). -
nextDecodedRecordreads one spectrum or chromatogram and decodes its arrays intoarrays. It returns null at the end of the file. -
recordand the numbers inarraysare valid until the next call. That one rule matters a lot; Ownership and lifetimes explains it.
Note
zmz never guesses. A missing MS level is null, not 1; a missing unit stays missing; a malformed number is an error, not zero. Expect optionals and error unions, and handle them.
- Read only some arrays, copy files, or walk raw XML: Reading.
- Look up a spectrum by its ID: Indexed access.
- Write mzML: Writing.
- The repository has complete example programs for each of these, built and tested with the library.
zmz | Changelog | Contributing | Security | Apache License 2.0
Start here
Using zmz
- Reading
- Ownership and lifetimes
- Indexed access
- Writing
- Binary arrays
- Metadata and parameters
- Vocabulary
When things go wrong
Under the hood