Skip to content

Releases: katalystnord/plottracer

v1.5.1

Choose a tag to compare

@github-actions github-actions released this 28 Jul 18:01

PlotTracer 1.5.1

One fix: a curve fit through a flat series reported R² = 1.00000 — a
perfect score for a model that explained nothing.

Why it happened

R² is 1 − SSres/SStot, where SStot is how much the data varies about its own
mean — how much there was to explain in the first place. When every value in a
series is the same, SStot is exactly zero: every point is the mean. The ratio
divides by zero, and R² has no value at all.

The code returned 1 in that case. That was not a rounding artifact — the
residual never entered the calculation, so the 1 would have been identical had
the fit been wildly wrong. It was a written-in default standing where the formula
has no answer.

What it looked like

Fitting a horizontal baseline — an ordinary thing to trace: a control series that
doesn't move, a saturated plateau — printed R² = 1.00000 on the Curve fit card,
and wrote 1 into the R2 column of every export. On a nonlinear model it could
appear directly beside the red "this fit did not settle", which is a contradiction
the app should never show.

What it does now

R² is reported as absent when the series has no variation:

  • the card shows R² = — and says why: R² needs variation to measure against, and
    every value in this series is the same
  • the R2 column exports a blank cell, never a fabricated number — the same
    rule PlotTracer already applies to any value that was not measured
  • JSON omits rSquared rather than nulling it, matching the schema's
    convention that an absent field means the thing does not apply

RMS is unaffected and is the number to read there. It needs no reference
variance, it is in the data's own units, and it was honest all along.

Unchanged on purpose: a negative R² on a genuinely poor nonlinear fit is
correct and still reported — for a nonlinear model R² is not a proportion of
explained variance and is not bounded below by zero. Only the zero-variance case
became absent.

Downloads

Installers for Linux (.AppImage, .deb), macOS (Apple Silicon .dmg) and
Windows (.exe) are attached below.

These builds are unsigned. macOS will need Right-click → Open the first time,
and Windows will show a SmartScreen warning — choose More info → Run anyway.

Full Changelog: v1.5.0...v1.5.1

v1.5.0

Choose a tag to compare

@github-actions github-actions released this 28 Jul 17:22

PlotTracer 1.5.0

Opens other digitizers' projects, fits shapes rather than only polynomials, and
says what an export will leave behind before you choose the format.

Opens other digitizers' projects

One Open Project command now reads projects written by WebPlotDigitizer,
Engauge Digitizer and StarryDigitizer, alongside PlotTracer's own. There
is no per-tool menu item and no per-tool file filter: the format is recognised by
what is inside the file, not by its extension, so a renamed file still opens.

Anything that cannot be read faithfully is refused with a reason — the old
binary Engauge format, an unsupported coordinate system, a calibration the file
does not actually contain. A partial import that looked complete would be worse
than no import at all.

When a project holds more than PlotTracer can open at once — an Engauge document
containing several coordinate systems is several figures — the first is opened and
the app says what it did not bring.

Fit a shape, not just a polynomial

Curve fitting adds five nonlinear models beside the polynomial:

Model Form
Exponential y = a·e^(b·x)
Power y = a·x^b
Logarithmic y = a + b·ln(x)
Gaussian y = a·e^(−(x−b)²/2c²)
Logistic y = a / (1 + e^(−b(x−c)))

Each option spells out its own equation, so the choice is readable without prior
knowledge. Degree belongs to the polynomial and disappears for the others. A
model that cannot take your data is refused by naming the requirement it needs
rather than returning a number it cannot stand behind, and Restrict fits over
a chosen x range.

A fit that did not settle now says so in the file, not just on screen. These
models are solved iteratively, and a solver that runs out of iterations still
returns something. The card has always shown that in red; the export did not carry
it, so a settled fit and an abandoned one were indistinguishable to whoever opened
the file. The Curve fit block gained a settled column, and the sampled
curve block says (did not settle) in its title — that block is built to be
lifted out on its own.

Exports say what they cannot carry

Choosing an export format now shows what that format will leave behind before
you pick it. No data format carries the figure image, the axis calibration or the
source document — save a project to keep those — and formats name their own limits
(MATLAB becomes a cell array once any cell holds text; flat text formats put every
block into one stream).

