1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//! Error types for the `dnoise` library.
//!
//! The library returns the typed [`DnoiseError`]; binaries can convert it into
//! `anyhow`/`eyre`/etc. via the standard [`std::error::Error`] impl. The low-level
//! type-2 decoder returns the narrower [`DecodeError`], which folds into
//! [`DnoiseError`] when used through the high-level pipeline.
use std::path::PathBuf;
use thiserror::Error;
/// Convenience alias for results produced by this crate.
pub type Result<T, E = DnoiseError> = std::result::Result<T, E>;
/// Anything that can go wrong while denoising a `.d` folder.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum DnoiseError {
/// Invalid input, configuration, or output path.
#[error("{0}")]
InvalidInput(String),
/// Installing output failed and recovery requires user attention.
#[error("{0}")]
Recovery(String),
/// The input path is not a Bruker `.d` folder (missing `analysis.tdf` /
/// `analysis.tdf_bin`).
#[error("{0} is not a Bruker .d folder (missing analysis.tdf / analysis.tdf_bin)")]
NotADotD(PathBuf),
/// The output folder already exists and overwriting was not requested.
#[error("output {0} already exists (pass force to overwrite)")]
OutputExists(PathBuf),
/// Opening the timsTOF frame data failed.
#[error("opening frame data: {0}")]
OpenFrames(String),
/// Reading the timsTOF metadata / calibration failed (needed by the diaPASEF
/// MS1 window gate to convert isolation m/z to TOF indices).
#[error("reading metadata: {0}")]
Metadata(String),
/// Reading or decoding a single frame failed.
#[error("reading frame {index}: {message}")]
FrameRead {
/// Zero-based frame index that failed.
index: usize,
/// Upstream reader message.
message: String,
},
/// Decoding a type-2 frame record failed.
#[error(transparent)]
Decode(#[from] DecodeError),
/// An underlying I/O error (copying the `.d`, writing `analysis.tdf_bin`, …).
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
/// An error from the `analysis.tdf` SQLite database.
#[error("database error: {0}")]
Sqlite(#[from] rusqlite::Error),
/// The run was cancelled via the [`crate::RunOptions::cancel`] token before it
/// finished. Any partial output is incomplete and should be discarded.
#[error("cancelled")]
Cancelled,
}
/// Failure decoding a type-2 `tdf_bin` frame record (see [`crate::codec`]).
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum DecodeError {
/// Decompression or encoding would exceed the supported frame size.
#[error("frame exceeds the 256 MiB size limit")]
SizeLimit,
/// Scan counts, offsets, or TOF deltas are inconsistent.
#[error("invalid frame layout or coordinates")]
InvalidLayout,
/// Record is shorter than the fixed 8-byte header.
#[error("record shorter than header")]
ShortRecord,
/// The record's declared `total_byte_count` is inconsistent with its length.
#[error("invalid total_byte_count {0}")]
InvalidByteCount(usize),
/// The decompressed payload is not a whole number of `u32` values.
#[error("decompressed blob not u32-aligned")]
Misaligned,
/// The decoded `scan_count` exceeds the decompressed payload length.
#[error("scan_count {scan_count} exceeds blob length {len}")]
ScanCountOverflow {
/// Decoded scan count.
scan_count: usize,
/// Number of `u32` values actually present.
len: usize,
},
/// zstd decompression of the payload failed.
#[error("zstd decompression failed: {0}")]
Zstd(#[source] std::io::Error),
}