From 0be4a9afa6d785b4507ab4c568e91b5933d781b8 Mon Sep 17 00:00:00 2001 From: Paullo9 Date: Sun, 1 Nov 2026 17:10:44 +0100 Subject: [PATCH 1/2] fix: reader notes state what is known instead of unvalidated Apps show the reader notes verbatim, so each note now states the plain fact and names where in the file the value is stored: - TIFFVeloxCalibration: "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard". - AcquisitionMetadata (generic): "no published reader reads this field; read as the file stores it". Each format now attaches its own wording: DM image tags, Velox metadata, the FEI extended header at the offset mrcfile declares, the Velox XML or the FEI header of a TIFF. - Velox detector: "read from BinaryResult.Detector; RosettaSciIO names some detectors from another field". - MRC camera length: "shown as stored; the instrument mode is not checked, as no published reader decodes it". The public names stay (unvalidatedNote, veloxUnvalidated); the new names noPublishedReaderNote, storedScaleNote and veloxStoredScale are aliases of the same strings. Only note text changes; no value moves. tools/acq-metadata/generate.py applies the same wording to the pinned app output, so a regeneration reproduces the pins. Done: notes reworded, tests pin the new texts. Next: consumers re-pin their snapshot tests when they update. Co-Authored-By: Claude Opus 5.5 --- Sources/FormatoCore/AcquisitionMetadata.swift | 16 +++++---- Sources/FormatoDM/AcquisitionMetadataDM.swift | 11 +++--- .../FormatoEMD/AcquisitionMetadataVelox.swift | 21 ++++++------ .../FormatoMRC/AcquisitionMetadataMRC.swift | 6 ++-- .../FormatoTIFF/AcquisitionMetadataTIFF.swift | 20 ++++++----- Sources/FormatoTIFF/TIFFAppImage.swift | 4 ++- .../FormatoTIFF/TIFFVeloxCalibration.swift | 7 ++-- .../AcquisitionMetadataTests.swift | 7 ++++ .../AcquisitionMetadataDMTests.swift | 2 +- .../CameraPixelPitchTests.swift | 5 +-- .../AcquisitionMetadataVeloxTests.swift | 6 ++-- .../VeloxEELSAcquisitionTests.swift | 3 +- .../AcquisitionMetadataMRCTests.swift | 2 +- .../AcquisitionMetadataTIFFTests.swift | 6 ++-- .../FormatoTIFFTests/TIFFAppImageTests.swift | 5 ++- .../TIFFCameraPixelPitchTests.swift | 4 +-- tools/acq-metadata/generate.py | 34 ++++++++++++++++++- 17 files changed, 108 insertions(+), 51 deletions(-) diff --git a/Sources/FormatoCore/AcquisitionMetadata.swift b/Sources/FormatoCore/AcquisitionMetadata.swift index 97461f1..e3c69e3 100644 --- a/Sources/FormatoCore/AcquisitionMetadata.swift +++ b/Sources/FormatoCore/AcquisitionMetadata.swift @@ -75,7 +75,7 @@ public nonisolated struct AcquisitionMetadata: Sendable, Equatable { /// The instrument, as the file names it. public var instrument: MetadataReading? /// The operating mode as the file states it: a name ("STEM", "TEM · DIFFRACTION") for Velox and DM; the stored - /// integer for MRC, labelled unvalidated (no pinned reference decodes it). + /// integer for MRC, with a note that no published reader decodes it. public var mode: MetadataReading? // MARK: Added in 0.3.1 (additive). Read by the `.rosettaSciIO` convention only, where RosettaSciIO 049e7d70 maps the key @@ -120,7 +120,7 @@ public nonisolated struct AcquisitionMetadata: Sendable, Equatable { /// RosettaSciIO uses it as the axis scale, not as metadata, so the `note` says what the file does not settle. public var pixelSize: MetadataReading? /// Convergence semi-angle in mrad. A Velox EELS spectrum image (`velox(eelsSpectrumImage:)`, `.rosettaSciIO` only) also fills - /// it, labelled unvalidated: no published reader reads the stored value. + /// it, with a note that no published reader reads the stored value. public var convergenceAngleMrad: MetadataReading? // MARK: Added after 0.11.0 (additive). Read by the DM reader from an image object (`AcquisitionMetadata.dm(_:convention:)`), and @@ -132,7 +132,7 @@ public nonisolated struct AcquisitionMetadata: Sendable, Equatable { /// is the first and `rows` the second, units "um" as the tag names them; the note says so when the two differ. Not the /// binned frame pixel (`Acquisition.Frame.CCD.Pixel Size (um)`). Nil when the tag is absent, does not hold exactly two /// numbers, or holds one that is not finite and positive. RosettaSciIO maps the tag for a CL signal only (its - /// `Detector.pixel_size`, also in `signalNumbers`); on any other signal `.rosettaSciIO` labels it `unvalidatedNote`. The + /// `Detector.pixel_size`, also in `signalNumbers`); on any other signal `.rosettaSciIO` notes that no published reader reads it. The /// `.app` convention reads it too (an extension of the consumer's rule set, which has no pitch), unlabelled. public var cameraPixelPitch: MetadataReading? @@ -206,7 +206,8 @@ public nonisolated struct AcquisitionMetadata: Sendable, Equatable { /// /// `.rosettaSciIO` (the default) follows RosettaSciIO at the pinned commit for every field RosettaSciIO maps: its tag /// choice, its mode tests and its unit arithmetic, with no positivity rule (a stored zero is 0, not nil). A field -/// RosettaSciIO does not map is read by the consumer's rule and carries the note ``AcquisitionMetadata/unvalidatedNote``. +/// RosettaSciIO does not map is read by the consumer's rule and carries the format's wording of +/// ``AcquisitionMetadata/noPublishedReaderNote``. /// `.app` is the consumer's own rule set (a to g above), pinned to its source; `docs/parity.md` lists the differences. public nonisolated enum AcquisitionMetadataConvention: Sendable, Equatable { case rosettaSciIO @@ -214,6 +215,9 @@ public nonisolated enum AcquisitionMetadataConvention: Sendable, Equatable { } extension AcquisitionMetadata { - /// The note of a value no RosettaSciIO mapping reads. - public static let unvalidatedNote = "unvalidated: no published reader reads it" + /// The note of a value no RosettaSciIO mapping reads: it is read as the file stores it. Each format's reader attaches + /// its own wording of this note, naming where in the file the value is stored. + public static let noPublishedReaderNote = "no published reader reads this field; read as the file stores it" + /// The same note under its older name. + public static let unvalidatedNote = noPublishedReaderNote } diff --git a/Sources/FormatoDM/AcquisitionMetadataDM.swift b/Sources/FormatoDM/AcquisitionMetadataDM.swift index 2f52409..475caf2 100644 --- a/Sources/FormatoDM/AcquisitionMetadataDM.swift +++ b/Sources/FormatoDM/AcquisitionMetadataDM.swift @@ -25,7 +25,7 @@ // the dwell with DigiScan tags, else the exposure; X-ray: neither; CL: the DigiScan sample time). The EELS frame number, // aperture and spectrometer, the X-ray (EDS) and CL groups and the SI group are read into `signalNumbers`/`signalTexts` under // RosettaSciIO's own path names, and the date and time take the last source that parses (DataBar, SI, then the signal group; for CL DataBar again, as the mapping ends). -// Fields RosettaSciIO does not map (the detector) are read by the consumer's rule with `unvalidatedNote`. The +// Fields RosettaSciIO does not map (the detector) are read by the consumer's rule with `DMNote.unvalidated`. The // signal-type mappings (EELS, X-ray, CL, SI) are applied from the tag maps (`Meta Data.Signal`), not from a signal object. // // `.app` is the consumer's rule set (AcquisitionMetadata.swift, rules a to g), pinned to its source: @@ -139,7 +139,8 @@ extension AcquisitionMetadata { nonisolated enum DMNote { static let cameraLengthUnit = "mm (assumed)" static let monthFirst = "month-first order assumed" - static let unvalidated = "unvalidated: no published reader reads it" + /// This format's wording of `noPublishedReaderNote`: the value is read as the DM image tags store it. + static let unvalidated = "no published reader reads this field; read as stored in the DM image tags" } /// The two ImageTags maps with the stack-builder fallback: the direct key, else the same key under @@ -267,10 +268,10 @@ extension AcquisitionMetadata { private static let dmCreationPrefix = "source.Tags at creation." /// `Acquisition.Device.CCD.Pixel Size (um)` as a pitch: exactly two finite positive numbers (x, y), else nil. `unvalidated` - /// adds `unvalidatedNote` (`.rosettaSciIO` on a signal RosettaSciIO does not map the tag for). + /// adds `DMNote.unvalidated` (`.rosettaSciIO` on a signal RosettaSciIO does not map the tag for). private static func dmCameraPitch(_ stored: [Double]?, unvalidated: Bool = false) -> MetadataReading? { guard let stored, stored.count == 2, stored.allSatisfy({ $0.isFinite && $0 > 0 }) else { return nil } - let notes = [stored[0] == stored[1] ? nil : unequalPitchNote, unvalidated ? unvalidatedNote : nil].compactMap { $0 } + let notes = [stored[0] == stored[1] ? nil : unequalPitchNote, unvalidated ? DMNote.unvalidated : nil].compactMap { $0 } return MetadataReading(PixelSize(rows: stored[1], columns: stored[0], units: "um"), note: notes.isEmpty ? nil : notes.joined(separator: "; ")) } @@ -463,7 +464,7 @@ extension AcquisitionMetadata { } // RosettaSciIO maps no detector: the camera name as stored, labelled. - if let name = text(string("Acquisition.Device.Name")) { meta.detector = MetadataReading(name, note: unvalidatedNote) } + if let name = text(string("Acquisition.Device.Name")) { meta.detector = MetadataReading(name, note: DMNote.unvalidated) } // The camera pitch, every signal type: the tag as stored. RosettaSciIO maps it for CL only (`Detector.pixel_size` above), // so on any other signal it is the consumer's rule, labelled. meta.cameraPixelPitch = dmCameraPitch(arrays[prefix + dmDevicePitchKey], unvalidated: signalType != "CL") diff --git a/Sources/FormatoEMD/AcquisitionMetadataVelox.swift b/Sources/FormatoEMD/AcquisitionMetadataVelox.swift index f69d907..20849ef 100644 --- a/Sources/FormatoEMD/AcquisitionMetadataVelox.swift +++ b/Sources/FormatoEMD/AcquisitionMetadataVelox.swift @@ -7,7 +7,7 @@ // field: `Optics.AccelerationVoltage` / 1e3 (kV), `Optics.CameraLength` * 1e3 (mm, in every mode), // `CustomProperties.StemMagnification.value` as the magnification (Velox stores an unset bool as 0; it is returned as // stored); no positivity rule. RosettaSciIO maps no detector, dwell, exposure, mode or date for an image; those are read -// by the consumer's rule with `unvalidatedNote`: the detector `BinaryResult.Detector`, the instrument +// by the consumer's rule with `veloxUnvalidated` (no published reader; read as stored): the detector `BinaryResult.Detector`, the instrument // `Instrument.InstrumentModel` (`.app`; under `.rosettaSciIO` it is `instrumentModel`, and `instrument` is RosettaSciIO's `InstrumentClass`), the dwell `Scan.DwellTime` only for a // ScanningDetector, the exposure of the detector the image names (`VeloxMetadata.exposureTimeSeconds`), the magnification // `Optics.NominalMagnification` when no `StemMagnification` is stored, the mode `Optics.OperatingMode` as the stored @@ -18,7 +18,7 @@ // the note says it is not a metadata mapping) under `.rosettaSciIO`, and `velox(spectrumImage:)`, the same fields for the metadata // of a spectrum image (`VeloxEMDReader.spectrumImageMetadata()`). `velox(eelsSpectrumImage:)` reads the same fields from one EELS // spectrum image's metadata (`VeloxEMDReader.eelsSpectrumImageMetadata()`) plus the collection and convergence semi-angles, where -// RosettaSciIO maps nothing (the collection angle as pyEELSMODEL reads it; the convergence angle labelled unvalidated). +// RosettaSciIO maps nothing (the collection angle as pyEELSMODEL reads it; the convergence angle noted as read by no published reader). // // `.app` is the consumer's reading of the same entry, pinned to its source: high tension, detector, instrument, start // date and dwell only; magnification, camera length, exposure and mode are `unread` (the consumer's reader predated the @@ -44,7 +44,7 @@ nonisolated extension AcquisitionMetadata { if let stem = m.stemMagnification { out.magnification = MetadataReading(stem) } else if let nominal = positive(m.nominalMagnification) { - out.magnification = MetadataReading(nominal, note: unvalidatedNote) + out.magnification = MetadataReading(nominal, note: veloxUnvalidated) } // The microscope is `Instrument.InstrumentClass` (`_get_mapping`, :947-950), as stored; the stored model is kept beside it. out.instrument = m.instrumentClass.map { MetadataReading($0) } // as stored, as RosettaSciIO passes it @@ -66,9 +66,9 @@ nonisolated extension AcquisitionMetadata { if let unitY = text(m.pixelUnitY), unitY != unit { note += "; PixelUnitY is '\(unitY)', RosettaSciIO uses PixelUnitX for both" } out.pixelSize = MetadataReading(PixelSize(rows: size.height, columns: size.width, units: unit), note: note) } - if let seconds = positive(m.exposureTimeSeconds) { out.exposureS = MetadataReading(seconds, note: unvalidatedNote) } + if let seconds = positive(m.exposureTimeSeconds) { out.exposureS = MetadataReading(seconds, note: veloxUnvalidated) } if let mode = text(m.operatingMode) { - out.mode = MetadataReading(mode, note: "the stored code, not decoded; " + unvalidatedNote) + out.mode = MetadataReading(mode, note: "the stored code, not decoded; " + veloxUnvalidated) } return out } @@ -87,7 +87,7 @@ nonisolated extension AcquisitionMetadata { /// `velox(spectrumImage:)`, among them the beam energy `Optics.AccelerationVoltage` / 1e3 (kV, RosettaSciIO's mapping for /// the EDS signal of the same file; pyEELSMODEL's `emd_reader` reads the same volts as E0), and the two angles in mrad: /// the collection semi-angle `EnergyFilter.CollectionAngleRange.End` × 1e3 (pyEELSMODEL's beta, radians as stored) and - /// the convergence semi-angle `Optics.BeamConvergence` × 1e3 (no published reader reads it: unvalidated). An angle that is + /// the convergence semi-angle `Optics.BeamConvergence` × 1e3 (no published reader reads it; noted so). An angle that is /// not a finite positive number is nil (pyEELSMODEL passes a stored 0 through as beta; here 0 is no collection angle). The /// angles are read under `.rosettaSciIO` only; `.app` gives what `velox(spectrumImage:)` gives. public static func velox(eelsSpectrumImage metadata: VeloxMetadata, timeZone: TimeZone = .current, @@ -126,10 +126,11 @@ nonisolated extension AcquisitionMetadata { return out } - static let veloxUnvalidated = "unvalidated: no published reader reads it" - /// The registered clause failed (2026-10-13, velox-image-parity): RosettaSciIO's title comes from the file's - /// Operations, not `BinaryResult.Detector`, and differs on 7 of 33 public and owner files ("Ceta" for "BM-Ceta"). - static let veloxDetectorNote = "unvalidated: RosettaSciIO names some detectors from another field" + /// This format's wording of `noPublishedReaderNote`: the value is read as the Velox metadata stores it. + static let veloxUnvalidated = "no published reader reads this field; read as stored in the Velox metadata" + /// RosettaSciIO's title comes from the file's Operations, not `BinaryResult.Detector`, and differs on 7 of 33 public + /// and owner files ("Ceta" for "BM-Ceta"). + static let veloxDetectorNote = "read from BinaryResult.Detector; RosettaSciIO names some detectors from another field" /// Unix seconds as `YYYY-MM-DD HH:MM:SS` on `timeZone`'s clock (whole seconds, truncated as RosettaSciIO's /// `isoformat` is); nil when not finite or out of the four-digit years. diff --git a/Sources/FormatoMRC/AcquisitionMetadataMRC.swift b/Sources/FormatoMRC/AcquisitionMetadataMRC.swift index b784678..72d1907 100644 --- a/Sources/FormatoMRC/AcquisitionMetadataMRC.swift +++ b/Sources/FormatoMRC/AcquisitionMetadataMRC.swift @@ -103,7 +103,7 @@ // STEM Detector name, else Camera name, else Detector commercial name (FEI2). DEVIATION from the first sketch // (detector: STEM Detector name, else Camera name): the third source is needed because 4DSTEMscan.mrc names its // detector only there ("Ceta-S speed"). Exposure = "Integration time" (the layout has no field called exposure; -// this is the camera field in seconds) — unvalidated and labelled so (`unvalidatedNote`): mrcfile declares the +// this is the camera field in seconds) — labelled `unvalidatedNote` (no published reader; read as stored): mrcfile declares the // field (f8 at offset 419, mask 2 bit 16) and the harness plants and compares it, but no pinned reader treats it // as an exposure and no real file records a positive value. // @@ -195,10 +195,10 @@ nonisolated struct FEIRecord { static let fei1Size = 768 static let fei2Size = 888 /// The label of a value whose path no pinned reference reads (exposure, mode). - static let unvalidatedNote = "unvalidated: no published reader reads it" + static let unvalidatedNote = "no published reader reads this field; read as stored in the FEI extended header, at the offset mrcfile declares" /// RULE (c), open deviation: the label of a camera length shown without a mode test (Instrument mode and /// Projection mode are enumerations no published reader decodes). - static let modeUncheckedNote = "unvalidated: the mode is not checked" + static let modeUncheckedNote = "shown as stored; the instrument mode is not checked, as no published reader decodes it" /// A field: its byte offset in the record and the (mask, bit) that says it was written. Masks are 0...3 for /// Bitmask 1...4; their offsets are `maskOffsets`. diff --git a/Sources/FormatoTIFF/AcquisitionMetadataTIFF.swift b/Sources/FormatoTIFF/AcquisitionMetadataTIFF.swift index 9abc8a1..cd65bad 100644 --- a/Sources/FormatoTIFF/AcquisitionMetadataTIFF.swift +++ b/Sources/FormatoTIFF/AcquisitionMetadataTIFF.swift @@ -11,7 +11,7 @@ // ports) joined into one stamp; no positivity rule (a stored 0 is 0), values as tifffile's `astype` makes them; // - Velox XML: the same schema's EMD mapping (`emd/_emd_velox.py` `_get_mapping`, :934-948): `Optics.AccelerationVoltage` // / 1e3 and `Optics.CameraLength` * 1e3 with NO mode gate and no positivity rule; every other value is read by the -// consumer's rule and keeps its `unvalidatedNote`; +// consumer's rule and keeps its `TIFFNote.veloxUnvalidated`; // - the DM tag stream (tag 65027) goes through `AcquisitionMetadata.dm` with the same convention. // // WHAT IS READ, first directory only, in the order FEI SEM, Velox, DM (the first two are the order @@ -61,7 +61,7 @@ // projector mode is read only to decide rule (c); it is not part of the mode shown. // Which Velox paths a published reader maps: RosettaSciIO 049e7d70 rsciio/emd/_emd_velox.py maps // Optics.AccelerationVoltage (lines 938–941, / 1e3) and Optics.CameraLength (942–945, × 1e3, in no mode gate): those -// two carry no `TIFFNote.unvalidated`, every other value does — the same schema, no reader. In particular the date: +// two carry no `TIFFNote.veloxUnvalidated`, every other value does — the same schema, no reader. In particular the date: // the reference reads Acquisition.AcquisitionStartDatetime.DateTime (902–903, 916–918, 934–937), the EMD's unix-time // sub-key shown in the VIEWER's zone and mapped to General.time_zone; the TIFF's XML text of that element is ISO // local text with no DateTime child (measured on the six Ceta files), a path no published reader reads. (It also @@ -94,7 +94,7 @@ // [PrivateFei] TimeOfCreation (a second stamp, dd.mm.yyyy hh:mm:ss, not a registered path). // RosettaSciIO 049e7d70 rsciio/tiff/_api.py `mapping_fei` (lines 1130–1159) maps Beam.HV (× 1e-3 via // `_parse_beam_energy_FEI`, lines 1081–1085: float() or None), Scan.Dwelltime (as is), User.Date and User.Time -// (dateutil) and System.SystemType; it does not map [Detectors] Name, so the detector carries `TIFFNote.unvalidated`. +// (dateutil) and System.SystemType; it does not map [Detectors] Name, so the detector carries `TIFFNote.feiUnvalidated`. // DEVIATION: HV is divided by 1e3 here, multiplied by 1e-3 there — the same number to within one ulp. // DEVIATION: a stored 0 (HV or Dwelltime) is 0.0 there and "not recorded" here (rule b). // DEVIATION: the dwell is stated in µs here, seconds there (the registered unit). @@ -125,7 +125,9 @@ nonisolated extension AcquisitionMetadata { /// The notes this reader attaches, worded once. Private: the other readers word their own, and the tests pin /// the texts as literals. private enum TIFFNote { - static let unvalidated = "unvalidated: no published reader reads it" + /// This format's wordings of `noPublishedReaderNote`, naming the block of the TIFF the value is stored in. + static let veloxUnvalidated = "no published reader reads this field; read as stored in the Velox XML of the TIFF" + static let feiUnvalidated = "no published reader reads this field; read as stored in the FEI header of the TIFF" } /// The acquisition values a TIFF records; an empty `AcquisitionMetadata` when it records none. Throws only @@ -189,7 +191,7 @@ nonisolated extension AcquisitionMetadata { if let current = sections["EBeam"]?["BeamCurrent"]?.asFloat { out.beamCurrentNA = MetadataReading(current * 1e9) } if case .string(let user)? = sections["User"]?["User"] { out.operatorName = MetadataReading(user) } if case .string(let name)? = sections["Detectors"]?["Name"], let name = text(name) { - out.detector = MetadataReading(name, note: unvalidatedNote) + out.detector = MetadataReading(name, note: TIFFNote.feiUnvalidated) } return out } @@ -241,12 +243,12 @@ nonisolated extension AcquisitionMetadata { func child(_ element: XMLElement, _ name: String) -> String? { GuardedXML.bounded(text(element.elements(forName: name).first?.stringValue)) } - // A reading with the notes that apply: its own, then "unvalidated" unless a published reader maps its path. + // A reading with the notes that apply: its own, then the no-published-reader note unless a published reader maps its path. let readByReference: Set = ["Optics/AccelerationVoltage", "Optics/CameraLength", "Instrument/InstrumentClass", "Stage/AlphaTilt", "Stage/BetaTilt", "Stage/Position/x", "Stage/Position/y", "Stage/Position/z"] func reading(_ value: V, _ path: String, note: String? = nil, otherCopy: V? = nil) -> MetadataReading { - MetadataReading(value, note: joined(note, readByReference.contains(path) ? nil : TIFFNote.unvalidated), + MetadataReading(value, note: joined(note, readByReference.contains(path) ? nil : TIFFNote.veloxUnvalidated), otherCopy: otherCopy) } @@ -326,9 +328,9 @@ nonisolated extension AcquisitionMetadata { private static func fei(_ sections: [String: [String: String]]) -> AcquisitionMetadata { var out = AcquisitionMetadata() func stored(_ section: String, _ key: String) -> String? { text(sections[section]?[key]) } - // "unvalidated" unless mapping_fei maps the path (Beam.HV, Scan.Dwelltime, User.Date/Time, System.SystemType). + // The no-published-reader note unless mapping_fei maps the path (Beam.HV, Scan.Dwelltime, User.Date/Time, System.SystemType). func reading(_ value: V, mapped: Bool, note: String? = nil) -> MetadataReading { - MetadataReading(value, note: joined(note, mapped ? nil : TIFFNote.unvalidated)) + MetadataReading(value, note: joined(note, mapped ? nil : TIFFNote.feiUnvalidated)) } // Rule (b) after the unit conversion, as for the Velox values: a stored 5e-324 V is 0.0 kV, a stored 1e306 s is diff --git a/Sources/FormatoTIFF/TIFFAppImage.swift b/Sources/FormatoTIFF/TIFFAppImage.swift index e0634e4..bd7166d 100644 --- a/Sources/FormatoTIFF/TIFFAppImage.swift +++ b/Sources/FormatoTIFF/TIFFAppImage.swift @@ -84,7 +84,9 @@ public nonisolated enum TIFFAppImage { /// The notes a reading can attach, worded once. public enum Note { public static let render = "8-bit render, not counts" - public static let veloxUnvalidated = TIFFVeloxCalibration.unvalidatedNote + public static let veloxStoredScale = TIFFVeloxCalibration.storedScaleNote + /// The same note under its older name. + public static let veloxUnvalidated = veloxStoredScale public static let veloxDisagree = TIFFVeloxCalibration.disagreeNote } diff --git a/Sources/FormatoTIFF/TIFFVeloxCalibration.swift b/Sources/FormatoTIFF/TIFFVeloxCalibration.swift index 2b4b6ee..5857bbd 100644 --- a/Sources/FormatoTIFF/TIFFVeloxCalibration.swift +++ b/Sources/FormatoTIFF/TIFFVeloxCalibration.swift @@ -21,8 +21,11 @@ public nonisolated enum TIFFVeloxCalibration: Sendable, Equatable { /// The XML and the resolution tags name different sizes. case disagree - /// The note of a calibrated reading: the scale comes from one convention seen on one acquisition. - public static let unvalidatedNote = "scale unvalidated (one acquisition)" + /// The note of a calibrated reading: the scale is the pixel size Velox wrote (`BinaryResult/PixelSize`), at most + /// cross-checked against the file's own resolution tags (metres, tag 65452 = 3); no calibration standard checks it. + public static let storedScaleNote = "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" + /// The same note under its older name. + public static let unvalidatedNote = storedScaleNote /// The note of `disagree`. public static let disagreeNote = "uncalibrated: the Velox XML and the resolution tags disagree" diff --git a/Tests/FormatoCoreTests/AcquisitionMetadataTests.swift b/Tests/FormatoCoreTests/AcquisitionMetadataTests.swift index bdb3419..0e8a3ed 100644 --- a/Tests/FormatoCoreTests/AcquisitionMetadataTests.swift +++ b/Tests/FormatoCoreTests/AcquisitionMetadataTests.swift @@ -79,4 +79,11 @@ import FormatoCore #expect(formatoDisplayFileName("") == "") #expect(formatoDisplayFileName("/") == "/") } + + @Test func theNoReferenceNoteStatesTheFactAndKeepsItsOldName() { + // Apps show the note verbatim: it says what is known (no published reader, read as stored), never "unvalidated". + #expect(AcquisitionMetadata.noPublishedReaderNote == "no published reader reads this field; read as the file stores it") + #expect(AcquisitionMetadata.unvalidatedNote == AcquisitionMetadata.noPublishedReaderNote) + #expect(!AcquisitionMetadata.noPublishedReaderNote.lowercased().contains("unvalidated")) + } } diff --git a/Tests/FormatoDMTests/AcquisitionMetadataDMTests.swift b/Tests/FormatoDMTests/AcquisitionMetadataDMTests.swift index 96a8424..297d5d0 100644 --- a/Tests/FormatoDMTests/AcquisitionMetadataDMTests.swift +++ b/Tests/FormatoDMTests/AcquisitionMetadataDMTests.swift @@ -162,7 +162,7 @@ import FormatoDM let names = try both("whitespace-names") #expect(names.reference.instrument?.value == " " && names.app.instrument?.value == "Titan") // The detector is mapped by neither RosettaSciIO nor the app's reference: labelled in both conventions' defaults. - #expect(tem.reference.detector == MetadataReading("K2", note: AcquisitionMetadata.unvalidatedNote)) + #expect(tem.reference.detector == MetadataReading("K2", note: "no published reader reads this field; read as stored in the DM image tags")) // The ambiguous day/month order is named in the note. let ambiguous = try both("ambiguous-date") #expect(ambiguous.reference.acquired?.value == "2021-03-04 00:00:00") diff --git a/Tests/FormatoDMTests/CameraPixelPitchTests.swift b/Tests/FormatoDMTests/CameraPixelPitchTests.swift index c2f73a5..92d4975 100644 --- a/Tests/FormatoDMTests/CameraPixelPitchTests.swift +++ b/Tests/FormatoDMTests/CameraPixelPitchTests.swift @@ -54,7 +54,8 @@ import FormatoDM let object = try Self.object("rsciio-EELS_SI.dm4") let meta = AcquisitionMetadata.dm(object) #expect(meta.cameraPixelPitch?.value == PixelSize(rows: 14, columns: 14, units: "um")) - #expect(meta.cameraPixelPitch?.note == AcquisitionMetadata.unvalidatedNote, "not mapped by RosettaSciIO outside CL") + #expect(meta.cameraPixelPitch?.note == "no published reader reads this field; read as stored in the DM image tags", + "not mapped by RosettaSciIO outside CL") #expect(meta.signalNumbers["Detector.pixel_size"] == nil, "RosettaSciIO maps the tag for CL only") let app = AcquisitionMetadata.dm(object, convention: .app) #expect(app.cameraPixelPitch?.value == PixelSize(rows: 14, columns: 14, units: "um")) @@ -179,7 +180,7 @@ import FormatoDM @Test func aPlantedSquarePitchOutsideCLHasNoCLKey() throws { let meta = AcquisitionMetadata.dm(try Self.file(tags: Self.device([15, 15]))) #expect(meta.cameraPixelPitch?.value == PixelSize(rows: 15, columns: 15, units: "um")) - #expect(meta.cameraPixelPitch?.note == AcquisitionMetadata.unvalidatedNote) + #expect(meta.cameraPixelPitch?.note == "no published reader reads this field; read as stored in the DM image tags") #expect(meta.signalNumbers["Detector.pixel_size"] == nil) let cl = AcquisitionMetadata.dm(try Self.file(tags: Self.device([15, 15], signal: "CL"))) #expect(cl.signalNumbers["Detector.pixel_size"]?.value == 15) diff --git a/Tests/FormatoEMDTests/AcquisitionMetadataVeloxTests.swift b/Tests/FormatoEMDTests/AcquisitionMetadataVeloxTests.swift index 82c79f5..ee1b28d 100644 --- a/Tests/FormatoEMDTests/AcquisitionMetadataVeloxTests.swift +++ b/Tests/FormatoEMDTests/AcquisitionMetadataVeloxTests.swift @@ -46,14 +46,14 @@ extension VeloxEMDSerialized { let ceta = AcquisitionMetadata.velox(try #require(entries["ceta"]), timeZone: Self.utc) // StemMagnification "0" is returned as stored (RosettaSciIO's float); the camera's exposure is the detector the image names. #expect(ceta.magnification == MetadataReading(0)) - #expect(ceta.exposureS == MetadataReading(0.5, note: AcquisitionMetadata.unvalidatedNote)) + #expect(ceta.exposureS == MetadataReading(0.5, note: "no published reader reads this field; read as stored in the Velox metadata")) #expect(ceta.mode?.value == "1") #expect(ceta.cameraLengthMM == MetadataReading(844.0)) // RosettaSciIO's microscope is InstrumentClass ("Talos"); the stored model is kept beside it, labelled. #expect(ceta.instrument == MetadataReading("Talos")) - #expect(ceta.instrumentModel == MetadataReading("Talos F200X", note: "unvalidated: no published reader reads it")) + #expect(ceta.instrumentModel == MetadataReading("Talos F200X", note: "no published reader reads this field; read as stored in the Velox metadata")) #expect(AcquisitionMetadata.velox(try #require(entries["ceta"]), timeZone: Self.utc, convention: .app).instrument - == MetadataReading("Talos F200X", note: "unvalidated: no published reader reads it")) + == MetadataReading("Talos F200X", note: "no published reader reads this field; read as stored in the Velox metadata")) #expect(ceta.dwellUS == nil) // an ImagingDetector's image carries the scan settings too, but no dwell let haadf = AcquisitionMetadata.velox(try #require(entries["haadf"]), timeZone: Self.utc) #expect(haadf.dwellUS?.value == 10 && haadf.magnification == MetadataReading(225000.0)) diff --git a/Tests/FormatoEMDTests/VeloxEELSAcquisitionTests.swift b/Tests/FormatoEMDTests/VeloxEELSAcquisitionTests.swift index 85da9ec..195efeb 100644 --- a/Tests/FormatoEMDTests/VeloxEELSAcquisitionTests.swift +++ b/Tests/FormatoEMDTests/VeloxEELSAcquisitionTests.swift @@ -78,7 +78,8 @@ extension VeloxEMDSerialized { #expect(a.highTensionKV?.value == Double(cube.beamVoltageV) / 1e3) #expect(a.collectionAngleMrad.map { bits($0.value) } == bits(cube.collectionAngleEndRad.value * 1e3)) #expect(a.convergenceAngleMrad.map { bits($0.value) } == bits(pins.planted.beamConvergenceRad * 1e3)) - #expect(a.convergenceAngleMrad?.note?.contains("unvalidated") == true) + #expect(a.convergenceAngleMrad?.note + == "Optics.BeamConvergence in radians × 1e3; no published reader reads this field; read as stored in the Velox metadata") } } diff --git a/Tests/FormatoMRCTests/AcquisitionMetadataMRCTests.swift b/Tests/FormatoMRCTests/AcquisitionMetadataMRCTests.swift index b2b1436..12e8b72 100644 --- a/Tests/FormatoMRCTests/AcquisitionMetadataMRCTests.swift +++ b/Tests/FormatoMRCTests/AcquisitionMetadataMRCTests.swift @@ -53,7 +53,7 @@ import FormatoMRC #expect(try AcquisitionMetadata.mrc(data: data).isEmpty) let m = try AcquisitionMetadata.mrc(data: data, convention: .app) #expect(m.highTensionKV == MetadataReading(300.0)) - #expect(m.cameraLengthMM?.value == 844 && m.cameraLengthMM?.note == "unvalidated: the mode is not checked") + #expect(m.cameraLengthMM?.value == 844 && m.cameraLengthMM?.note == "shown as stored; the instrument mode is not checked, as no published reader decodes it") #expect(m.detector?.value == "Ceta" && m.instrument?.value == "Talos F200X" && m.dwellUS?.value == 10) #expect(m.acquired?.value == "2022-12-05 13:13:07") } diff --git a/Tests/FormatoTIFFTests/AcquisitionMetadataTIFFTests.swift b/Tests/FormatoTIFFTests/AcquisitionMetadataTIFFTests.swift index 8025fe8..1ff863e 100644 --- a/Tests/FormatoTIFFTests/AcquisitionMetadataTIFFTests.swift +++ b/Tests/FormatoTIFFTests/AcquisitionMetadataTIFFTests.swift @@ -34,7 +34,7 @@ import FormatoTIFF let m = try AcquisitionMetadata.tiff(data: Self.data(name)) #expect(referenceDifferences(m, c.reference, strict: ["beam_energy", "dwell_time", "microscope", "stamp"]) == [], "\(name)") // [Detectors] Name is mapped by neither: labelled. - #expect(m.detector == MetadataReading("ETD", note: AcquisitionMetadata.unvalidatedNote)) + #expect(m.detector == MetadataReading("ETD", note: "no published reader reads this field; read as stored in the FEI header of the TIFF")) } // A stored zero is 0 (RosettaSciIO), not recorded (rule b). let zero = try AcquisitionMetadata.tiff(data: Self.data("fei-sfeg-zero")) @@ -54,8 +54,8 @@ import FormatoTIFF #expect(try AcquisitionMetadata.tiff(data: imaging, convention: .app).cameraLengthMM == nil) // The values RosettaSciIO does not map are read by the app's rules, labelled. let m = try AcquisitionMetadata.tiff(data: imaging) - #expect(m.detector == MetadataReading("BM-Ceta", note: AcquisitionMetadata.unvalidatedNote)) - #expect(m.exposureS == MetadataReading(0.5, note: AcquisitionMetadata.unvalidatedNote)) + #expect(m.detector == MetadataReading("BM-Ceta", note: "no published reader reads this field; read as stored in the Velox XML of the TIFF")) + #expect(m.exposureS == MetadataReading(0.5, note: "no published reader reads this field; read as stored in the Velox XML of the TIFF")) #expect(m.acquired?.value == "2026-06-05 13:05:07") // A zone designator is another quantity: not recorded. #expect(try AcquisitionMetadata.tiff(data: Self.data("velox-zone-designator")).acquired == nil) diff --git a/Tests/FormatoTIFFTests/TIFFAppImageTests.swift b/Tests/FormatoTIFFTests/TIFFAppImageTests.swift index a07ae5c..6a0884a 100644 --- a/Tests/FormatoTIFFTests/TIFFAppImageTests.swift +++ b/Tests/FormatoTIFFTests/TIFFAppImageTests.swift @@ -88,7 +88,10 @@ import FormatoTIFF } #expect(TIFFAppImage.Refusal.compressed(scheme: 5).reason == "its pixels are compressed (scheme 5); only uncompressed TIFF is read.") #expect(TIFFAppImage.Note.render == "8-bit render, not counts") - #expect(TIFFAppImage.Note.veloxUnvalidated == "scale unvalidated (one acquisition)") + #expect(TIFFAppImage.Note.veloxUnvalidated == "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard") + #expect(TIFFAppImage.Note.veloxStoredScale == TIFFAppImage.Note.veloxUnvalidated) + #expect(TIFFVeloxCalibration.storedScaleNote == TIFFVeloxCalibration.unvalidatedNote) + #expect(!TIFFVeloxCalibration.storedScaleNote.lowercased().contains("unvalidated")) #expect(throws: FormatoReadError.self) { try TIFFAppImage.read(path: Self.path("no-such-file")) } } diff --git a/Tests/FormatoTIFFTests/TIFFCameraPixelPitchTests.swift b/Tests/FormatoTIFFTests/TIFFCameraPixelPitchTests.swift index 051ed97..654d412 100644 --- a/Tests/FormatoTIFFTests/TIFFCameraPixelPitchTests.swift +++ b/Tests/FormatoTIFFTests/TIFFCameraPixelPitchTests.swift @@ -99,7 +99,7 @@ import FormatoTIFF let reference = try AcquisitionMetadata.tiff(data: data) #expect(reference.cameraPixelPitch?.value == Self.um14) // Not a CL signal: RosettaSciIO maps the tag for CL only (and reads no tag 65027), so `.rosettaSciIO` labels it. - #expect(reference.cameraPixelPitch?.note == AcquisitionMetadata.unvalidatedNote) + #expect(reference.cameraPixelPitch?.note == "no published reader reads this field; read as stored in the DM image tags") #expect(reference.signalNumbers["Detector.pixel_size"] == nil) let app = try AcquisitionMetadata.tiff(data: data, convention: .app) #expect(app.cameraPixelPitch?.value == Self.um14) @@ -141,7 +141,7 @@ import FormatoTIFF for convention in [AcquisitionMetadataConvention.rosettaSciIO, .app] { var expected = AcquisitionMetadata.dm(numbers: tree.numbers, strings: tree.strings, convention: convention) expected.cameraPixelPitch = convention == .app ? MetadataReading(Self.um14) - : MetadataReading(Self.um14, note: AcquisitionMetadata.unvalidatedNote) + : MetadataReading(Self.um14, note: "no published reader reads this field; read as stored in the DM image tags") #expect(try AcquisitionMetadata.tiff(data: Self.tiff(stream: stream), convention: convention) == expected) } } diff --git a/tools/acq-metadata/generate.py b/tools/acq-metadata/generate.py index 12368a2..a7fc80a 100644 --- a/tools/acq-metadata/generate.py +++ b/tools/acq-metadata/generate.py @@ -377,7 +377,39 @@ def build_harness(td): def run_harness(exe, kind, cases, td): cp = td / f'{kind}.json' cp.write_text(json.dumps(cases)) - return json.loads(subprocess.check_output([str(exe), kind, str(cp)])) + return kit_notes(kind, json.loads(subprocess.check_output([str(exe), kind, str(cp)]))) + + +# The kit words the notes as plain facts where the pinned app (APP) wrote "unvalidated": the same notes, attached to the +# same values, in the kit's wording. Applied to the app output only; no value changes. +OLD_NOTE = 'unvalidated: no published reader reads it' +KIT_NOTE = { + 'dm': 'no published reader reads this field; read as stored in the DM image tags', + 'velox': 'no published reader reads this field; read as stored in the Velox metadata', + 'mrc': 'no published reader reads this field; read as stored in the FEI extended header, at the offset mrcfile declares', + 'tiff-velox': 'no published reader reads this field; read as stored in the Velox XML of the TIFF', + 'tiff-fei': 'no published reader reads this field; read as stored in the FEI header of the TIFF', +} +KIT_PAIRS = [ + ('unvalidated: RosettaSciIO names some detectors from another field', 'read from BinaryResult.Detector; RosettaSciIO names some detectors from another field'), + ('unvalidated: the mode is not checked', 'shown as stored; the instrument mode is not checked, as no published reader decodes it'), + ('scale unvalidated (one acquisition)', 'scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard'), +] + + +def kit_notes(kind, out): + def sub(obj, pairs): + if isinstance(obj, str): + for a, b in pairs: obj = obj.replace(a, b) + return obj + if isinstance(obj, list): return [sub(x, pairs) for x in obj] + if isinstance(obj, dict): return {k: sub(v, pairs) for k, v in obj.items()} + return obj + if kind == 'tiff': # keyed by case name: the Velox XML cases, the FEI INI cases, the DM tag stream + prefix = {'velox': 'tiff-velox', 'fei': 'tiff-fei', 'dm': 'dm'} + return {n: sub(v, KIT_PAIRS + [(OLD_NOTE, KIT_NOTE[prefix[p]])] if (p := next((k for k in prefix if n.startswith(k)), None)) else KIT_PAIRS) + for n, v in out.items()} + return sub(out, KIT_PAIRS + ([(OLD_NOTE, KIT_NOTE[kind])] if kind in KIT_NOTE else [])) # ---------------------------------------------------------------------------------------------------------------- image readers From 0458d55c5681c2a517b8dfbb87c3499c4ebf1804 Mon Sep 17 00:00:00 2001 From: Paullo9 Date: Sun, 1 Nov 2026 17:10:46 +0100 Subject: [PATCH 2/2] test: re-record the acquisition and image pins with the reworded notes Reason: the readers now word their notes as plain facts instead of "unvalidated" (previous commit). The six pins files hold the pinned app output, notes included; only the note strings (and the TIFF source line that embeds the Velox scale note) change. No number, key or value moves. tools/acq-metadata/generate.py now applies the same wording, and a check of its mapping against the old pins reproduces these files exactly. Tests/Fixtures/README.md: the size column of the six files. Co-Authored-By: Claude Opus 5.5 --- Tests/Fixtures/README.md | 12 ++-- .../Fixtures/acq-metadata/pins.json | 6 +- .../Fixtures/acq-metadata/acq-pins.json | 22 +++---- .../Fixtures/acq-metadata/pins.json | 8 +-- .../Fixtures/acq-metadata/pins.json | 64 +++++++++---------- .../Fixtures/app-image/pins.json | 36 +++++------ .../Fixtures/image-readers/pins.json | 24 +++---- 7 files changed, 86 insertions(+), 86 deletions(-) diff --git a/Tests/Fixtures/README.md b/Tests/Fixtures/README.md index e6ae230..187f3f6 100644 --- a/Tests/Fixtures/README.md +++ b/Tests/Fixtures/README.md @@ -66,7 +66,7 @@ others stay in SpectroKit or the first consumer, named in the rows. | `FormatoDMTests/Fixtures/acq-metadata/eels-scanning.dm4` | 1.3 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoDMTests/Fixtures/acq-metadata/negative-voltage.dm4` | 1.2 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoDMTests/Fixtures/acq-metadata/no-microscope-group.dm4` | 1.3 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | -| `FormatoDMTests/Fixtures/acq-metadata/pins.json` | 29.7 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | +| `FormatoDMTests/Fixtures/acq-metadata/pins.json` | 29.8 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoDMTests/Fixtures/acq-metadata/sem-stage.dm4` | 1.3 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoDMTests/Fixtures/acq-metadata/sem.dm4` | 1.3 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoDMTests/Fixtures/acq-metadata/si-group.dm4` | 1.5 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | @@ -152,7 +152,7 @@ others stay in SpectroKit or the first consumer, named in the rows. | `FormatoDMTests/Fixtures/rsciio-EELS_SI.truth.json` | 2.5 KB | `tools/eels-reader/truth.py` | RosettaSciIO 049e7d70's reading of its public file; from SpectroKit 0.3.0 | | `FormatoDMTests/Fixtures/rsciio-MonarcCL_spectrum-ccd.dm4` | 316.6 KB | *copied* | third party: RosettaSciIO public test data (GPL-3.0-or-later), copied unchanged (RosettaSciIO 8363d24 `digitalmicrograph/1D/`); sha256 equal to its `registry.txt` | | `FormatoDMTests/Fixtures/rsciio-MonoCL_spectrum-ccd.dm4` | 320.1 KB | *copied* | third party: RosettaSciIO public test data (GPL-3.0-or-later), copied unchanged (RosettaSciIO 8363d24 `digitalmicrograph/1D/`); sha256 equal to its `registry.txt` | -| `FormatoEMDTests/Fixtures/acq-metadata/acq-pins.json` | 6.5 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | +| `FormatoEMDTests/Fixtures/acq-metadata/acq-pins.json` | 6.8 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoEMDTests/Fixtures/acq-metadata/velox-acquisition.emd` | 48.7 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoEMDTests/Fixtures/acq-metadata/velox-no-unit.emd` | 48.7 KB | `tools/acq-metadata/no_unit.py` | planted (from velox-acquisition.emd); pins RosettaSciIO 049e7d70 | | `FormatoEMDTests/Fixtures/acq-metadata/velox-no-unit.pin.json` | 883 B | `tools/acq-metadata/no_unit.py` | planted (from velox-acquisition.emd); pins RosettaSciIO 049e7d70 | @@ -398,7 +398,7 @@ others stay in SpectroKit or the first consumer, named in the rows. | `FormatoMRCTests/Fixtures/acq-metadata/fei2-all-set.mrc` | 2.8 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoMRCTests/Fixtures/acq-metadata/fei2-zero-and-clear-bits.mrc` | 1.9 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoMRCTests/Fixtures/acq-metadata/no-extended-header.mrc` | 1.1 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | -| `FormatoMRCTests/Fixtures/acq-metadata/pins.json` | 3.2 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | +| `FormatoMRCTests/Fixtures/acq-metadata/pins.json` | 3.5 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoMRCTests/Fixtures/image-readers/axis-order.mrc` | 1.0 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoMRCTests/Fixtures/image-readers/big-endian.mrc` | 1.0 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoMRCTests/Fixtures/image-readers/complex64.mrc` | 1.0 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | @@ -434,7 +434,7 @@ others stay in SpectroKit or the first consumer, named in the rows. | `FormatoTIFFTests/Fixtures/acq-metadata/fei-helios.tif` | 340 B | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoTIFFTests/Fixtures/acq-metadata/fei-sfeg-zero.tif` | 333 B | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoTIFFTests/Fixtures/acq-metadata/fei-stage-beam.tif` | 473 B | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | -| `FormatoTIFFTests/Fixtures/acq-metadata/pins.json` | 9.9 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | +| `FormatoTIFFTests/Fixtures/acq-metadata/pins.json` | 11.2 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoTIFFTests/Fixtures/acq-metadata/plain.tif` | 126 B | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoTIFFTests/Fixtures/acq-metadata/velox-ceta-imaging.tif` | 972 B | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoTIFFTests/Fixtures/acq-metadata/velox-diffraction-zero-voltage.tif` | 966 B | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | @@ -527,7 +527,7 @@ others stay in SpectroKit or the first consumer, named in the rows. | `FormatoTIFFTests/Fixtures/app-image/no-width.tif` | 122 B | `tools/acq-metadata/generate.py` | planted; pins the consumer's readers | | `FormatoTIFFTests/Fixtures/app-image/not-tiff-letters.tif` | 16 B | `tools/acq-metadata/generate.py` | planted; pins the consumer's readers | | `FormatoTIFFTests/Fixtures/app-image/palette.tif` | 1.6 KB | `tools/acq-metadata/generate.py` | planted; pins the consumer's readers | -| `FormatoTIFFTests/Fixtures/app-image/pins.json` | 54.2 KB | `tools/acq-metadata/generate.py` | planted; pins the consumer's readers | +| `FormatoTIFFTests/Fixtures/app-image/pins.json` | 55.3 KB | `tools/acq-metadata/generate.py` | planted; pins the consumer's readers | | `FormatoTIFFTests/Fixtures/app-image/plain.tif` | 126 B | `tools/acq-metadata/generate.py` | planted; pins the consumer's readers | | `FormatoTIFFTests/Fixtures/app-image/rgb-16bit.tif` | 158 B | `tools/acq-metadata/generate.py` | planted; pins the consumer's readers | | `FormatoTIFFTests/Fixtures/app-image/rgb-4-samples.tif` | 160 B | `tools/acq-metadata/generate.py` | planted; pins the consumer's readers | @@ -591,7 +591,7 @@ others stay in SpectroKit or the first consumer, named in the rows. | `FormatoTIFFTests/Fixtures/app-image/white-is-zero.tif` | 134 B | `tools/acq-metadata/generate.py` | planted; pins the consumer's readers | | `FormatoTIFFTests/Fixtures/app-image/wrong-magic.tif` | 134 B | `tools/acq-metadata/generate.py` | planted; pins the consumer's readers | | `FormatoTIFFTests/Fixtures/app-image/zero-height.tif` | 134 B | `tools/acq-metadata/generate.py` | planted; pins the consumer's readers | -| `FormatoTIFFTests/Fixtures/image-readers/pins.json` | 8.3 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | +| `FormatoTIFFTests/Fixtures/image-readers/pins.json` | 9.0 KB | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoTIFFTests/Fixtures/image-readers/plain.tif` | 126 B | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoTIFFTests/Fixtures/image-readers/velox-agree.tif` | 362 B | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | | `FormatoTIFFTests/Fixtures/image-readers/velox-and-fei.tif` | 523 B | `tools/acq-metadata/generate.py` | planted; pins RosettaSciIO 049e7d70 and the consumer's readers | diff --git a/Tests/FormatoDMTests/Fixtures/acq-metadata/pins.json b/Tests/FormatoDMTests/Fixtures/acq-metadata/pins.json index 3138cf3..2444968 100644 --- a/Tests/FormatoDMTests/Fixtures/acq-metadata/pins.json +++ b/Tests/FormatoDMTests/Fixtures/acq-metadata/pins.json @@ -14,7 +14,7 @@ "value": 130 }, "detector": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the DM image tags", "otherCopy": null, "value": "Orius" }, @@ -24,7 +24,7 @@ "value": 15 }, "exposureS": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the DM image tags", "otherCopy": null, "value": 0.5 }, @@ -89,7 +89,7 @@ }, "cameraLengthMM": null, "detector": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the DM image tags", "otherCopy": null, "value": "K2" }, diff --git a/Tests/FormatoEMDTests/Fixtures/acq-metadata/acq-pins.json b/Tests/FormatoEMDTests/Fixtures/acq-metadata/acq-pins.json index 15e23ae..697b3d2 100644 --- a/Tests/FormatoEMDTests/Fixtures/acq-metadata/acq-pins.json +++ b/Tests/FormatoEMDTests/Fixtures/acq-metadata/acq-pins.json @@ -12,7 +12,7 @@ }, "cameraLengthMM": null, "detector": { - "note": "unvalidated: RosettaSciIO names some detectors from another field", + "note": "read from BinaryResult.Detector; RosettaSciIO names some detectors from another field", "otherCopy": null, "value": "BM-Ceta" }, @@ -24,7 +24,7 @@ "value": 200 }, "instrument": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox metadata", "otherCopy": null, "value": "Talos F200X" }, @@ -80,12 +80,12 @@ }, "cameraLengthMM": null, "detector": { - "note": "unvalidated: RosettaSciIO names some detectors from another field", + "note": "read from BinaryResult.Detector; RosettaSciIO names some detectors from another field", "otherCopy": null, "value": "HAADF" }, "dwellUS": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox metadata", "otherCopy": null, "value": 10 }, @@ -96,7 +96,7 @@ "value": 300 }, "instrument": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox metadata", "otherCopy": null, "value": "Talos F200X" }, @@ -157,12 +157,12 @@ }, "cameraLengthMM": null, "detector": { - "note": "unvalidated: RosettaSciIO names some detectors from another field", + "note": "read from BinaryResult.Detector; RosettaSciIO names some detectors from another field", "otherCopy": null, "value": "HAADF" }, "dwellUS": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox metadata", "otherCopy": null, "value": 10 }, @@ -173,7 +173,7 @@ "value": 200 }, "instrument": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox metadata", "otherCopy": null, "value": "Talos F200X" }, @@ -229,19 +229,19 @@ }, "cameraLengthMM": null, "detector": { - "note": "unvalidated: RosettaSciIO names some detectors from another field", + "note": "read from BinaryResult.Detector; RosettaSciIO names some detectors from another field", "otherCopy": null, "value": "HAADF" }, "dwellUS": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox metadata", "otherCopy": null, "value": 10 }, "exposureS": null, "highTensionKV": null, "instrument": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox metadata", "otherCopy": null, "value": "Talos F200X" }, diff --git a/Tests/FormatoMRCTests/Fixtures/acq-metadata/pins.json b/Tests/FormatoMRCTests/Fixtures/acq-metadata/pins.json index a8e8a20..de3e0d5 100644 --- a/Tests/FormatoMRCTests/Fixtures/acq-metadata/pins.json +++ b/Tests/FormatoMRCTests/Fixtures/acq-metadata/pins.json @@ -57,7 +57,7 @@ "value": "2022-12-05 13:13:07" }, "cameraLengthMM": { - "note": "unvalidated: the mode is not checked", + "note": "shown as stored; the instrument mode is not checked, as no published reader decodes it", "otherCopy": null, "value": 844 }, @@ -72,7 +72,7 @@ "value": 10 }, "exposureS": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the FEI extended header, at the offset mrcfile declares", "otherCopy": null, "value": 0.5 }, @@ -92,7 +92,7 @@ "value": 28500 }, "mode": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the FEI extended header, at the offset mrcfile declares", "otherCopy": null, "value": "3" }, @@ -124,7 +124,7 @@ }, "magnification": null, "mode": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the FEI extended header, at the offset mrcfile declares", "otherCopy": null, "value": "3" }, diff --git a/Tests/FormatoTIFFTests/Fixtures/acq-metadata/pins.json b/Tests/FormatoTIFFTests/Fixtures/acq-metadata/pins.json index b3bcfe2..ac194eb 100644 --- a/Tests/FormatoTIFFTests/Fixtures/acq-metadata/pins.json +++ b/Tests/FormatoTIFFTests/Fixtures/acq-metadata/pins.json @@ -4,19 +4,19 @@ { "app": { "acquired": { - "note": "local time, zone not stored; unvalidated: no published reader reads it", + "note": "local time, zone not stored; no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "2026-06-05 13:05:07" }, "cameraLengthMM": null, "detector": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "BM-Ceta" }, "dwellUS": null, "exposureS": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": 0.5 }, @@ -26,17 +26,17 @@ "value": 200 }, "instrument": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "Talos F200X" }, "magnification": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": 17500 }, "mode": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "TEM" }, @@ -52,7 +52,7 @@ { "app": { "acquired": { - "note": "local time, zone not stored; unvalidated: no published reader reads it", + "note": "local time, zone not stored; no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "2026-06-05 13:05:07" }, @@ -62,25 +62,25 @@ "value": 150 }, "detector": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "BM-Ceta" }, "dwellUS": null, "exposureS": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": 0.5 }, "highTensionKV": null, "instrument": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "Talos F200X" }, "magnification": null, "mode": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "TEM" }, @@ -96,7 +96,7 @@ { "app": { "acquired": { - "note": "local time, zone not stored; unvalidated: no published reader reads it", + "note": "local time, zone not stored; no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "2026-06-05 13:05:07" }, @@ -106,13 +106,13 @@ "value": 200 }, "detector": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "BM-Ceta" }, "dwellUS": null, "exposureS": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": 0.5 }, @@ -122,17 +122,17 @@ "value": 200 }, "instrument": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "Talos F200X" }, "magnification": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": 17500 }, "mode": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "STEM" }, @@ -150,13 +150,13 @@ "acquired": null, "cameraLengthMM": null, "detector": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "BM-Ceta" }, "dwellUS": null, "exposureS": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": 0.5 }, @@ -166,17 +166,17 @@ "value": 200 }, "instrument": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "Talos F200X" }, "magnification": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": 17500 }, "mode": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "TEM" }, @@ -192,19 +192,19 @@ { "app": { "acquired": { - "note": "local time, zone not stored; unvalidated: no published reader reads it", + "note": "local time, zone not stored; no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "2026-06-05 13:05:07" }, "cameraLengthMM": null, "detector": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "BM-Ceta" }, "dwellUS": null, "exposureS": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": 0.5 }, @@ -214,17 +214,17 @@ "value": 200 }, "instrument": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "Talos F200X" }, "magnification": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": 17500 }, "mode": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the Velox XML of the TIFF", "otherCopy": null, "value": "TEM" }, @@ -251,7 +251,7 @@ }, "cameraLengthMM": null, "detector": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the FEI header of the TIFF", "otherCopy": null, "value": "ETD" }, @@ -294,7 +294,7 @@ }, "cameraLengthMM": null, "detector": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the FEI header of the TIFF", "otherCopy": null, "value": "ETD" }, @@ -344,7 +344,7 @@ }, "cameraLengthMM": null, "detector": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the FEI header of the TIFF", "otherCopy": null, "value": "ETD" }, @@ -379,7 +379,7 @@ }, "cameraLengthMM": null, "detector": { - "note": "unvalidated: no published reader reads it", + "note": "no published reader reads this field; read as stored in the FEI header of the TIFF", "otherCopy": null, "value": "ETD" }, diff --git a/Tests/FormatoTIFFTests/Fixtures/app-image/pins.json b/Tests/FormatoTIFFTests/Fixtures/app-image/pins.json index 8d0756e..aa09520 100644 --- a/Tests/FormatoTIFFTests/Fixtures/app-image/pins.json +++ b/Tests/FormatoTIFFTests/Fixtures/app-image/pins.json @@ -2749,7 +2749,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1065353216, @@ -2757,7 +2757,7 @@ 1077936128, 1082130432 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -2797,7 +2797,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1065353216, @@ -2805,7 +2805,7 @@ 1077936128, 1082130432 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -2825,7 +2825,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1065353216, @@ -2833,7 +2833,7 @@ 1077936128, 1082130432 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -2853,7 +2853,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1065353216, @@ -2861,7 +2861,7 @@ 1077936128, 1082130432 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -2881,7 +2881,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1065353216, @@ -2889,7 +2889,7 @@ 1077936128, 1082130432 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -2909,7 +2909,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1065353216, @@ -2917,7 +2917,7 @@ 1077936128, 1082130432 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": null, @@ -3013,7 +3013,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1065353216, @@ -3021,7 +3021,7 @@ 1077936128, 1082130432 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -3111,7 +3111,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1065353216, @@ -3119,7 +3119,7 @@ 1077936128, 1082130432 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -3139,7 +3139,7 @@ "app": { "height": 3, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 0, @@ -3155,7 +3155,7 @@ 1167867904, 1168891904 ], - "source": "TIFF \u00b7 uint16 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint16 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 4, "x": { diff --git a/Tests/FormatoTIFFTests/Fixtures/image-readers/pins.json b/Tests/FormatoTIFFTests/Fixtures/image-readers/pins.json index 152f33d..581c411 100644 --- a/Tests/FormatoTIFFTests/Fixtures/image-readers/pins.json +++ b/Tests/FormatoTIFFTests/Fixtures/image-readers/pins.json @@ -5,7 +5,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1, @@ -13,7 +13,7 @@ 3, 4 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -101,7 +101,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1, @@ -109,7 +109,7 @@ 3, 4 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -153,7 +153,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1, @@ -161,7 +161,7 @@ 3, 4 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -205,7 +205,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1, @@ -213,7 +213,7 @@ 3, 4 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -257,7 +257,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1, @@ -265,7 +265,7 @@ 3, 4 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": { @@ -309,7 +309,7 @@ "app": { "height": 2, "notes": [ - "scale unvalidated (one acquisition)" + "scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard" ], "pixels": [ 1, @@ -317,7 +317,7 @@ 3, 4 ], - "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale unvalidated (one acquisition)", + "source": "TIFF \u00b7 uint8 \u00b7 Velox metadata \u00b7 scale as Velox stores it (BinaryResult/PixelSize), not checked against a calibration standard", "voltage": null, "width": 2, "x": null,