Fixes

  • A number is never a date. dateConversion.parse applied its "must contain a
    separator" guard only to strings, so a bare number between 0 and 23 was read as
    an hour of today and ordinary axis values became timestamps around 1.78e12. Only
    0–23 were affected, which is why 100 behaved and 10 did not. Fixed in the model,
    so every entrance — interactive, project load, and every import filter — gets the
    same answer.
  • Engauge angles in gradians or turns were read as radians: a point whose true
    angle was 0° exported as 49.21 or 5.62. All four of the format's angle units are
    now read correctly, and an unrecognised unit is refused by name.
  • A multi-figure Engauge document was reduced to its first, silently. The
    disclosure was keyed on an element that does not exist in the format, so it could
    never appear. On real files this dropped most of the recorded points without a
    word.
  • StarryDigitizer projects with no tilt setting were rotation-corrected anyway,
    the opposite of that tool's own default.
  • The import notice no longer outlives the figure it describes.
  • The Curve fit export gained a model column, and no longer reports a
    degree for models that have none — it was the leftover value of a hidden control.
  • The PNG snapshot is separated from the data formats, so the note about what those
    formats cannot carry no longer reads as though it covered the one export that
    carries exactly that.

Also

OpenDocument (.ods) export. Saved projects record which build wrote them.

Downloads

Installers for Linux (.AppImage, .deb), macOS (Apple Silicon .dmg) and
Windows (.exe) are attached below.

These builds are unsigned. macOS will need Right-click → Open the first time,
and Windows will show a SmartScreen warning — choose More info → Run anyway.

Full Changelog: v1.4.0...v1.5.0

v1.4.0

Choose a tag to compare

@github-actions github-actions released this 27 Jul 19:02

Full Changelog: v1.3.0...v1.4.0

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 26 Jul 10:17

Your exported data says which points you placed and which the app filled in

PlotTracer's whole claim is that a record tells you where its numbers came from.
That held inside the project file, but not once you handed the data to anyone
else: an interpolated spline sample left a CSV byte-identical to a point you had
judged by eye off the figure.

Now every text export (CSV, TSV, LaTeX, MATLAB, Python, R) and XLSX carries a
role column — anchor for a point you assigned, interpolated for one the
app filled in between, and blank for an ordinary traced point. It appears
only for a series that actually has roles, so a plain trace exports exactly as
it did before, byte for byte.

On screen, derived rows are now visibly derived: muted italic cells, read-only,
with a legend under the table saying what the italics mean. Typing into a derived
cell used to appear to work and then be silently wiped on the next rebuild.

Category names on bar and categorical-line figures

A bar chart's independent variable is a name you read off the tick labels —
the one thing on that axis the pixels cannot tell you. There was nowhere to put
it: bar exports had a Label column nothing in the app could write, so it always
said Bar0, and a categorical line exported a bare ordinal with no name at all.

The right-hand table gains a Category column you can type into, and the names
ride out with the data. On a grouped chart you type the category set once: a
point added to the next series takes the name of the nearest already-named bar,
so it lands on the right category however you click and whatever you skip. Each
name belongs to its own point, so any cell can be retyped without shifting its
neighbours — and where the app can't tell which category you meant, it leaves the
cell blank rather than guess.

One breaking change to note

A bar chart's category column is now called Category in exported files. It was
Label — a word inherited from WebPlotDigitizer that no other part of PlotTracer
used: the on-screen table, the box-plot category field and the new categorical
export all said Category. Now everything does.

The column's position and contents are unchanged, so anything reading the file by
column number is unaffected. If you have a script that looks up the column by
name, change Label to Category.

Two silent wrong-number bugs fixed

