Remove the efmtool / Java compression backend - #72
Merged
Conversation
…oupling The Python `sparse_rref` compressor is the default, the tested path, and the one every correctness gate runs. The legacy Java backend was strictly worse: it does not normalize lumped-reaction scales, so a bound stated on a lumped reaction is read in the lump's units -- the mechanism behind the 4484x biomass trap on iML1515. It also needed a JVM plus jpype1, and its tests could only run on the Windows CI leg because JPype's JNI bridge segfaults non-deterministically on Linux/macOS (jpype#934). Removed: - `straindesign/efmtool.jar` (2.2 MB) and `straindesign/efmtool_cmp_interface.py` - eager JVM startup from `straindesign/__init__.py`, which ran on *every* import - the `compression_backend` parameter, now single-valued, from `compress_model`, `compress_model_coupled` and `compute_strain_designs` - `compress_model_efmtool`, the backward-compat alias named after the backend - `suppressed_reactions` from `compress_model_coupled`: it was documented as "Java backend only ... ignored for the Python backend" and was in fact unused - the `[java]` extra and the jar from `package-data` in `pyproject.toml` - Java setup and jpype1 install steps from the CI matrix - `docs/source/legacy_methods.rst`, developer's guide section 3.11 (196 lines), and the JPype/JVM notes scattered through the guide, README, index and the compression notebook Tests: dropped the four Java parity tests, the `jpype_available` fixture, the `java` marker and its platform skip, `--java`, and `TestEfmtoolBackendGpr`. Two were kept by converting rather than deleting them: `test_basic_columns_rat_python` now calls `compression.basic_columns_from_numpy` directly (the deleted function was a thin shim over it), and the backend-parity FBA test becomes `test_fba_optimum_recovered_through_map`, asserting that the compressed optimum recovers the uncompressed one through the compression map. That is the part of the old test that was actually about correctness rather than about having two backends, and it still exercises the map factors. Kept deliberately: the EFMTool citation in README and index.rst. The compression approach follows Terzer & Stelling; only the bundled implementation is gone. Note the jar carried its own Simplified BSD licence (and a vendored JMatIO) that the repository never reproduced, so removing it also closes that gap. Verified: no `efmtool`/`jpype`/`java` reference remains outside those two citations; jpype is not imported on `import straindesign`; the wheel drops from 3.08 MB to 0.70 MB; e_coli_core gene-MCS is 455, set-identical to the canonical reference. Co-Authored-By: Claude <noreply@anthropic.com>
Follow-up to the efmtool removal. None of this was orphaned *by* that removal -- the Java module was self-contained, importing only `basic_columns_from_numpy` from the package -- but the sweep for stale leftovers surfaced pre-existing dead code. Removed five functions with no caller anywhere in the package or the tests: - `networktools.modules_coeff2float` -- the float counterpart of `modules_coeff_to_fraction`, which is used; this one never was - `lptools.remove_redundant_bounds` - `parse_constr.lineq2mat`, `lineqlist2str`, `get_rids` These modules define no `__all__`, so `straindesign/__init__.py`'s star imports made all five importable as `straindesign.<name>`. Removing them is therefore a public API change, even though nothing in the project used them. Also dropped `sparse_nullspace as nullspace` from the package namespace. It shadowed `compression.nullspace`, a different function taking a `RationalMatrix`, so `straindesign.nullspace` and `straindesign.compression.nullspace` silently disagreed. `sparse_nullspace` remains exported under its own name, and `compression.nullspace` is untouched for internal callers. Design-identical: e_coli_core gene-MCS 455, set-identical to the canonical reference. Co-Authored-By: Claude <noreply@anthropic.com>
VonAlphaBisZulu
added a commit
that referenced
this pull request
Jul 26, 2026
The hardcoded list of names CNApy imports goes stale the moment CNApy imports something new, and nothing in this repository can notice: a downstream consumer is invisible to grep here. So read CNApy instead of installing it. The test fetches its source, walks the AST for every `from straindesign ... import`, and asserts each name is still exported. Installing CNApy was the obvious alternative and is a bad trade: it depends on Qt and PyQtWebEngine, on cplex, which this matrix already cannot install on macOS or 3.13, and on jpype, which is the JVM binding removed in #72 and the reason those tests were Windows-only. That would drag all of it back into twenty jobs to test one import list. It is marked `downstream` and skipped unless --downstream is passed, following the existing --medium and --large convention, and the workflow passes the flag only on the quarterly schedule. It needs network and tracks a branch we do not control, so it reports drift rather than gating pull requests. The static list stays. It runs everywhere, offline and unconditionally, and it is the layer that would have blocked the removal in the first place. Verified against ffad74b, before the restore: the AST check fails there, as do both static guards. A test that cannot fail is decoration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Remove the efmtool / Java compression backend
The pure-Python
sparse_rrefcompressor is the default, the tested path, and the oneevery correctness gate runs. The legacy Java backend was strictly worse: it does not
normalize lumped-reaction scales, so a bound stated on a lumped reaction is read in the
lump's units — the mechanism behind the 4484× biomass trap on iML1515. It also needed a
JVM plus
jpype1, and its tests could only run on the Windows CI leg because JPype's JNIbridge segfaults non-deterministically on Linux/macOS (jpype#934).
This branch removes the backend thoroughly and surgically — code, tests, docs, packaging,
and CI — leaving the Python compressor as the single path.
Results
jpypeonimport straindesignCI-test)Design-neutral at genome scale; the removed backend was never the tested path.
compression_backendparameter removed fromcompress_model,compress_model_coupled,and
compute_strain_designs(was single-valued after this change).compress_model_efmtoolremoved — the backward-compat alias named after the backend.compress_model_coupled(suppressed_reactions=...)removed — documented as "Java backendonly … ignored for the Python backend", and in fact unused.
straindesign.nullspacealias removed. It shadowedcompression.nullspace(a differentfunction taking a
RationalMatrix), so the two silently disagreed.sparse_nullspaceremainsexported under its own name;
compression.nullspaceis untouched.via star imports):
modules_coeff2float,remove_redundant_bounds,lineq2mat,lineqlist2str,get_rids.[java]extra and the bundledefmtool.jarare gone;jpype1is no longera dependency.
What was kept
index.rst. The compression routine follows theconcept of efmtool's compression, reimplemented in pure Python with exact rational
arithmetic — concept credited, no code implied.
test_basic_columns_rat_pythonnow calls
compression.basic_columns_from_numpydirectly, and the backend-parity FBA testbecomes
test_fba_optimum_recovered_through_map— the part of the old test that was aboutcorrectness rather than about having two backends.
Suggested version bump
Given the four breaking API removals, this warrants at least a minor bump (or major, per the
project's SemVer policy).
🤖 Generated with Claude Code