OncoLens

A PyQt desktop application that fits a growth–death ODE to serial RECIST lesion measurements and plots the resulting tumour trajectory against a treatment timeline for Moffitt’s Evolutionary Tumor Board — working mathematical oncology, and the first repository read into this wiki with nothing to do with pathology.

Purpose

Verdict: out of domain. Nothing to adopt, nothing to borrow, and no page in this wiki has an open question it touches. It is recorded anyway for one reason: neither the repository name nor its GitHub description — “a modeling and visualization application tool used for biological data research, analysis and prediction” — says what it actually is, and finding out cost a read of 21,000 lines. This page exists so that nobody spends that again.

What it actually is: a desktop tool for the Evolutionary Tumor Board, Moffitt’s forum for discussing individual patients’ tumour dynamics. You give it one Excel workbook of lesion measurements and treatment date ranges; it fits a growth–death model, reconstructs the patient’s history as a curve, projects it forward a short way, and draws that against the treatments. The unit of analysis is a lesion volume over time, which comes from radiology. There is no slide, no image, no report text and no morphology anywhere in it.

The decisive question for a third-party tool here is what it does that the indexed stack does not. The honest answer is that the question does not apply — QuPath Tooling is the index for WSI and QuPath work and OncoLens is not in that category at all. It was deliberately not added to that index, because putting a radiology-timeline modelling app in the slide-tooling hub would make the hub worse at the one job it has.

Data used

None committed — verified across all seven commits including deleted paths, so no CSV, workbook, database dump or patient record has ever been in this repository. The only tracked JSON is the app’s own settings and three GUI colour themes.

What it expects is one Excel workbook with four sheets: dates of interest, historical treatments with on/off dates, available treatments, and per-lesion RECIST scan measurements. The core modelling path needs no patient name or identifier. A newer, partly built “abstract visualiser” path does look for them — it scans incoming columns for names matching MRN, patient, name, date of birth, SSN and identifier — which tells you what its authors expect real input workbooks to contain.

Methods

Read at source level on 2026-08-01 from a full clone. Every substantive claim below was independently re-checked by a reviewer instructed only to refute it; two were corrected and both corrections are recorded in place.

The modelling is real, and it is not where the repository’s own structure says it is

src/core/processing/etb_modeling.py (1,427 lines) defines the growth–death right-hand side and integrates it with scipy.integrate.odeint, handling treatment segments, per-lesion volumes, non-systemic lesions and min/average/max parameter sweeps. It is reachable from the interface through a worker thread. The README’s claim that this workflow is operational is true.

A correction I nearly published. The first file I opened was src/core/models/gdrs_model.py, whose predict() is a bare pass and whose preprocess_data() only drops missing rows, sitting under an abstract base class with two unimplemented methods. Read alone, that says the headline feature is a stub and the README is false. It is not: src/core/models/ is an unwired refactor target for the “multi-model” expansion the README calls partly implemented, and the engine is elsewhere. The class is imported at start-up and never instantiated. This is the same failure the schema warns about — a partial read that felt sufficient — arriving from the opposite direction than usual, since here it would have produced a harsher verdict than the code deserves.

What is fair to say about the README instead is narrower and stranger: its Project Structure section names base_model.py and gdrs_model.py — the two stubs — and omits etb_modeling.py entirely, so it advertises the scaffolding and hides the engine. That tree is also rooted at a directory called digital-twin-pipeline/ rather than OncoLens, which is the same phantom root as the README on Valis-GUI’s valis-test branch — same author, both written on 2026-01-23. Two repositories documented from one template on the same afternoon.

A second copy of the ODE lives in src/core/processing/excel_etb.py: the same mathematics with renamed local variables, integrated separately, unreferenced by anything, and expecting different sheet names than the live path validates. Dead code that contradicts the schema next to it.

A live database credential, wired to a button

src/gui/views/windows/functions_main_window.py contains a method that opens a MySQL connection with a hardcoded root account and password against a named tumour database, runs select * from Tumors;, and prints the rows into a text box. This is not commented out and not example text in a docstring: it is live code, connected to a visible button on the application’s home page. The same password appears again in a commented block at the end of src/core/processing/mysql_connector.py.

It arrived in the repository’s first commit — a commit whose message describes it as a test of the repository connection — and has never been removed, so deleting the line would not undo it. Rotation is the only remedy. The host is localhost, so this is a developer’s own machine rather than a server anyone else can reach; the exposure is the reuse of a personal-looking password in a public repository, not access to a running database.

The value itself is deliberately not reproduced on this page. It is in the repository for anyone who needs it, and copying a live credential onto a published site to illustrate a point about credentials would be a poor trade.

This is the third instance of the same class recorded here and the first from outside the groupimagebank commits an API key, LOP commits publisher tokens, and both of those are private repositories where the problem is governance. This one is public, which is the difference that matters, and it is a useful corrective to reading the estate’s own record as a local failing.

Two smaller things

The PHI masking is cosmetic. The table widget substitutes mask characters at render time while the underlying dataframe keeps the real values, and a reveal toggle turns the masking off. That is a display convenience being carried as if it were a control — see De-identification.

Nothing leaves the machine. There is no HTTP client, socket, mail or cloud SDK anywhere in the tree; the only writes are local settings files and the only network call is the localhost database above.

Current state / open questions

  • Is there any question in this group this would serve? None found. It would need longitudinal lesion volumes and treatment date ranges, which is radiology data this department does not hold in that form. If that ever changes the tool is MIT and readable, and etb_modeling.py is the file to open.
  • The repository disagrees with itself about what it is: setup.py packages it as IMO-modeling version 1.0.0, settings.json calls it OncoLens v1.3.0 with a copyright year of 2021, the MIT licence is dated 2025, and the first commit is 2025-01-21. None of this matters for a tool nobody here will run; it is recorded because a version string is the kind of thing a later reader would otherwise quote.
  • Zero tests, for software that produces forward projections of tumour burden used in a clinical discussion forum. Not this wiki’s problem, and worth noting beside the VALIS entry, where the maintainers’ own regression thresholds were the most informative thing on the page.

How it connects

Valis-GUI — same author, the same PyQt scaffold down to the settings file and window chrome, and the same README template written the same day. Reading the two together is what turns “an unfinished GUI” into a recognisable house style, which is the only reason this page links there.

De-identification — the display-only masking with a reveal toggle is an outside worked example of that page’s argument: a control that changes what is rendered while leaving the values in place is not a control, and nothing in the code asserts otherwise.

Survival Analysis Workflow — the contrast worth noticing rather than a dependency. Everything this wiki does with time is statistical: fit a hazard, compare groups, report a concordance. This fits a mechanistic growth–death ODE to one patient’s own measurements and projects that individual forward. Neither replaces the other and this group has no use for the second, but the distinction is worth having met once.

Derived from: repository cloned at full depth 2026-08-01 (f911945, 7 commits, single branch, no tags); README.md, LICENSE, setup.py, package.py, settings.json, main.py, src/core/models/base_model.py and gdrs_model.py, src/core/processing/etb_modeling.py, excel_etb.py, mysql_connector.py, prediction_sampling.py, src/core/validation/data_keywords.py, src/gui/views/windows/functions_main_window.py and setup_main_window.py read directly; commit history and the credential’s provenance traced with git log -S. Currency computed from the clone’s own git history — the GitHub API was unreachable from this session, so star, fork and open-issue counts were not obtained.

Reuse

MIT (LICENSE file and README agree; setup.py declares no licence)