Both produced plausible numbers with nothing on screen to say they were wrong.
If you have traced a bar chart or captured error bars with an earlier version,
these are worth knowing about.

  • Auto-extract on a bar chart recorded each bar's MIDPOINT — roughly half the
    true value whenever the baseline is the axis zero, and wrong in general
    otherwise. Colour tracing and blob detection both centre on a filled shape,
    which is right for a curve and wrong for a bar, whose value is its top edge.
    Auto-extract is now refused for the whole bar family at both doors — the
    rail button and the 4 shortcut — with the reason on hover. Nothing correct is
    lost: none of those mechanisms could produce a valid bar value. A proper
    interval-native bar model is the next release's headline work. On a bar figure
    the guidance now also tells you where to aim — "click the end of each bar,
    never its middle" — because on a bar chart the height of your click is the
    number, and the old line said "click anywhere on the image".
  • Capturing an error cap dragged its own data point along with it. The
    gesture starts by pressing the datum the cap hangs off, and that one press did
    both jobs: it recorded the cap and hauled the datum to wherever the drag
    ended — which is, by definition, the cap. It then looked like a mis-aimed click
    in the table rather than a bug. Data markers are now inert while the Error-bars
    tool is active, exactly as they already were for Measure; the cap is still
    recorded, and the point stays where you put it.

Fixes

  • The Error-bars tool explains itself. It was the only tool with no guidance
    of its own, so on a calibrated chart the tips bar fell through to "Pick a graph
    type, then calibrate the axes to begin" — next to a Calibrated ✓ chip. It now
    describes the drag, and tells you to place the data points first if the active
    series is still empty.
  • The derived-row legend is actually visible. It sat inside the table's own
    scroll container, so it scrolled out of sight on any table longer than about
    180 rows — precisely the tables where you need it.
  • The empty-table hint no longer contradicts the tips bar. One said "click on
    the image to add data points" while the other said a plain click does nothing;
    both were on screen at the same time. On a bar figure it also no longer points
    you at the Auto-extract tool that's greyed out there.
  • An interpolated point can't be moved by any route. Derived rows were already
    read-only to typing; selecting one and using the arrow keys could still shift it,
    and the move was then silently discarded on the next rebuild.
  • The Error-bars card and tips bar name how to adjust a cap, and say plainly
    that the lower cap starts out mirrored through your data point rather than
    measured — move it to where the figure actually draws it.
  • Corrected tool numbers. The first tip on a fresh figure pointed at the wrong
    rail slot for rotate/crop/deskew, and the manual listed three tools under their
    pre-v1.0.2 numbers — including sending you to the image editor for Select.
  • The Trace Challenge briefing no longer promises auto-tracing on the bar,
    box-plot and histogram rounds, where it's deliberately refused.

Downloads

Linux .AppImage / .deb, Windows .exe, macOS .dmg / .zip (Apple Silicon).
Builds are unsigned — your OS will ask you to confirm on first launch.


Full Changelog: v1.2.0...v1.3.0

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 24 Jul 21:09

The Trace Challenge

PlotTracer ships 14 example figures. Seven of them now come with the real
numbers behind the plot
committed alongside the image — so the app can tell you
exactly how close your extraction landed.

Help ▸ Examples ▸ Take The Trace Challenge starts a timed game: five rounds
drawn at random from the seven, each pre-calibrated so you go straight to
tracing. Extract the curve, press Done, and the round is scored against the
ground truth. The score is a single number — time — because accuracy errors
are charged as added seconds. Rushing sloppily just trades placement time for
penalty time; the fun is finding the sweet spot.

  • Use whatever tools you like. By-colour, Flood-fill, Guide points, manual
    placement — the clock and the error penalty are the challenge, not an
    artificial restriction.
  • The true answer is drawn on your figure after each round, next to a
    breakdown of where your seconds went.
  • Five scoring families, each judged on its own terms: continuous curves
    (scored against the interpolated truth, no penalty for using more or fewer
    points), scatter (one-to-one nearest matching, with misses and extras counted),
    histograms, bar charts, and box plots (compared as five-number summaries).
  • Local high-score table — name, date, time — kept on your machine.

It doubles as an honest accuracy check: if you want to know how much to trust a
digitizer before you trust it with your data, measure it against figures whose
values are known.

Also new

  • Auto-extract ▸ By colour: drag a box directly on the image to limit the
    trace to a region. No toggle first — the same gesture as the Select tool's
    marquee.
  • Date axes read as dates in the table. A date-calibrated column showed a raw
    serial number on screen while the CSV export already wrote a real date; the
    table now uses the same formatter as the export.

