OperandoMerge
Heterogeneous instruments. One reproducible experiment timeline.
OperandoMerge aligns reactor loggers, MFCs, high-frequency MS, sparse GC, XRD, Raman, FTIR, and other CSV/XLSX logs without hiding where values came from. It uses channel semantics to interpolate continuous measurements, hold stepwise setpoints causally, and keep event/discrete samples strictly discrete.
The figure is generated from the repository's real five-instrument synthetic workflow. Purple GC values exist only at 120, 300, and 480 s: the other 298 canonical rows remain missing rather than receiving invented chromatograms.
Install
Python 3.10 or newer is required. Install the published package from PyPI:
python -m pip install operandomerge
For development and the bundled source examples, use a source checkout:
git clone https://github.com/hdkim99/OperandoMerge.git
cd OperandoMerge
python -m pip install -e '.[dev]'
30-second showcase
mkdir -p showcase-output
operandomerge inspect examples/showcase/reactor_logger.csv
operandomerge merge examples/showcase/config.json \
--excel showcase-output/operandomerge-showcase.xlsx \
--plot showcase-output/alignment-cli.png
Expected CLI summary:
Merged 5 dataset(s), 301 timeline row(s); QC: 0 error(s), 0 warning(s)
The Excel report contains complete merged, metadata, provenance, qc, and
configuration sheets. To regenerate the source CSVs and showcase figures from
their deterministic equations:
python examples/showcase/generate_showcase.py --output-dir showcase-output
Launch the same workflow through the desktop UI with:
operandomerge-gui
Python's Tk bindings are included with python.org installers. Some distro or
Homebrew Python builds require their matching optional Tk package, such as
python3-tk on Debian/Ubuntu.
What is being aligned?
The showcase represents one 600 s catalyst experiment with deliberately different clocks and sampling intervals:
| Instrument | Raw sampling | Alignment evidence | Result semantics |
|---|---|---|---|
| Reactor logger | 10 s | absolute UTC experiment origin | temperature/pressure, continuous |
| MFC controller | 20 s | local event at 100 s = experiment event at 120 s | H₂/Ar flow, stepwise |
| MS | 2 s | known 8 s transport delay | m/z 44/28, continuous |
| GC | three injections | 12 s sampling + 18 s analysis delay | compositions, discrete samples |
| XRD | 60 s | −5 s clock offset + 15 s analysis delay | phase stepwise; lattice discrete |
The raw clocks and applied corrections remain in metadata/provenance. See the showcase definition for hand-checkable invariants.
Scientific rules
The canonical coordinate is experiment_time_s:
experiment_time_s = source_time_s + alignment_offset_s - total_delay_s
total_delay_s = manual + sampling + transport + dead_volume + analysis
A positive delay means a reported value corresponds to an earlier physical event,
so it is subtracted. Reference-event alignment uses
target_event_time_s - source_event_time_s. Absolute timestamps use an explicit
ISO-8601 experiment origin when provided; otherwise the earliest absolute record
becomes zero.
| Channel semantic | Available policy | Scientific constraint |
|---|---|---|
continuous |
linear, nearest, none | bounded by measured range; no extrapolation |
stepwise |
previous, none | causal hold; never takes a future setpoint |
event |
exact timestamp only | never interpolated |
discrete_sample |
exact timestamp only | never interpolated |
For every emitted value, provenance identifies the source file, column, row, original timestamp, offset, delay, and interpolation method. Linear values retain both bracketing source rows/timestamps.
GUI and Python API
The GUI workflow is: add files → map clocks/channels → assign channel semantics → enter offsets/delays/events → choose the timeline → preview → inspect values/QC → export. Controls are converted to the same configuration models used by the CLI; the GUI contains no independent scientific formulas.
from pathlib import Path
from operandomerge.config import load_config
from operandomerge.export import export_excel
from operandomerge.service import MergeService
datasets, policy = load_config(Path("examples/showcase/config.json"))
result = MergeService().run(datasets, policy)
export_excel(result, Path("operandomerge-showcase.xlsx"))
Supported, experimental, planned
Supported in 0.1.3:
- multiple CSV/XLSX inputs and one selected worksheet per dataset;
- absolute/injection timestamps, elapsed seconds/minutes, and midnight-wrapping instrument-local clocks;
- absolute, elapsed, manual-offset, and reference-event alignment;
- explicit manual/sampling/transport/dead-volume/analysis delays;
- union or named-reference timeline, type-aware merging, QC, provenance, figures, CSV bundle, Excel, CLI, Tk GUI, and public Python API; and
- Python 3.10+ packaging with scientific/unit/integration/showcase regressions.
Experimental:
- automatic GUI time-column guesses, which must be reviewed;
- robust-MAD possible-outlier warnings; and
- the interchange draft, which documents concepts but is not a stable cross-project contract.
Planned, not implemented:
- cross-correlation alignment. It will not be added until candidate offsets have quantitative confidence, multi-channel agreement, a visual approval step, and complete provenance;
- vendor-native binary adapters;
- automatic dead-volume calculation from apparatus geometry; and
- configurable regular target grids.
Assumptions and limitations
- OperandoMerge cannot prove that two clock events represent the same physical event. Users must justify every offset and delay.
- Absolute and injection timestamps require an explicit ISO-8601 timezone offset.
Unzoned instrument clocks must use
instrument_local_timeor a documented elapsed/reference-event workflow; OperandoMerge never guesses UTC. - Signal units are preserved as source metadata/names but are not converted or dimensionally validated in this release.
- Numeric channels are required for resampling. Categorical phase labels should be encoded as documented numeric states or retained outside the merged value table.
- On a named reference timeline, off-grid event/discrete measurements remain absent rather than being snapped or interpolated.
- Duplicate times are reported by QC; numeric merging deterministically uses the final row at that time while raw files remain untouched.
- GUI tables preview up to 500 rows; exports always contain the complete result.
- Synthetic curves demonstrate synchronization behavior, not validated reactor kinetics, mass balances, or diffraction physics.
Validation details are in scientific validation and the public-data source register, and every JSON setting is described in the configuration reference.
Related tools
These are independent repositories. Direct interoperability is planned, not currently claimed:
- Ordifile — chromatographic file conversion
- ReactorCheck — catalytic reactor calculation and QC
- TPxLab — temperature-programmed characterization analysis
Development and citation
ruff check .
mypy src
pytest
python -m build
Contributions are welcome under CONTRIBUTING.md. Cite the software using CITATION.cff. The project is MIT-licensed; the dependency license review records compatibility.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file operandomerge-0.1.3.tar.gz.
File metadata
- Download URL: operandomerge-0.1.3.tar.gz
- Upload date:
- Size: 293.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d40e07b60fbd21cd361c9a2fe6e35f76b374f798baa8d8f078d583cffc8c46c
|
|
| MD5 |
55cbabf899c264c657f7b0afa2858a99
|
|
| BLAKE2b-256 |
c1034d048ec418e4e17029a72b336cc480aff6f81c80c3f4a8a788d154609e71
|
Provenance
The following attestation bundles were made for operandomerge-0.1.3.tar.gz:
Publisher:
release.yml on hdkim99/OperandoMerge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
operandomerge-0.1.3.tar.gz -
Subject digest:
8d40e07b60fbd21cd361c9a2fe6e35f76b374f798baa8d8f078d583cffc8c46c - Sigstore transparency entry: 2569631286
- Sigstore integration time:
-
Permalink:
hdkim99/OperandoMerge@630b3769ff74017a9564fae048268a3f17da5604 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/hdkim99
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@630b3769ff74017a9564fae048268a3f17da5604 -
Trigger Event:
release
-
Statement type:
File details
Details for the file operandomerge-0.1.3-py3-none-any.whl.
File metadata
- Download URL: operandomerge-0.1.3-py3-none-any.whl
- Upload date:
- Size: 26.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f1d6ca9da2b5f4c26a1829059db224b576b729d34bd337432491c0ac2ddce2c
|
|
| MD5 |
0a6dfb97ec12d7ac9335fd063da58093
|
|
| BLAKE2b-256 |
9ff11e7720e60b9d53d98b96694e480e71d6d6471dc3a19ebea9058cc26ea4f9
|
Provenance
The following attestation bundles were made for operandomerge-0.1.3-py3-none-any.whl:
Publisher:
release.yml on hdkim99/OperandoMerge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
operandomerge-0.1.3-py3-none-any.whl -
Subject digest:
4f1d6ca9da2b5f4c26a1829059db224b576b729d34bd337432491c0ac2ddce2c - Sigstore transparency entry: 2569631312
- Sigstore integration time:
-
Permalink:
hdkim99/OperandoMerge@630b3769ff74017a9564fae048268a3f17da5604 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/hdkim99
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@630b3769ff74017a9564fae048268a3f17da5604 -
Trigger Event:
release
-
Statement type: