Conversation
Apex-finder bench
Sensitivity + timing across canonical scenarioscommit c440386 |
| /// Borrows the arena the results were scored against to resolve each result's | ||
| /// row handle into the external library and competition-group IDs. | ||
| pub struct ResultParquetWriter<'a> { | ||
| sample: Option<crate::sample_identity::SampleIdentity>, |
There was a problem hiding this comment.
move the import up
There was a problem hiding this comment.
Moved SampleIdentity into the top-level imports in fbfb7a5.
| ArrowWriter::try_new(file, schema, Some(props)).map_err(std::io::Error::other)?; | ||
|
|
||
| Ok(Self { | ||
| sample: None, |
There was a problem hiding this comment.
Q: why not pass the identity directly instead of having this as an option + over-write?
There was a problem hiding this comment.
The optional setter only preserved the old constructor API; no current caller needed identity-less output. Changed new/raw to require &SampleIdentity and establish metadata at construction. Removed the optional state and setter; updated all callers and empty/nonempty raw/rescored tests. 306 unit tests pass, clippy clean (fbfb7a5).
| // Fixed FNV-1a 64-bit over UTF-8 bytes. Not DefaultHasher: its implementation | ||
| // is not a persistence contract. Parent text includes its trailing slash. | ||
| fn fnv1a64(bytes: &[u8]) -> u64 { | ||
| bytes.iter().fold(0xcbf29ce484222325, |hash, byte| { |
There was a problem hiding this comment.
O.O pretty interesting ...
| let mut stem = name; | ||
| loop { | ||
| let before = stem; | ||
| for ext in [".idx", ".tar", ".gz", ".d", ".raw", ".mzML", ".mzml"] { |
There was a problem hiding this comment.
Q: do we define these elsewhere?
There was a problem hiding this comment.
Overlapping checks exist, but no shared suffix list: tims_stage::uri::parse_uri_shape classifies .idx/.tar; vendor readers sniff formats (e.g. mzML). Those answer format support, not stable identity normalization. Named this SAMPLE_STORAGE_SUFFIXES and documented that distinction in fbfb7a5; enabling another reader should not silently change persisted IDs. In particular, stripping .raw/.mzML.gz here does not claim those formats are currently readable.
There was a problem hiding this comment.
Q2: why is this defined as caps sensitive match?
There was a problem hiding this comment.
Case sensitivity was inherited from the old helper, not intentional. bef2891 makes suffix matching ASCII-case-insensitive (.D, .RAW, .MzMl.GZ, etc.) while preserving stem and parent URI case. Added mixed-case, Unicode and duplicate-identity fixtures. Also renamed writer new() to rescored() to make the schema distinction from raw() explicit.
There was a problem hiding this comment.
Updated per our discussion: a19ef90 removes the separate sample suffix list. RawReader now owns sample_name(); built-in readers share the same case-insensitive rule for sniffing and naming, and ReaderRegistry dispatches naming. Staging unwraps .idx/.tar (preserving standalone wrapper names without a raw suffix); SampleIdentity retains validation and URI hashing. Unsupported raw formats are no longer assigned guessed stems. Verified 410 unit tests, nine registry tests without default features, CLI duplicate-input integration, formatting and clippy.
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Windows-invalid characters in derived directory suffixes can cause valid remote-key inputs to fail output creation.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
What changed in this PR
Adds stable, location-derived sample identities across search outputs, reports, artifacts, and Parquet metadata.
Changes:
- Adds FNV-1a IDs and duplicate-input validation.
- Propagates identities through outputs, cleanup, uploads, and reports.
- Updates PSI-MS metadata version and development documentation.
| File | Description |
|---|---|
rust/timsseek/src/scoring/timings.rs |
Adds identity to reports. |
rust/timsseek/src/scoring/parquet_writer.rs |
Stores identity metadata in Parquet files. |
rust/timsseek/src/sample_identity.rs |
Implements identity derivation and validation. |
rust/timsseek/src/lib.rs |
Exposes the identity module. |
rust/timsseek_cli/tests/sample_identity.rs |
Tests duplicate rejection. |
rust/timsseek_cli/src/search.rs |
Integrates identity resolution into searches. |
rust/timsseek_cli/src/sample_identity.rs |
Resolves identities and detects duplicates. |
rust/timsseek_cli/src/processing.rs |
Propagates identities to writers and reports. |
rust/timsseek_cli/src/output_sink.rs |
Removes legacy basename derivation. |
rust/timsseek_cli/src/main.rs |
Registers the CLI module. |
rust/timsseek_cli/src/artifacts.rs |
Uses identities for artifact probing. |
rust/timsquery/src/serde/psims_origin_type.rs |
Updates the ontology version. |
docs/development.md |
Documents identity and output-path behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if name.contains('\\') || name.chars().any(char::is_control) { | ||
| return None; | ||
| } |
There was a problem hiding this comment.
NGL this suggestion looks disgusting ...
There was a problem hiding this comment.
ngl this looks horrendous and im unsure when it actually matters.
I do like that there is something raised in the sense that some remote keys can include byte-range assets (say define a file inside a .zip) but this is very much not within the scope of this PR
There was a problem hiding this comment.
Leaving the proposed Windows-character restriction/encoding expansion out per your scope feedback. This concern is specifically a remote key being reused as a Windows staging-directory component; it does not require archive/member or byte-range URI handling, and none is added here. The existing minimal separator/control-character checks remain unchanged.
|
NGL this feels like a solution to a non-problem ... |

Summary
--overwrite. Rerunning the same command with--overwritestill replaces prior outputs normally. Same stems in different parents work in batch or independent invocations.sample_id/sample_namein run/performance reports and Parquet metadata, including empty and raw-score files.SampleIdentity, not arbitrary ID/name strings; no unchecked deserialization.Compatibility
Per-sample directories change from
<stem>/to<16-hex-prefix>-<stem>/. Legacy directories are not migrated. Parquet columns/format version remain unchanged: sample identity is file-level metadata. Consumers combining files must retain that metadata. Local paths become absolute without resolving symlinks; no moved-file/content equivalence is promised. Seedocs/development.mdfor pinned decomposition and fixtures.No library provenance, generated-decoy, scientific scoring, reducer, or FDR changes.
CI vocabulary refresh
Regenerated PSI-MS origin-type snapshot from 4.1.261 to 4.2.2. The generated diff is only the version string: all ten origin terms and their decoy/theoretical-m/z memberships are identical. Compared full release term stanzas excluding new
subset:tags: no existing terms removed, onlyMS:1003384(semantic-version regex, unused here) changed; 1,934 terms added outside the generated subtree. mzSpecLib reader's RT/mobility, origin and decoy term semantics remain unchanged.Sources: 4.1.261, 4.2.2.
Additional checks:
uv run python scripts/gen_psims_origin_type.py --check;cargo test -p timsquery serde::mzspeclib_io— all 29 reader tests passed.Verification
cargo test -p timsseek_cli -p timsseek --lib --bins— 306 passed, 1 existing ignored testcargo test -p timsseek_cli --test sample_identity— CLI rejection with/without overwritecargo test -p timsseek --doc sample_identity— forging private fields fails compilationcargo clippy -p timsseek -p timsseek_cli --all-targets -- -D warningstask fmt;git diff --checkTests pin hash vectors, independent/reordered runs, local/remote paths, storage suffixes, duplicate/invalid inputs, separate artifact destinations, cleanup isolation, JSON fields and empty/nonempty Parquet metadata in both modes. No live cloud upload or full instrument-data search was performed.