Fixes

  • The zoom loupe stays usable near the floating cards — it now paints above
    them instead of behind, and hides while your cursor is over a card rather than
    jumping to the middle of the plot.
  • Clicks no longer get eaten under the Auto-extract card. In Guide-points and
    Flood-fill modes you place points by clicking the curve; a click landing under
    the card's footprint silently did nothing. The card is click-through now,
    except on its own controls.
  • "+ Add series" keeps the tracing tool you were using. Tracing a multi-curve
    figure no longer dumps you back to place-point on every added series.
  • Tall fold-out cards scroll instead of spilling off a short window
    (Measure, Image, Error bars).
  • The Select sub-mode strip closes when you click away from it.
  • Geometry no longer leaks between series when switching or adding one.
  • Smoother clicking during a timed round — the game clock used to re-render
    the whole workspace ten times a second, which made canvas clicks feel dropped.

Packaging

The Electron entry files are now globbed rather than listed by hand, so a newly
added one can't be silently left out of the installer.

Downloads

Linux .AppImage / .deb, Windows .exe, macOS .dmg / .zip (Apple Silicon).
Builds are unsigned — your OS will ask you to confirm on first launch.


Full Changelog: v1.1.0...v1.2.0

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 23 Jul 20:45

The tool rail, redesigned

Every tool that folds out a card — Select, Measure, Curve Fit, Geometry,
Auto-extract, Image edit, Error bars — now works the same way, and that way is
simpler than before.

Fold-outs are inputs only. A tool card holds the controls you act with and
nothing else: one compact row of icons or fields. Measure is Distance / Angle /
Area / Slope / Set-scale. Curve Fit is Degree · Restrict · Fit · Clear. Geometry
is ☐ Closed curve · Compute · Clear.

Results live in one place. Everything a tool produces — recorded
measurements, the fit equation with R² and RMS, the geometry summary — now
appears in the right-hand panel, bound to the series it belongs to, next to that
series' data. Nothing is buried in a popup you have to keep open to read.

Cards appear where you clicked. A fold-out is anchored to its own button and
vertically centred on it, then clamped so a card for a low button can't run off
the bottom of the window. Opening a fly-out closes any other open card, so two
never stack.

Every fold-out button says so. Rail buttons that open a card carry a small
fold-out arrow in the lower-right corner (the digit hotkey badge moved to the
upper-left to make room) — following Ketcher's design language.

Outputs that stay true

Measurements, curve fits and geometry are all derived from your current
points
, so editing the series updates them with no re-run. If an edit makes a
result impossible — deleting points until a curve can't be measured — the panel
says so and the tips bar raises a callout, rather than leaving a stale number on
screen.

They also draw on the figure and export as their own labelled blocks,
never mixed into the recorded data. Geometry draws the path it measured, shades
the enclosed area when Closed, and rings the point of maximum curvature — so the
numbers have something visible to refer to.

Geometry is now saved with your project. It used to be a throwaway popup.

New tools and gestures

  • Select is a multi-tool: Rectangle (click a point or drag a box), Lasso
    (drag a freeform loop), Whole series (click any point, get all of them), and
    Point. The rail button shows the active mode; click it again to pick another.
    All four select data points only — never your calibration handles.
  • Measure snaps to your points. A measurement vertex lands exactly on a data
    point within reach of the cursor, data markers no longer swallow the click, and
    a dashed rubber-band shows direction and length before you commit the next one.
  • Click the fitted curve to edit it. The green fit line on canvas is a handle
    to its own controls. Only in Pan and Select modes, so it never hijacks a click
    that was placing a point.

Export

  • R (.R) export — each block renders as a named data.frame(), one vector
    per column. Non-syntactic headers like Strain (%) are back-ticked with
    check.names = FALSE so they survive verbatim; blanks become NA, and
    non-finite values emit real R literals (Inf, NaN).
  • Copy to clipboard — every text format (CSV, TSV, JSON, LaTeX, MATLAB,
    Python, R) has a copy button beside it that puts exactly the same rendered text
    on your clipboard.

Data entry

Points insert in place. Adding a point splices it into the curve edge it
disturbs least, so re-adding one you removed from the middle of a series lands
back in curve order — moving only that point, never renumbering the rest. A
normal left-to-right trace still just appends.

Downloads

Linux .AppImage / .deb, Windows .exe, macOS .dmg / .zip (Apple Silicon).
Builds are unsigned — your OS will ask you to confirm on first launch.


