Triplot
An interactive panel for stacked DSC scans from TA Instruments TRIOS
files. Drop .tri files on it, stack the scans into the arrangement you want,
mark an interval on a curve to analyse it, and hand the result to a figure: a
PNG or SVG, a CSV, or a DSC_Plotter.py script that redraws it in matplotlib.
It reads TRIOS .tri files and .txt exports from DSC and SDT (TGA + DSC)
instruments with its own reader, validated against TRIOS's exports value by
value (tests/test_reader.py).
pip install triplot
triplot # start it
triplot my-sample.tri # straight into a file
triplot register # put it in the Start Menu (optional)
Python 3.10 or newer; PySide6 (the Essentials only), numpy and RDKit come
with it. From a checkout, pip install -e <checkout> installs it editable.
Version 1.1.0; what changed is in CHANGELOG.md.
It was called DSC-Panel until 1.0.0 and installed from the repository
as ach-dsc-panel. To move over, uninstall that first (both install the
same dscpanel package), then clean up the old name's Start Menu entry:
pip uninstall ach-dsc-panel
pip install triplot
triplot register --clean-legacy
triplot register
Its preferences, presets and window place come across by themselves the
first time Triplot starts, and saved figures keep their .dscpanel
extension.
What it does differently from a plotting script
- Every segment is an object. A
.triholds a heating ramp, a cooling ramp and usually five more; each one is a scan you can select, move, hide, colour and right-click. A file opens with its first heating scan on the plot and every other segment listed in the outliner, one tick away - so comparing the second and third up-scans of four samples is four ticks. - Three themes.
blender-defaultis the dark screen one,lightis the same figure on white,boomboxa brushed-metal dark one. Exports are always light, whichever is on screen. - Analyses are objects, and they start off. A run carries a dozen stored
analyses; each is a row in the outliner with its own box, its own colour
and its own settings. Where the file could not say for certain which scan
an analysis belongs to (a
.txtexport names only the step), it is drawn with a dashed tick and a question mark, and it can be moved to the right scan by hand. - The stack is continuous. Scans go wherever you put them (
G, or just type a number), and the offset each one carries is drawn beside it as a number with an arrow. No mouse gesture moves a scan by accident. - Nothing is normalised. The y axis is mW, W/g or W/mol, with real numbers on it. A DSC baseline depends on the mass, the pan and the heating rate, and scaling each trace to its own extremum would hide exactly the differences a stack is for.
- Per mole is opt-in. W/mol needs a molar mass, there is no default, and
a scan that has not been given one is drawn as a dashed placeholder with a
blinking red label instead of being plotted wrong. An export of a figure
with one in it carries a
NO MOLAR MASSnotice on the image and on the console. - A legend when you want one (tick it in the outliner): a colour sample and a name per drawn scan, taking each scan's own label. It is an artist, so it is dragged and anchored like the rest, and it starts off.
- Labels can belong to a line. Right-click a curve and add one: it
takes that line's colour, is listed under it in the outliner, and is
removed with it. Free-standing captions (
Ctrl+T) work the same way otherwise. - Artists carry a transform. Everything that augments the figure rather than coming from the data - the heat-flow arrow, a caption, whatever comes next - derives from one base class with a position, an anchor and per-kind capability flags. A position can be given as a fraction of the plot or in the axes' own units, and switching between them does not move anything.
- The heat-flow arrow is an object too. Label it "exo down", "exo up", "endo up" or "endo down"; the curves and the y axis follow the label, so the arrow and the data cannot contradict each other.
- The exotherm direction is read from the file where the file says it (a
.txtexport states it in the header; a.tricarries TRIOS's audit line), and reported as assumed where it does not.
Keys
| Key | What it does |
|---|---|
| click | select what is under the pointer (Shift adds) |
| drag from a curve | mark an interval; let go and pick the analysis |
| drag from an artist | move it: the arrow, the legend, a label, an analysis label, an axis caption |
| drag from empty space | box select (with Shift, a box from anywhere, adding) |
| double-click | settings: a curve, an analysis, an axis spine, a caption |
| two-finger swipe, mouse wheel, or middle-button drag | scale the y axis about y = 0 (drag up: taller) |
Shift + swipe or middle drag |
pan the view, in whichever direction the hand goes |
pinch, Ctrl + wheel or middle drag |
zoom both axes about the pointer (Windows sends a pinch as Ctrl+wheel) |
Alt + swipe or middle drag |
zoom the page, like a document; with Shift, move it (Alt+F fits it again) |
Z |
cycle zoom: box, horizontal, vertical (Esc leaves) |
P |
cycle pan: horizontal, vertical, free |
F / Home |
fit the view, with room for every analysis label shown |
Esc |
back to plain select |
G |
grab the selection: move, or type a number, Enter to confirm - the only way a scan moves |
X / Y while moving |
lock a direction (a scan only moves in y) |
Shift / Ctrl while moving |
precision / snap to round numbers |
R |
reset the selected offsets to zero (or all of them) |
| a number | move the selected scans by it; Enter confirms, Esc cancels |
Ctrl+T |
add a caption where the cursor is |
Ctrl+Shift+T |
add a note: a caption with an arrow to the point under the cursor (on a curve, it belongs to that scan); drag the ring at its tip to re-aim it |
S with only scans selected |
spread them evenly about y = 0; type the step, Ctrl for a round one |
Ctrl+P / Alt+P |
give the selected labels to the selected scan (they then move with it) / free them; or drag a label onto a scan in the outliner |
| double-click a page handle | type the figure's size in cm or inches, the aspect ratio kept |
Ctrl+L / Ctrl+R / Ctrl+M |
align analysis labels left / right / centred on their arrows |
C |
measure by typing: two temperatures, then Enter |
Delete |
remove the selection: an analysis, a caption, or scans |
Ctrl+A / Alt+A |
select everything / nothing; Shift+click adds |
H / Alt+H |
hide the selection / show everything |
Shift+M |
set the molar mass |
N |
show or hide the outliner |
F3 |
operator search: everything, filtered by what is selected |
Ctrl+Z / Ctrl+Y |
undo / redo, including a file you removed - and zoom, pan and fit, one gesture at a time |
Ctrl+S / Ctrl+E |
save the session / export the figure |
Ctrl+, |
settings: the house style, for every figure and for this one |
Ctrl+W |
close the pop-up in front; the window only when no pop-up is open |
The rule is short on purpose: a drag acts on what it starts near.
"Near" is the pick distance (Settings > Handling, 14 px unless you change
it): start within it of a curve and the drag marks an interval; of a label,
the arrow or the legend and it moves that; anywhere else it draws a box. A
click selects, a double-click opens settings. A scan moves with G and
nothing else, and an analysis label moves up or down only, with its leader
arrow stretching to follow.
The menu bar is File, Edit, Search (the same as F3) and Help (About).
Everything else lives in the search, filtered by what is selected.
Right-click a curve for its settings, its molar mass, a label or a note; right-click an axis's number to hide it (its tick stays).
The figure follows the DSC_Plotter template: no grid, ticks pointing inward
with minor ticks, an italic T against an upright unit, and integrations
shaded between the curve and their baseline. All of it is editable per object,
and the x axis can be drawn in degrees Celsius, Kelvin or Fahrenheit.
Measuring
Press on a curve and drag along it (a double-click-drag works too): the
stretch between the two crosshairs is the interval. Let go, and a short list opens under the pointer -
Onset, Integration, Glass transition and the rest; one click, or type and
Enter. The analysis is computed, drawn and added to the outliner at once,
and it is one undo step. Esc on the list drops the interval.
To give the temperatures as numbers instead, select one scan and press C,
then type a temperature for each crosshair (in whatever unit the axis is
showing) and Enter; Esc steps back one stage at a time.
Double-clicking an analysis made here brings its cursors back as gizmos, with its settings opened beside them rather than over them. Drag a gizmo and the analysis is recomputed as you let go; close the settings - OK, Cancel or the window's X - and the interval is confirmed and the gizmos go.
The arithmetic is trios_analysis, the same code the reader uses for the
analyses TRIOS stored, so a measurement made here and one read out of a .tri
are the same kind of thing. Against a stored integration in a reference run
the panel computes 13.3 J/g where the file says 13.2611.
Each analysis marks its interval with a dash on the curve at each end, in the axis colour; an onset, endset or glass transition also gets straight lines from those dashes to its result point, the template's construction (one tickbox hides them). A cursor can be picked up and dragged rather than replaced. Adjusting an existing analysis keeps the model it already has. Analyses made here are saved with the session and recomputed from the file when it is reopened.
A finished analysis arrives with its own caption - \Delta*H* = 13.247 J/g,
*T*_{g} = 78.9 degC - which is editable text in its settings. Captions
anywhere in the figure take the same small markup: *T* for italic, _{g}
for a subscript, and a backslash name for a Greek letter.
Hiding the ends of a curve (Scan settings > Hide) is the plotter's
x_truncate: the first and last N % of the POINTS, never a temperature
window - a DSC curve doubles back at its start and runs backwards when
cooling. The hidden ends show dashed while the scan is hovered or selected,
and are left out of the fit, the analyses and the exports. For the same
reason an interval dragged along a curve is the stretch of points between
where the drag began and ended, not every point between two temperatures.
The caption's alignment is the plotter's flush: which edge of the text
sits on the leader arrow. Left reads away to the right of the feature, right
to the left, centred hangs over it. By default it follows the analysis kind
as the template does - tangent constructions (onset, endset, glass
transition) flush left, integrals centre.
House style
Ctrl+, (Edit > Settings) sets the sizes and the label alignment, in two
columns:
- Default is yours: kept on this computer, used by every figure, and there the next time the program starts. The pick distance lives here too, under Handling: it is about your hand, not about a figure.
- This figure is saved in the session file and wins over the default, for this figure only. Left on "default", it follows the column beside it.
A size chosen in an object's own settings (double-click it) wins over both, and its Default button hands it back. The caption distance is the space between an axis's numbers and its caption.
Every settings window applies as you touch it and keeps the changes however it is closed; its Revert button is the one way back. Closing the program with unsaved changes asks first.
Figure size
Edit > Figure size and margins (saved with the session) gives the figure one of three sizes: whatever the window is, a fixed aspect ratio, or an exact size in centimetres or inches with four margins. At an exact size the margins decide the axes box - the numbers and captions live inside them, and the dialog says when one does not fit - so two figures with the same settings have identical axes boxes whatever their numbers say, and sit side by side in Word without adjusting. On screen the figure is shown as its page, scaled to fit. Use for new figures makes a layout the default.
Each axis can sit on either side (x bottom or top, y left or right) and hide its numbers, single numbers or its caption (double-click the axis line or its numbers). On an exact figure an axis moved to its other side takes its margin with it, and no margin can be cut into the numbers it holds - the one at the corner of the box included.
Exports
| Export | What it is for |
|---|---|
| PNG / SVG | the figure, drawn in the light palette, warnings stamped on; at an exact size, exactly that size (the PNG carries its dpi, the SVG its millimetres) |
| CSV | the curves as numbers, one x/y column pair per scan |
DSC_Plotter.py |
the arrangement as a driver script for the DSC_Plotter matplotlib template |
The driver needs that template's achdsc package, which is not on PyPI.
With it installed the export is a complete, runnable DSC_Plotter.py with
your paths, segments, colours and offsets already in it; without it, the
driver section alone, to paste into a copy made by dsc -c ..
The Start Menu, aliases, and the name
The name lives in exactly one module (src/dscpanel/branding.py) and a test
fails if it is hard-coded anywhere else; that is how DSC-Panel became
Triplot. Putting the program in the Start Menu is opt-in and reversible,
and it writes down what it created, so a rename can take the old name away:
triplot register # Start Menu entry (add --desktop for one there too)
triplot register --list # what is registered
triplot register --remove # take it away again
triplot register --clean-legacy # after a rename: remove the old name's entries
Your own name for it, on any platform (a .cmd shim on Windows, a symlink in
~/.local/bin elsewhere):
triplot alias tp
triplot alias tp --remove
Project layout
src/dscpanel/
branding.py every place the program says its own name
register.py Start Menu entry, aliases, and the manifest of both
core/ UI-free: model, units, arranging, undo, session, export
trios_io.py the TRIOS reader (docs/TRI-FORMAT.md)
trios_analysis.py the TRIOS analyses, recomputed
ui/ the painted plot, the outliner, the F3 palette, dialogs
docs/PLAN.md what is built, what is next, what is still undecided
docs/TRI-FORMAT.md the binary .tri format, and how it was decoded
docs/OPERATORS.md every operator, its key and when it lights up
Development
python -m pytest -q
Measurements are not committed. The tests that need a real .tri look for
paths in TRIOS_TESTDATA or in an uncommitted tests/local_testdata.txt,
and skip when there are none. They name a real file by a hash of its file
name (tests/conftest.py, hashed_name), so no sample id is in the
source.
Metadata
Release files for triplot 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| triplot-1.1.0.tar.gz | 471.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| triplot-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 832.8 kB
Release files / triplot-1.1.0.tar.gz
| Download URL | triplot-1.1.0.tar.gz |
|---|---|
| Size | 471.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8031ece9bd1e58bbecee2164bcb9820f5d53120e1594025d75deb90da97d0509
|
|
BLAKE2b-256 checksum How to use checksums |
61db2e341f51243cce71b2c9062a0e38687e1cc0d332547916632b53f63d2381
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.0
|
Release files / triplot-1.1.0-py3-none-any.whl
| Download URL | triplot-1.1.0-py3-none-any.whl |
|---|---|
| Size | 361.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
af0d3a1121d221c02408816d77d89e51a0707700d2ac0500727efcb1613ced3b
|
|
BLAKE2b-256 checksum How to use checksums |
5fb22759722d1dd5f065d02eda1bea514d1e0f2367ef6c44f297263b9c470f48
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.0
|