Repository navigation
Releases
Releases · PlantSimulationLab/Phytograph
0.97.0
New
- OBJ object groups stay editable. An
.objthat names its parts (o/g) now imports as one mesh that still knows them. The Meshes panel lists each group with its triangle count, visibility and color. You can move, rotate, scale, extract or delete selected groups, and.objexport writes the groups back. - Fractal dimension in QSM results. QSM now reports the box-counting fractal dimension of the woody surface, with fit quality, in the results window and the batch CSV.
Fixes
- Point size on large clouds. Octree clouds now draw at the size the slider says, and sizes below 2 now make a visible difference. Points look smaller than before, especially on standard (non-Retina) displays. If you preferred the old look, raise Point Size in the Display panel.
- Projects keep their point size. Opening a project now restores the point size it was saved with, rather than resetting to your default.
- Canceling a plant build. Canceling a canopy and starting another plant straight away could fail with "Could not resolve asset file". The second build now succeeds.
- Auto-register with a wrong scanner heading. A wrong heading could produce a badly wrong alignment that still reported "Auto-Register Complete". A search that comes back unconfident now retries without the heading and keeps the better result. "Use the scanner heading" now starts unticked, and uncertain results show a warning instead of a success message.
- Ground segmentation on close-range crops. Points high in a tree were sometimes classified as ground. This is fixed for small clouds. Airborne clouds keep their existing behavior.
- Class labels in
.xyz/.ascexports. These exports now include a comment line naming their columns, so class labels are recognized when you re-import the file. To leave it out for software that rejects comment lines, untick "Write column names header" in the Export window. - Scan metadata. The scanner origin now starts blank and must be entered, instead of defaulting to the center of the cloud, which is rarely where the scanner stood. The default grid is now 0.1° (1800 x 3600), and terrestrial scanner presets suggest a typical survey resolution.
0.96.0
Highlights
- Much faster ground segmentation. At fine cloth resolutions ground segmentation is now 5–24× faster (on a 45.7 M-point scan at the default 0.2 m cloth: 24 min → 61 s), and labels now come out the same on every platform.
- Tools that add a column no longer rebuild the point-cloud octree. Ground, wood/leaf, tree and organ segmentation, height above ground, normals, computed scalar fields and label commits now show their results right away instead of re-converting the whole cloud. Splitting a cloud by class draws the children from the parent, so nothing is converted then either.
- Registration is more reliable. Each scan is now placed along a chain of pairwise alignments that have been checked by a closed loop, instead of trusting its direct pair with the reference. Scans captured inside the canopy also register now. The success message only says the alignments agree when every loop closes. On an apple orchard that used to misplace a scan by 33 m, all scans now land within 2.3 cm of RiSCAN PRO.
Features
- Synthetic multi-return scans now record returns the way a real RIEGL instrument does: no miss point for energy that escapes a partly intercepted pulse, and a lower detection floor. This makes synthetic LAD a realistic test of the inversion. Requires the updated PyHelios/helios-core.
Fixes
- Viewer: where the display point budget cuts the level of detail short, points are drawn just large enough to keep the same coverage, so coarser areas no longer show up as sparse rectangles. Areas at full detail still draw at your chosen point size. A crash with more than 2048 visible octree nodes is fixed, and point picking (brush, erase, zoom to cursor) no longer grabs a foreground point that is off the cursor.
- Export: scan exports now write world coordinates (the import-time global shift is added back) and raw intensity values. Before this, a UTM scan exported in local coordinates and intensity was stretched separately in each file.
- Merge: merged clouds keep their GPS time encoding, so they export and re-import correctly.
- Georeferenced triangulation: Helios triangulations of UTM clouds keep full precision and draw in the right place.
- Wood/leaf segmentation leaves points already labeled as ground out of the result, and reminds you when ground was never segmented. "Remove wood" no longer deletes labeled ground.
- Tree segmentation (CHM) now estimates its cost from the grid size rather than the point count, so it warns before a long run and refuses a grid too large for memory, suggesting the smallest cell size that fits.
- Edits are no longer silently reverted when the backend spills a session to disk while a request is using it, or when an erase or undo happens during a bake. Segmentation tools refuse to overwrite an edit made while they were running.
- A plant's random seed now reproduces the same plant. It never did: the seed was applied after the plant model had already drawn its random parameters, so the same seed gave a different plant every time. This applies to single plants, canopies and the growth/age tools.
- The backend now exits when the app dies, including a Force Quit, crash or out-of-memory kill, instead of staying behind holding every cloud in RAM.
- RIEGL import: an empty
.rxpfile (e.g. a Dropbox project that hasn't finished downloading) now gets a clear message instead of RiVLib's "bad preamble". A Docker race right after the reader image is rebuilt is retried automatically.
Performance
- QSM skeleton extraction is ~2.7× faster on large leaf-on trees, with identical output.
- Showing normals on very large clouds fetches their values tile by tile, with no octree rebuild.
- Scan progress updates no longer re-render the whole viewer.
Internal
- PyHelios v0.1.38 / helios-core 1.3.93.
- CI keeps each E2E session's app and backend logs, plus periodic backend thread stacks, for diagnosing failures that only happen on CI.
0.95.0
Features
- Run a tool on several clouds at once. Label Points, Ground Segmentation, Segment Trees, Segment Wood / Leaf, Segment Plant Organs, Generate DEM and Extract Skeleton each have a Clouds picker in their panel, seeded from the Scans-pane selection. Each checked cloud is processed on its own, one after another, with one set of options. Cancel stops the current cloud and skips the rest, and a cloud that fails does not stop the others. Previously, several of these tools did nothing when more than one scan was selected.
- Label Points across clouds. One stroke labels every checked cloud and is a single undo step.
- Tool panels keep their title and close button pinned while the panel scrolls.
- Transform: Apply is grayed out when there is nothing to apply.
Fixes
- Windows: the app no longer fails to start under Smart App Control or other application-control policies. Every bundled native library is now signed, not only the executables. If an organization's policy still blocks the app, the error dialog now says so. (#6)
- ASCII import: a column of text (for example
leaf,wood, or a plant id) now imports as named classes instead of failing with "could not convert string to float". - ASCII import: a trailing column of class ids is no longer pre-selected as intensity, and a headerless first row such as
0 0 0 leafis no longer mistaken for a column legend. - LAS/LAZ export keeps full GPS time precision. Pulse timestamps were written at single precision, which merged distinct pulses in exported files.
- OBJ materials:
Kdcolors are read and written as linear, matching Blender and Helios. Exported plants no longer look about 3× too bright in Blender, and Helios-written OBJ files no longer import near-black. An OBJ exported by an earlier version now imports lighter. - Cloud-to-Mesh Distance measures the mesh as drawn, including its rotation and scale after Snap to Fit.
- Quitting with unbaked deletions no longer leaves a window that only Force Quit could close.
- Single-key shortcuts (
t,s,r) work right after checking a box in a panel. - Camera: newly imported content is reliably treated as framed when a mesh arrives at the same moment, on slow machines.
Performance
- Helios triangulation hands scans over in memory instead of through a text file. At 10 million points this removes about 15 s of file writing and parsing, and a further 12 s and 3.4 GB when cropping to a grid.
- The app stays responsive during long operations on large clouds. Segmentation, bake and delete no longer stall other clouds, progress updates or Cancel. Erase-brush deletes with many stamps are much faster.
Internal
README demo animation, a research harness for vegetation clumping scale, and more reliable end-to-end tests on Linux CI.
0.94.0
Features
- Project files (.phyto) — Projects are now much smaller: columns are compressed and octrees are regenerated on open instead of being embedded. Open a project by double-clicking it or dropping it on the window, and the quit prompt now offers Save Project. Very large projects no longer hit a size limit on save.
- Merge meshes (Stitch) — Merge several meshes into one. Where the merged meshes overlap, colors are matched and the duplicate surface is removed.
- Mesh cropping — The Crop tool now works on meshes as well as point clouds.
- Resample large clouds — Resample now works on octree-backed clouds.
- Pick targets in the panel — Transform, Crop, Erase, Filter, Normals and Cross-section now let you check the clouds (and, for Transform, meshes) to act on in the panel, and operate on several at once.
- Transform — Move, rotate and scale clouds and meshes together; Apply keeps the tool open for the next change;
t/rkeyboard gestures now work for point clouds. - Crop and Erase — Rect and Polygon cut what is on screen while the view stays free to move. Crop remembers the last shape and Keep mode between uses.
- Organ segmentation — Segments every selected scan, one after another.
- Scene origin — Click-to-place snaps to mesh and QSM surfaces.
- Mesh export — Exported files are named after the mesh.
- Startup — Open3D warms up in the background, and a tool that has to wait for it says so.
Fixes
- Projects — Fixed a hang on save/open, corruption from concurrent saves, undo after reopening, and unsaved-work tracking. Saving works after a session is lost, opening works when an octree rebuild fails, and the rest of the view is restored. Unbaked labels, every cloud's inventory entries and cancel behavior are preserved on open.
- Mesh export — A mesh is written where it is drawn (its transform is applied), and PLY export keeps per-vertex color and normals.
- Mesh-to-mesh ICP — Recovers large rotations and respects the mesh's own transform.
- Point picking — Picks the nearest point across all visible clouds rather than the last one.
- Transform — The
tgesture no longer moves opposite to the cursor. - Measure — The first vertex marker of a measurement is shown.
- Tools — A checked but hidden object is shown while a tool acts on it; box-draw corners land on meshes.
- Camera — A camera move issued right at startup is no longer overwritten.
- RIEGL import — Docker finds its credential helper when the app is launched from the Finder/desktop, and building the reader image no longer crashes the backend.
- Canceling — Canceling an import (or another long operation) now reliably stops the work; previously a cancel could occasionally be missed and the import would finish in the background.
- Backend status — The app only reports the backend as unreachable on a real connection failure.
0.93.0
Highlights
- Tree Inventory — per-tree DBH, height, lean, crown base and stem curve, stand-level metrics, batch QSM across a plot, and
.phytoproject files. Every setup parameter has a hover hint. - Segment Plant Organs — a new ML tool that labels soil, stem, leaf and individual leaflets.
- ML leaf/wood segmentation (PointNeXt) is now the default wood-segmentation method, with a v2 model for dense crowns.
- Tree segmentation for large and airborne plots — automatic stem seeds, tiled segmentation for large plots, and a canopy-height method for airborne scans.
- Label Points, greatly expanded — rectangle selection, Front/Box depth modes, Pick (label a whole piece of the cloud per click), painting above/below/near a line drawn in a cross-section, hide/isolate/lock classes, find unlabeled points, instance columns (new, merge, delete, frame, pairing), pre-labeling from another column, saving and loading strokes, keyboard shortcuts, and one undo/redo history shared with erases. The display now rebuilds on its own, so the Commit button is gone.
- Generated plants can be steered toward a chosen leaf angle distribution.
Other features
- Cross-section view: step keys, grayed-out full cloud outside the section, and an inset map.
- QSMs can be selected in the viewport.
- LAS import: flag columns, a choice of classification byte, and class names. LAS export now writes LAS 1.4 point formats, so user classes 64 and above are preserved.
- LAD: choose the leaf/wood split column; pulse columns are audited at import.
- Export: prepend or append the base name, and allow an empty base name.
- PyHelios v0.1.35: static-scan backfill by direction, and recovery from rounded timestamps.
Fixes
- Filter: every selected scan is previewed; a committed filter no longer flashes the removed points back; Min/Max re-seed when the panel is reopened on another scan.
- Clicking outside a modal no longer dismisses it.
- Auto-framing never undoes a camera view you chose.
- Classes past 64 no longer blend into their neighbors; new classes and sequentially imported meshes get distinct colors.
- Many Label Points fixes: stroke ordering, per-cloud pending strokes, instance ids above 255, cancelable rebuilds, and labels staying drawn with the panel closed.
- Import: "apply to all scans" works live, and in-file renames and roles are respected.
- The minimum window height again fits the whole toolbar.
- RIEGL reader image staleness check uses the resolved Docker binary.
Performance
- Ground segmentation runs CSF on one point per cloth particle.
- XYZ/PLY/PCD import streams positions straight into the session.
- Leaner session memory: whole-number scalar columns stored as narrow integers, and tool outputs written directly into stored clouds.
- Terrestrial scan tiles are balanced by point count.
- Label strokes are applied once and culled to the tiles they touch.
0.91.0
New
- Scalar Fields tool. Statistics, histograms and arithmetic on any per-point field, including across several clouds at once.
- Leaf and wood area density. LAD now splits into separate leaf and wood densities in a single inversion, with the wood G(θ) measured from the triangulation instead of assumed.
- Manual labelling, extended. Paint into any classification column (including a failed tree segmentation's instances) or create your own. Commit now returns immediately; the octree rebuild runs in the background and your labels stay on screen throughout.
- Compute Normals is now a proper tool, tiled so it handles large clouds.
- RiSCAN PRO
.asciiimport. RIEGL instrument-diagnostic scalars are now unticked by default at import. - Memory budget tracks free RAM. Thresholds scale with the machine, the budget is shown, and registration and editing operations are now covered by it.
- Meshes panel: Select All / Deselect All.
- Crop: the view now tells you it is locked while a polygon is set.
Faster
- Multi-scan registration is about 3.6× faster, and its fine stage is more accurate.
- RIEGL import does less work per scan.
- Box crop preview scales its density with your point budget.
Fixed
- Tree segmentation now detects the solver collapse that fused orchard rows into one tree per row, retries it, and warns when an instance looks like several trees.
- LAD no longer turns cropped returns into transmitted beams, which biased density low.
- Viewer: a cloud hands over to its rebuilt octree instead of briefly blanking.
- Updates ask about unsaved work before installing, and say the app is restarting.
- RIEGL on macOS: Docker is found when the app is launched from Finder or the Dock, and a missing Docker CLI is no longer reported as a stopped daemon.
- Transform applies to every selected mesh and opens for meshes.
- Undo keeps the backend in sync after rolling back an erase or a label stroke.
- Scalar fields: renaming shows the new name without rebuilding the octree, and a field can be named
reflectance. - Import: Phytograph's own class columns come back as labels, not plain scalars.
- Picking: the brush cursor follows the pointer, and the scroll wheel resizes it in place.
- Origin placement snaps to any visible cloud and never drops to z = 0.
- Crop: the drawn rectangle stays aligned with the region it crops.
- Erase no longer exceeds the viewer's clip-box limit on many strokes.
- Resample refuses an octree-backed cloud instead of writing NaNs.
- Large meshes are transferred as binary, avoiding slow or failed loads.
- Stability: QSM builds are cancellable and capped; segmentation workers are cleaned up if the backend dies; a live session's data is never trimmed from disk; a slow-but-successful backend restart is no longer reported as a failure; LAS export is no longer truncated by the memory check.
0.86.0
This release is largely about working with clouds far bigger than RAM. Import, segmentation, filtering, DEM building and export were each rebuilt to run in bounded memory, so scans in the tens of millions of points stay usable on an ordinary laptop instead of exhausting it.
Large clouds
- Large sessions are held in a memory-mapped store from import onward, rather than entirely in RAM.
- Buffered XY tiling for whole-cloud algorithms (the approach lidR and LAStools use): ground segmentation, outlier removal and local features run tile by tile with a collar, so peak memory is one tile rather than the whole cloud. Tiles run in parallel on a worker pool.
- Streaming I/O: LAS imports read in chunks, PLY and E57 conversions write in blocks, session export to LAS/LAZ streams, and cloud-to-mesh streams.
- DEM generation runs in bounded memory and sorts roughly ten times faster.
- Undo history is stored as deltas instead of full snapshots.
- You can pin the backend's memory budget in Settings, and set the octree renderer's display point budget.
- Splitting builds only the children and rebuilds the parent in the background; Remove points rebuilds the octree in the background.
Leaf Area Density
- Vertical LAD profile and bulk LAI are shown in the viewer.
- Occluded voxels are screened by probed path length and filled by kriging, rather than being reported as measured zeros.
- Several correctness fixes to the inversion: each miss keeps its own beam, hits deleted outside the grid are fed back in, G(θ) integrates over beams in blocks, and a background refresh no longer lets a crop bias the result.
Measurement and units
- Distance, path and angle measurement in the point picker. Measurements survive rigid transforms and move with their cloud.
- A scan's source unit is detected at import and normalised to metres, so a survey in feet measures correctly.
Color
- The colorbar fits the data rather than the noise, and one continuous scale is shared across visible clouds.
Safety
- Closing the app now confirms first when it would destroy the session. Nothing in a session is auto-persisted, so this previously happened on a single stray click.
Platform and reliability
- Linux: the real glibc requirement (2.38) is now stated and guarded at build time. This needs Ubuntu 23.10+/24.04 LTS, Debian 13, or Fedora 39+ — not Ubuntu 22.04, Debian 12, or RHEL/Rocky 8–9.
- Windows: octree-install failures are survivable, and evicted sessions spill to disk.
- RIEGL: the reader spawns without forking the loaded image, and no longer reports an update pending when staleness isn't the blocker.
- SBET trajectory import works end to end for georeferenced scans.
- Ball Pivoting drops duplicate points first; ground segmentation fixes the band floor on clean ground and stops scaling the CSF cloth with extent on airborne clouds.
- Upgraded to PyHelios v0.1.32 (streaming, bulk and block-tiled APIs).
Install
macOS users on Apple Silicon want Phytograph-arm64.dmg; Intel Macs want Phytograph-x64.dmg. Windows is Phytograph-Setup.exe. Linux is Phytograph-x86_64.AppImage (glibc 2.38+).
0.82.0
test(e2e): say why a launch never got a backend launchApp's "did not become ready within 120000ms" was all CI shard 2 had to offer when lad-export.spec.ts failed at 0ms on run 34081346174 — a first-time failure with nothing to chase, and no way to tell a crashed sidecar from a taken port from a supervisor that stood down. The main process routes console.* through electron-log, so its stdout is empty; the record is the per-session file logger.ts names with the main process's pid, and the sidecar's own log beside it under the same tag. On a readiness timeout, attach the tails of both. Verified by forcing the supervisor to stand down: the error now carries its own warning line and reports the sidecar log as never written.
0.74.0
v0.74.0 Auto-Register detects built scenes instead of asking, and drops the options that could not change the result. The heading prior is now gated on every selected scan having a recorded pose — sending it unconditionally put the correct answer outside the yaw search space for unposed scans. The RIEGL reader image updates itself when it falls behind, rather than surfacing a stale-image error behind a button hidden precisely because an image existed. CI gains a GPU parity workflow, validated on real hardware (Tesla T4): the CUDA ray-tracing path is exercised by the CPU-derived scan expectations, so a CPU/GPU divergence fails the build.