Full Changelog: v1.0.2...v1.1.0

v1.0.2

Choose a tag to compare

@github-actions github-actions released this 23 Jul 09:41

Full Changelog: v1.0.1...v1.0.2

v1.0.1

Choose a tag to compare

@github-actions github-actions released this 23 Jul 07:08

Full Changelog: v1.0.0...v1.0.1

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 22 Jul 16:12

The first stable release. PlotTracer extracts numbers from figures — the
stress-strain curve, the fatigue plot, the dose-response chart that exists only
as a raster image in a paper, a standard, or a scanned report. Load it, calibrate
the axes, place or auto-trace the points, export the data.

It runs on Linux, Windows and macOS, installs from a single binary, and works
fully offline — no account, no telemetry, no cloud calls. Your figures never
leave your machine, including on an air-gapped one.

What's in 1.0

Chart and axis types — XY, Bar, Polar, Ternary, Map (scale bar), Circular
Chart Recorder, Histogram (captures true bin edges, not just centres), Box
Plot, Line with a categorical X axis, and Error Bars.

Getting points off a figure

  • Manual placement across multiple series, drag to reposition, arrow-key nudge,
    click a value to edit it.
  • Auto-extract, under one wand tool: flood fill, trace by colour (continuous
    curve or scatter markers), a blob detector, and interpolation-assist (guide
    points plus a centripetal spline). A live mask preview shows exactly which
    pixels a trace will capture before you commit, and you can restrict a trace to
    a drawn box.
  • Grid-line removal, to clean a busy plot first.

Analysis — polynomial curve fitting (degree 1–9, optional x-range), geometry
and statistics (arc length, enclosed area, curvature), and a Check Calibration
overlay that draws the calibrated axis box back onto the image so you can see
whether it landed.

Measurements — distance, angle, area, slope, and a px→real-unit "Set scale"
reference, kept as their own collection, separate from the series data.

Images and documents — PNG, JPG, GIF, BMP, WEBP, SVG, PDF (multi-page),
and TIFF / multipage TIFF for historic scans. Rotate, flip, crop and
fine-angle deskew, all undoable.

Multi-figure projects — one project holds several figures (every page of a
paper, say), each with its own image, calibration, graph type and series. Flip
between them, or extract another figure from the retained source document.

Export — CSV, TSV, JSON, Excel (.xlsx), LaTeX, MATLAB, Python, plus a
WYSIWYG PNG of the digitised figure. Fitted curves export as their own labelled
blocks rather than being mixed into your data.

A durable record — undo/redo across everything, project save and reload as a
self-contained .zip that can carry the source PDF or TIFF with it, and import of
existing WebPlotDigitizer .tar projects.

Honest about precision

PlotTracer records what the figure shows — pixels first, values derived from your
calibration — and reports numbers no finer than the pixel grid can support, so an
export never carries precision the source never had. If you want the raw
full-precision values anyway, there's an explicit opt-in.

How 1.0 was gated

Three independent blind audits ran over the release candidate — correctness and
data integrity, tenets and UX, release and security — and their findings were
fixed before the tag. Among them: two bugs that silently produced wrong numbers
(ternary axis orientation lost across a save/reload, and a month-overflow on date
axes), degenerate-calibration and non-finite-value guards, and a hardened Electron
shell (OS sandbox, CSP, navigation lock).

Lineage and licence

AGPL-3.0. The calibration engine began as an extraction of
WebPlotDigitizer by Ankit
Rohatgi (AGPL-3.0); some algorithms are clean-room reimplementations of Engauge
Digitizer ideas; the interface follows Ketcher's design language. The application
itself — interface, interaction model, workflow — is a ground-up rebuild in
TypeScript, React and Electron.

Downloads

Linux .AppImage / .deb, Windows .exe, macOS .dmg / .zip (Apple Silicon).

Builds are unsigned: on first launch macOS Gatekeeper needs a right-click →
Open, and Windows SmartScreen a More info → Run anyway. Code-signing is a
planned follow-up.


Full Changelog: v1.0.0-rc.3...v1.0.0

v1.0.0-rc.3

v1.0.0-rc.3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 21 Jul 16:02