Remote sensing analysis · macOS
Hachure is a macOS application for examining and measuring remotely sensed imagery. Its sensor catalogue already carries the bands, wavelengths, ground sample distances and calibration equations of Landsat 4 through 9, Sentinel-1 and 2, MODIS, VIIRS, ASTER, SPOT 1 through 7, Pléiades and Pléiades Neo, WorldView-2/3 and Legion, GeoEye-1, SkySat and the PlanetScope Doves. That is what lets an index written once resolve on any of them. Aerial photography, LiDAR surfaces, hyperspectral cubes, reflectance transformation captures and towed conductivity surveys open in the same window. Everything you see is drawn from the data at its own bit depth.
Plotted above: hachures traced down the gradient of a 1 m LiDAR surface, Whanganui Inlet, north-west Nelson. Stroke weight follows slope, after Lehmann (1799). The same ground appears photographically further down.
Ways inWho this is for
The application began as a satellite-scene viewer and has grown sideways: into aerial survey mosaicking, LiDAR terrain, the archaeologist's terrain methods and reflectance imaging, towed soil sensing, and the time axis. Each card below names one of those ways of working, the parts of this page that describe it, and the GuideRail inside the app that walks it step by step.
Satellite scenes
Search five public archives from the window you are in, open a delivery with its calibration on record, compose it on the wavelength axis, convert to reflectance, take the haze out, classify or unmix it, and compare two dates with the normalisation stated.
GuideRail: Finding and downloading the right scene · Raw numbers to comparable reflectance · Change between two dates
Aerial surveys
A survey folder of ninety orthophotos opens as one mosaic. Seventeen 0.3 m tiles go onto a 32,000 × 60,000 grid in a minute with the seam under your control. Coarse bands take detail from a finer guide. Where no single band resembles the one being sharpened, the guide is fitted per band.
GuideRail: Several scenes into one mosaic · Sharpening coarse bands with a finer guide
Terrain and elevation
Relief shading with the sun on a dial, slope as a written product, elevation profiles that report where the model has nothing, an image draped over its DEM in three dimensions, and the change between two epochs with a level of detection behind the volume.
GuideRail: A DEM to a draft Land Resource Inventory
Archaeology
Local relief, openness, the sky-view factor and sixteen-sun hillshades on airborne LiDAR, with the Visualization for Archaeological Topography and its relatives as ready-made stacks; reflectance transformation captures relit after the fact; the decorrelation stretch for faint pigment, previewed live on the GPU.
Built September 2026 from RVT, the RTI papers and the ASTER ATBD
Soil and the near subsurface
A towed electromagnetic-induction survey is recognised, filtered stage by stage, inverted to conductivity against depth and drawn as a volume you can cut into. From there: soil pits ranked by purpose, substrate units, and a factor layer for the land inventory.
GuideRail: A proximal survey to soil pits
A property, over time
Several dates of one grid put a timeline under the map. A composite states whether its spectra were measured or assembled, and it carries the number of observations behind every pixel. A land-cover map comes with separability, blocked cross-validation and an area-based accuracy assessment.
GuideRail: A property's carbon-forestry baseline · An unsupervised land-cover map
The ten GuideRails live under Help ▸ GuideRail (⇧⌘G). Each is a run of steps that names the menu each control is under, folds a step away once it is ticked, and keeps the ticks between launches. Where Apple Intelligence is on, a More info button beside each step expands it from the app's own guide text, under instructions that forbid adding to it. Where it is off, the authored text is the whole feature.
Part 1
Satellite scenes and aerial photography: finding them, composing and stretching them, converting them to physical units, comparing them across dates, fusing and mosaicking them, and turning them into classes and fractions.
Finding dataWhere the time goes
Most of the time spent on a scene goes before it opens: working out which archive holds it, drawing the area again in a web viewer, downloading four candidates to find the one the cloud missed. Hachure searches Earth Search on AWS, Microsoft Planetary Computer, CNES GEODES, the Alaska Satellite Facility and LINZ from the window you are already working in. It shows you enough to choose before anything is fetched.
The common case is that you have a scene open and want the one before it, or the same ground from a different sensor. Elsewhere, that is where the fiddling goes. When a raster is open, the panel offers Extent of <that raster>, and one click seeds the search area from it, correctly projected. No coordinates are typed and no box is redrawn by eye. Otherwise you drag a box on the built-in world map. It carries cities, rivers and lakes and works offline.
The date range is a draggable span drawn over the archive's own temporal extent. SPOT 2's imagery begins in 1990. A search from 1986 shows the four years it is wasting. An empty result would have left you to guess why. Cloud cover is a slider where the collection reports it. A filter that could not act would only look as though it had. Where a collection does not report cloud cover, the slider is absent. Results sort by least cloud first.
A cloud percentage cannot say whether the cloud is over the ground you care about or off in a corner. A scene at 18 % cloud is useless when all of it sits on your paddock. Where an archive publishes a browse image, it is drawn on the map, inside the scene's own footprint, over your area of interest. The question then answers itself at a glance. Thumbnails load only for rows that appear and are cached per scene. A long result list does not fetch fifty images as you scroll.
A browse image is positioned by its scene's bounding box. Any transparent margin inside the picture is ground it claims and does not have. On a real radar quicklook that margin was 27.5 % of the canvas above the swath. It drew the data a fifth of a box too far south. Trimming to the opaque content puts the four points where the swath meets its own envelope within 0.15 – 0.73 % of where the archive's geometry says they are. To a brightness test, a dark margin and a dark coastline are the same pixels, so the trim reads the alpha channel alone.
LINZ publishes a static catalogue with no search service behind it, so it is selected by Topo50 sheet. Click the sheets you want, or drag a band across the grid to take several at once, and Find Surveys asks the bucket which aerial surveys hold tiles for them. Over a single sheet that answer is a time series of the same ground across decades, narrowed by the years they were flown. One listing request per survey settles whether it covers your ground before anything is fetched.
Choosing a survey draws its tiles on the map. The map and the list are one selection. A click or a dragged band on either side ticks the same tiles. Hovering names the sheet the way LINZ printed it and the tile by its filename. The download states its size before it starts.
Bands on different native grids are assembled as separate stacks and are never resampled together. A file already on disk is not fetched again. A dropped transfer is retried and resumed where the archive allows it. The retry fetches only what is still missing. A truncated raster that opens looks like a complete one until something reads its far end. The partially written file is therefore discarded. The failed attempt stays on record as its own row. Landsat is free on Planetary Computer and requester-pays on Earth Search, and the panel says which before you commit.
A finished download opens through the same door as a file from the Finder. A downloaded delivery is recognised the same way. Landsat MTL, Sentinel-2 SAFE, Maxar IMD with RPB, Airbus DIMAP v2, SPOT Scene (DIMAP v1, the SPOT World Heritage format) and NITF each open their own window with the bands, the calibration and the geometry the delivery publishes. Recognition looks at most one folder below the one it is asked about. The downloads folder itself is never mistaken for the delivery beneath it. Where a delivery ships several resolutions of the same ground, as Landsat 7 does with its 30, 60 and 15 m bands, a sheet lists the grids with a tick beside each. It asks which one the window is built on. Browse and branding images start unticked, with the row saying why.
Once a scene is open, the overview pane answers “where is this?” against real topography. The source is picked by the ground under the scene: New Zealand gets the LINZ 1:50,000 series, Switzerland gets swisstopo, the United States its USGS topo and France the IGN plan. Ground no national service covers falls back to Apple's map, dark and muted with points of interest off. That fallback was looked at before it was given the role. Over Aoraki it carries shaded relief, glaciers and landcover. Over farmland it is very nearly blank. That is why it fills in only where nothing better reaches. Every raster in the window is drawn on it as a footprint, along with your cursor. The pane follows the active project until you pan it by hand.
Composites& spectral indices
NDVI is (B08−B04)/(B08+B04) on Sentinel-2 and (B5−B4)/(B5+B4) on Landsat 8. Because the catalogue carries every band's centre wavelength, FWHM, ground sample distance and spectral role, the preset resolves itself against whatever stack is open. You never say which band is which. The same holds for NDWI, NDMI, NBR, NDSI, NDRE and the tasseled-cap brightness, greenness and wetness.
The Composite panel draws every band that states a wavelength where it sits on the axis, at its own width, with a draggable puck per display channel. Centring one channel in an absorption feature and the other two on its shoulders is then a drag along the axis. Three band-number popups have no way to express that. The presets are drawn as the spectra they select. You can see what a choice will do before you make it.
A band with no stated wavelength has nothing to place it by, so it appears in the list below the axis, fully assignable, without a position on it. Where none of the bands state one, as in a photograph, the axis stays and says so across it. The list does the assigning.
A wavelength axis as an assignment control is established prior art. What is less usual is making it the primary control, in the place bands are assigned, with the bands drawn at their widths.
Click a pixel and its full spectrum is plotted, against wavelength where the bands declare one and band index where they do not. An axis rescaled for every pixel would make every step look like the axis moving. The y-axis stays pinned as you scrub instead. On a hyperspectral cube that is the fastest way to tell two surfaces apart. On a ten-band stack it is the fastest way to catch a band assignment that is wrong.
Beyond the presets, a custom expression takes an arbitrary formula in b1…bN with arithmetic, comparison, logical and bitwise operators, conditionals, clamp, min and max, logarithms, safe division and QA bit extraction. One typed expression tree drives both the CPU evaluation that writes a Float32 GeoTIFF and the Metal shader compiled at runtime for the live view. The two are tested against each other for parity. The picture on screen and the file on disk are the same arithmetic.
Worth knowing An index is only as good as the spectral roles behind it. NDVI uses whichever bands are named NIR and Red. On a stack whose roles are wrong, the arithmetic still succeeds and returns a plausible surface of the wrong two bands. The Composite panel is where you check the roles, and the spectral profile is how you notice.
DisplayTone & fidelity
Stretch, gamma, curve, colour map and blend mode are display exposure. Processing jobs, band maths and the GeoTIFF export read source samples whatever the screen is showing. You can drive the display as hard as you like without wondering whether it has reached a result. Nothing is corrected on open. The default is the band's own full range. When you do want the curve in the file, one named command puts it there and labels what it made.
Five transfer modes: full range, percentile, histogram equalisation, levels and a tone curve. The judgement being made is “steepen where the pixels are”, so the curve is drawn over the distribution it is shaping. A histogram redrawn from the output always looks well spread and would tell you nothing. The histogram underneath shows the values going in and holds still as you drag. A curve can be derived from an equalisation and then edited. Unlike Auto, which is recomputed, a curve is fixed. The same mapping can be re-applied to another scene.
Each raster layer carries its distribution as a sparkline in its sidebar row. That is how you spot the one layer in a stack of twelve whose histogram sits somewhere different, before it turns into a mosaic seam or a bad difference. It is the question the Levels plot answers for one layer, asked of the whole stack at a glance.
Beside each layer's opacity slider is a blend mode: normal, multiply, screen, overlay, soft light or luminosity, the six ISO 32000 modes, evaluated in the same single render pass by framebuffer fetch. A group can take a mode too. A group with none is pass-through and its opacity multiplies into each child, as it always has. A group with a mode is composited as one picture first and then blended over the frame at its opacity. That gives a different image from fading its children one by one. It is what the archaeological composites below need. Both are saved in the project. Eight full-viewport layers with blend modes cost 1.3 to 1.7 ms of GPU time at 2048², inside the frame budget.
Export as GeoTIFF writes the source's own samples and records the curve beside them. The curve travels with the file without touching a sample. The rendered exports (PNG, HEIC, OpenEXR) apply it and produce a picture: a display composite with no georeferencing, 8-bit or Float16. Processing ▸ Radiometry ▸ Apply Display Tone Curves applies the curve and keeps the raster. That is usually what someone asking for a stretched product means. Every display channel goes through its own transfer, whatever is in force. The result is a georeferenced GeoTIFF at full bit depth. It is either the source's own data type spread over that type's whole range, as another GIS or a print expects to be handed, or Float32 holding the transfer's 0 to 1 output with no requantisation at all.
The shader's lookup table holds 4096 entries, sixteen times coarser than uint16 data. Writing the file through it would quantise the result to whatever the screen happened to need. The curve is instead evaluated per sample. The file that comes out is finer than the display was, and its metadata says so. An integer band cannot hold NaN, and absent ground reading as legitimate black is a confusion worth a level. Where a contributing band declares nodata and the output is an integer type, zero is reserved for it and the tone occupies one level less.
What the output says about itself A tone curve clips at both ends and is not invertible, so the result is not radiometry and cannot be treated as any. The file states that in its own metadata: a per-band description ending (not radiometry), and a tag reading “these samples are display intensities… the measurements are in the source named above”, along with the source path, the transfer used on each channel and a note of any clipping. The display path itself is untouched. The command is chosen once, by name, and writes a new file.
A sixteen-bit scene holds far more range than a standard-dynamic-range screen can present. That is why so much of the craft of looking at one is choosing what to sacrifice. On a display with extended range there is less to sacrifice. The composite is rendered to rgba16Float in extended-linear Display P3 and handed to the compositor at that depth. Bright cloud tops and a shadowed valley floor can then hold detail in the same view without trading against each other in the stretch. Nothing along the way is quantised to eight bits.
SDR is the default and HDR is a choice you make. Headroom is a property of the screen the window is actually on. It is read from that screen and re-read when the window moves to another. Where a screen has no usable headroom there is nothing to render into, and the effective mode stays SDR even with HDR preferred. The footer says which regime you are in with a plain SDR or HDR badge. The tooltip gives the number: rendering in HDR, output range 0 to 3.4× SDR white, or rendering in SDR, display EDR headroom 1.0× (no EDR). That matters when two people compare the same scene on different machines. It is invisible until it has misled somebody.
Each layer declares its colour space. ColorSync converts to the profile of whatever display is attached. A wide-gamut composite looks the same on a calibrated studio display as on a laptop, and a colormap ramp is the ramp you chose. Exports stay SDR unless you pick HDR explicitly, and the export panel says so. OpenEXR is there for when the float range needs to leave the app intact.
Twelve- and sixteen-bit data stays at its own depth from disk to screen. The display never invents a sample when it magnifies. A readout, a histogram bin and a percentile clip all refer to values the file contains. Decimation is allowed to sample. The alternative is showing one pixel in nine. A raster with no overview pyramids opens anyway, streaming from full resolution. A banner offers to build a sidecar in the background: mode resampling for thematic rasters, average for continuous ones.
Click corners, free draw, rectangle, ellipse, or press a pixel and drag to grow a selection of similar pixels around it. Each finished shape becomes its own layer inside a polygon group. It carries its ground area in whatever unit suits its size, hectares for a paddock and square metres for a gravel bar. Each also gets a distinct tint so overlapping regions stay legible. Mark one Use as Processing Region and it turns graticule cyan. Every region-aware job then clips to it. The Processing menu says which region it will use. An imported shapefile or GeoJSON boundary works the same way with no conversion.
The similar-pixel selection grows four-connected from the seed as you drag. It finds the paddock you pressed and stops at its boundary. Its tolerance can match on value, scaled by each band's spread, or on spectral shape, which ignores brightness and keeps sunlit and shaded ground of one material together. The raster is read around the seed, so a region that runs off the edge of the screen comes back whole.
Once marked, the region scopes measurement as well as processing. Band statistics switches between whole image and selected region. Per band, it reports the valid and excluded pixel counts alongside minimum, maximum, mean and standard deviation. Its percentiles state their own resolution: exact for integer data in a modest range, a declared bin width for float. Zonal statistics does the same per polygon, in one pass however many zones there are. The table exports as CSV.
RadiometryPhysical values
Metadata ingest reads Landsat MTL, Sentinel-2 SAFE, Maxar IMD with RPB, Airbus DIMAP v2, SPOT Scene and NITF, and records what calibration each delivery publishes without applying any of it. Run the conversion when you want it. The result carries the quantity, the units, the exact equation and which coefficient came from where. A reflectance product can be audited a year later.
Calibration covers scale and offset in both conventions, solar-elevation reflectance, Planck brightness temperature, Sentinel quantification, Maxar gain and bandwidth, DIMAP divisor gain and lookup tables. Only the operations you tick are applied. Results are Float32 and unclipped. A plausible number in place of a fill value or an out-of-range input would be the harder error to find, and both become NaN.
Atmospheric correction is per-band dark-object subtraction with the scene percentile and sample bound in your hands. The method assumes somewhere in the scene is genuinely black in every band. Over a bright arid scene or a small subset that is often false. The panel labels it plainly as DOS and claims none of the rigour of a radiative-transfer model like 6S.
Two haze reductions sit beside it. The haze thickness map (Makarau et al. 2014) estimates haze per location from a locally searched dark-object field and subtracts it from each band scaled by how much that band sees haze. It streams the coarse fields it needs in one walk and upsamples them per row inside the transform. A scene of any size costs one row block of memory. The cirrus correction (Gao & Li 2017) uses the sensor's own 1.38 µm channel. There the water-vapour column absorbs all surface signal and the band records scattering alone. It is offered only where such a band exists. Both refuse where their assumptions fail, name the band they could not measure, and stamp their departures from the papers into the output.
Topographic correction offers SCS+C, C-correction, Minnaert with the constant fitted per band, and the statistical-empirical rotation. Slope and aspect come from a Horn 3 × 3 operator on the DEM you choose. A correction fitted where the DEM does not reach is not applied there, and the report says how much of the scene was covered.
Sun zenith and azimuth are auto-filled from acquisition metadata where the product states them. The Info inspector draws them as well as listing them. The glyph is the sky dome seen from above with the sun where the metadata puts it. A low winter sun and a near-nadir summer one are told apart at a glance. Illumination geometry decides whether a topographic correction is worth running at all. That is why it is drawn where you will see it.
The catalogue's band centres are the agencies' measured ones. ASTER's, for example, are derived in a test from JPL's published spectral response functions (556 nm for band 1 against the 560 nm range midpoint the handbook quotes). The test fails if anyone tidies them back to round numbers. The same catalogue recognises a band by its description, its filename or its position in a known layout. Where the file's own colour interpretation disagrees with what the catalogue knows, the catalogue wins. An ASTER VNIR granule therefore opens colour-infrared with its near-infrared band in the red channel.
TimeDates on an axis
Open several dates of one grid and a timeline appears under the map: one lane per platform, a tick for an instant and a bar for a span, and a playhead that snaps to the observations. A gap in the record is the revisit cadence, the cloudy fortnight or the twenty-nine years between two aerial surveys. Closing it would manufacture an adjacency nobody measured. The observations therefore never move.
Following the playhead works by hiding, leaving exactly one date checked in the Layers sidebar. A date switched off is still part of the record, and membership of the series is every raster layer whether or not it is visible. The dates an answer is computed from are the timeline's window. That window is explicit, named in the panel and written into the output. A collection is formed from the layers that share a grid to within a hundredth of a pixel. A candidate that joins nothing carries a sentence saying why. Acquisition time is an instant or a span in its own type, so a survey flown across five years prints as a range. The midpoint of an eight-day product appears nowhere. For browsing a forty-year record, an Evenly spaced mode arranges the marks by count, and its tooltip says so.
A per-band reduction (median, mean, minimum, maximum) produces a spectrum no sensor recorded: the red may come from March and the near-infrared from July. That is right for “what does this ground usually look like” and wrong for anything that reads a pixel as a spectrum, such as unmixing, spectral angle or a library match. A donor rule (the date with the largest or smallest value of an expression, the earliest, the latest) picks one date per pixel and copies its bands whole. The output stays a measurement, at the cost of seams where neighbouring pixels chose differently. Because neither is safe as a default, the panel has none. It says which claim you are making before the run, and HACHURE_TIME_COMPOSITE_SPECTRA records it in the file.
Every composite carries an Observations band. A median over eighteen clear dates and a median over two are the same number with different standing. A product stating only the number invites the second to be read as the first. A donor composite carries a Source date band beside it. A pixel no date observed is nodata in the bands and zero in the count. Validity is per pixel, taken from Landsat's QA_PIXEL or Sentinel-2's SCL where a quality raster sits beside the scene. A date whose band 3 is fill contributes none of its bands. The count printed beside a pixel is the same whichever band you click.
A pixel's series is charted with its gaps intact. A line drawn across a date that saw nothing would assert a value nobody measured. On a cloudy coast that is most of the line. The chart breaks at every absence, and each gap carries which kind of nothing it was: unobserved, masked out, not computable, unreadable. The CSV keeps the empty rows for the same reason. On the generated eight-date series, the composite ran in 167 ms and its Observations band reads 7 inside the holed patch and 8 outside.
ChangeDrag the pane
The base document is A and any added or derived raster is B. They can be compared fixed side by side, with a draggable swipe, as a linear blend, or by timed flicker. All four are display-only, and all isolate A and B from the rest of the stack. Up to four named view groups link camera, zoom and crosshair across separate windows, in geographic coordinates where both datasets have a CRS.
Change detection offers differencing, log-ratio for radar, index difference including dNBR burn severity, and IR-MAD's no-change probability as the threshold. Every method compares co-located pixels. The panel states the same-grid requirement up front. Failing halfway through a read would have said the same thing later. The normalisation assumption travels with the product into every figure computed from it, and the panel also asks you to record what was done.
Six ways to normalise: histogram specification, linear optimal transport matching mean and full covariance across bands, global regression, LIRRN, and IR-MAD. Accuracy assessment follows the good-practice area estimators, and reports quantity and allocation disagreement in place of Kappa.
FusionDrag the pane
SFIM detail injection, Brovey, GSA (Gram-Schmidt Adaptive, which fits its intensity component by least squares where the plain form assumes a flat band mean) and MTF-GLP-HPM, which degrades the guide through a Gaussian matched to the sensor's modulation transfer before injecting it. Method, guide band, coarse resampling kernel and detail amount are all yours to set.
MTF-matched and GSA hold a property you can test. Aggregate the fused result back to the coarse grid and it should reproduce the input. A plain component substitution holds it much less well. Where a figure has to be defensible per pixel, a calibrated reflectance or an index quoted as a number, compute it on the source bands. Use the fused product for geometry. Only layers finer on the ground than the target are offered as a guide. The job streams one band at a time, and peak memory does not scale with band count.
The guide can be one band, the mean of the guide's bands, or fitted per band. A fitted guide is a least-squares weighting of the guide's bands onto each coarse band. It is solved after each guide band has been degraded the way the chosen method degrades its guide, and it is applied at full resolution. That is what makes fusion possible where no single guide band resembles the band being sharpened. MODIS bands 1 and 2 at 250 m against the 500 m shortwave bands is the case. Snow is bright in red and dark at 1640 nm, so a single red guide injects every boundary upside down. That case needs a negative weight, and the fit is free to give a guide band one. On a six-band Sentinel-2 20 m stack sharpened onto its 10 m bands, the fitted guide runs in 15.2 s at 5.2 cores and a single guide band in 4.35 s.
ClassificationAnd what follows it
Unsupervised: K-Means with k-means++ and maximin seeding, ISODATA with adaptive split and merge, and a Gaussian/Mahalanobis mixture. All are deterministic and multicore, with a Metal backend for the assignment step. Images too large for memory are fitted on a decimated sample and assigned block by block. Supervised: random forest, maximum likelihood, minimum distance and spectral angle from training polygons you label. And where a pixel is a mixture, linear unmixing writes how much of each material it holds.
Two classes that overlap in feature space cannot be told apart by any classifier. Separability is drawn as a heat map before you commit, and the problem pair is a dark cell you notice. Training classes carry their pixel counts. A row turns amber when it is thin for the bands you have selected, and you can untick the bands that carry nothing for these classes. A polygon that clipped the edge of a cloud teaches the classifier that cloud is forest, and the map that comes out is plausible everywhere. A quality mask beside the layer keeps cloud, shadow and fill out of the training pixels. The live preview fits on the visible extent. That makes it a tool for choosing k by looking. The full run fits the scene.
A random split over training polygons reports an accuracy inflated by up to 28 % through spatial autocorrelation. Blocked cross-validation refits the classifier with whole blocks of ground held out. It reports the figure beside the out-of-bag one and names the difference between them as optimism. The block size can be derived from a variogram over the training pixels. The derivation refuses where the pixels are too few or too clustered to fit one. Both figures describe the classifier. The map's own accuracy comes from an independent sample. It is drawn by reservoir sampling in one pass with the allocation you choose, and labelled point by point.
Spectral unmixing works from a named set of reference spectra. They are derived from polygons you have drawn over single materials, or imported from a spectral library and convolved onto this sensor's bands through each band's stated width. Three models: a single matrix, MESMA (every pixel solved against every candidate model, the winner chosen by fewest materials and then lowest residual), and AutoMCU. AutoMCU draws a different signature from each material's bundle many times and reports a mean and a spread. A fraction arrives with an error bar. “None of this pixel” is itself a measurement, and materials a winning model left out are written as zero. Spectral Angle Mapper labels each pixel with the reference it points most nearly at, ignoring brightness. It writes the angle beside the class so that a confident match and a distant one can be told apart.
Where a threshold falls is the whole of what the output says. Reclassify turns a continuous band into named classes by a table of breaks, with the band's own distribution drawn behind them. A value outside every class is left unclassified. Clamping instead would let a top break typed as 3.6 rather than 36 report a whole property as the steepest class, complete and confident, with no gap anywhere to notice.
Land Resource Inventory intersects up to five factor layers, rock type, soil, slope, erosion and vegetation, into inventory units. It sieves them to a minimum mappable area and looks each combination up in an editable rule table for a Land Use Capability class. Good drainage cannot compensate for a thirty-degree slope, so the class comes from the most limiting factor. Units missing a factor nobody assessed stay unclassified. A severity of zero records that somebody looked and found nothing, and it stays separate from nobody having looked. Every unit's row carries where each of its five statements came from.
MosaicJoining scenes
The panel plans the output grid, reports overlaps and disconnected pieces, and pre-flights CRS, resolution ratio, overlap sufficiency and radiometry. Two seam solvers: least-cost path routed through waypoints you pin, and graph cut, which can isolate an island. Four join modes: hard, feathered on a linear or cosine ramp, distance-weighted, and seamless multi-band Laplacian. Scenes in different coordinate systems are warped once into a target you choose.
The preview composites on a decimated grid so that the seam can be dragged and re-routed at interactive speed. The cost surface behind it is a superset of the usual difference term: absolute difference plus gradient, constrained by a dilated mask. Chained pairwise fits let error accumulate along a strip. Radiometric balancing avoids that by solving a per-scene gain and offset across every overlap simultaneously.
Hard blending leaves values untouched and is the default. Feathered, weighted and multi-band blending all rewrite pixels near the seam. Balancing rewrites whole scenes. The panel says which of those you have asked for. It is built for large jobs, such as seventeen 0.3 m aerial tiles onto a single 32,000 × 60,000 four-band grid: 7.68 billion samples planned, composited and written in 62 seconds. A folder of adjacent tiles opens the same way without the panel, as one image over the whole extent.
Part 2
Elevation models as pictures and as measurements: relief shading that stays on the display, slope and profiles that leave as files, an image draped over its surface, and the change in height between two epochs.
TerrainSame ground as the hero
Relief shading, the slope raster and the topographic correction all use Horn's 3 × 3 kernel, so a slope class and a hillshade cannot tell you different things about the same cell. Shading stays display-only. Every control has a live thumbnail. The full-resolution pass runs only when you press Apply, and it arrives as its own layer. Slope writes a file, in degrees, percent or rise over run, with the downslope bearing beside it if you want it.
A sun position is a point on the sky dome, so the light is placed on a dial, with bearing around the ring and height from the centre. Finding the azimuth that reveals a lineament becomes a matter of moving the sun until it does. Multi-directional light, cast shadows, skylight, and a hypsometric, slope or aspect tint over any colormap are all there.
The shading is a picture of the terrain and the slope raster is the measurement of it. That is why only the slope can leave as a file. Both come from the same operator and cannot disagree about a cell.
Right-click an image that shares ground with an elevation model and View in 3D drapes it over the DEM under an orbit camera. The pair is chosen by the most shared ground. Where the image reaches less than all of the surface, the menu states the share, rounded down. Unlit black would read as real surface, and a third of a hillside would look like night, so ground the image does not reach is drawn as nothing at all. A nodata gap inside the image is a hole for the same reason.
Click a line across an elevation surface and the terrain profile charts as you go: length, elevation range, ascent and descent, and maximum slope. Where the line crosses ground the elevation model does not cover, it reports the count of those cells and draws no line through them. A pane floating over the map would cover the very ground being measured, so the profile sits above the footer. The table glyph beside the readout takes the samples out as a file.
A slope is a height over a ground distance and most DEMs state only the second. The ground distance comes from the geotransform. A degree of longitude shortens with latitude, and on a geographic grid the distance is converted per axis. The vertical unit comes from the band or a compound CRS. Where nothing declares one, the panel says the heights were taken as metres. A DEM in feet read as metres reports every slope 3.28 times too steep and fails in no visible way.
DEM of Difference reports volume lost and gained with the uncertainty that makes the figure defensible: a level of detection measured from ground you mark as stable, a probability of real change per cell, and a spatial-coherence pass that keeps a coherent patch of marginal cells and drops isolated spikes. A rigid vertical correction removes a constant offset, and uniform soil loss is a constant offset. Co-registration is therefore offered as a check and left off. InSAR displacement answers the neighbouring question: millimetres of motion along one line of sight at 30–80 m posting, with the coherence that says which cells are a measurement at all.
Part 3
Three things archaeologists do that fit this machinery: the terrain methods that find earthworks in airborne LiDAR, relighting a reflectance transformation capture of a carved or painted surface, and the decorrelation stretch that brings faint pigment up out of rock. All three were built from the published sources in September 2026.
Terrain methodsAfter RVT
A bank, a ditch or a ploughed-out barrow is a metre of relief under the general lie of the land. A single hillshade hides whatever runs parallel to its light. The methods the Relief Visualization Toolbox made standard are here as four processing jobs, each writing a measured product. The Visualization for Archaeological Topography and its relatives are assembled from those products as stacks of ordinary layers.
A radius is typed in metres and converted on the model's own cell size. A recipe then states what the source states. Every windowed product obeys the complete-window rule. A cell whose radius runs off the raster or into nodata is withheld. Filling that ring would measure against surroundings the model does not have. Each product therefore carries a ring of one radius round the border and round every hole. The openness and sky-view marches run on the GPU from the horizon walk the relief shading already had. The two engines were found rounding half cells opposite ways, and they are now held to one CPU-built table of ray offsets. Metal's fast-math length() puts a point sitting exactly on the radius a hair outside it. The radius test is done in integer squares instead.
Terrain Composite offers eight recipes transcribed from RVT's own sources: VAT for general and for flat terrain, the combined VAT, the colour relief image map, prismatic openness, e4MSTP, and two pictures of the multi-directional hillshade, three suns as RGB and the principal components as RGB. Applying one runs the jobs it needs through the Jobs panel, adds each product as a layer with its published stretch, ramp, blend mode and opacity, and groups them under the preset's name. The stack is ordinary layers that can be inspected, re-ordered and saved. Each group remembers which recipe made it. The composite is a picture and cannot leave as a raster. The products beneath it can.
Two of those recipes lay one rendered picture over another. That is a different image from blending the picture's layers into the stack one at a time. The combined VAT, for instance, is the general stack at half opacity over the flat one, as a whole. A group can therefore carry a blend mode of its own. Its layers draw into a second colour attachment of the same render pass. The attachment is memoryless and lives in tile memory for the duration of the pass and nowhere else. One full-viewport triangle composites the result over the frame in the group's mode. Measured against the two stacks it is made of, the combined VAT is their average to within 8-bit quantisation. A resolve costs about 0.1 ms at 2048².
Found by looking, on real ground The presets were rendered headlessly on two LINZ 1 m tiles before anyone saw them in the app. Two faults came out. Both were in what the numbers meant, and four thousand green tests could not have found them. RVT turns its stretched slope upside down after the cut. The transcription had missed that, and every steep face on the first picture was lit. A translucent streamed layer was also being drawn twice, once from its coarse backfill and once from its detail tiles. A row set to 50 % composited at 75 %. Both are fixed and pinned by tests written from what was seen. The four jobs a VAT needs ran in 1.7 s over a 34.6-megapixel sheet.
RelightingReflectance transformation
A reflectance transformation image holds, per pixel, a function of the light direction in place of a colour, so a rock art panel or an inscription photographed under a dome of lights can be lit from any side afterwards. Open a polynomial texture map and it opens relit. Open a light file and the window offers to fit one from the whole capture.
Two bases from the papers: Malzbender, Gelb and Wolters' biquadratic polynomial, six terms with a fixed colour or per channel, and Gautron's hemispherical harmonics to order two or three, nine or sixteen terms per channel. The fit takes a .lp light file and the photographs it lists, solves one pseudo-inverse per fit, and writes a coefficient raster as a GeoTIFF declaring its basis, terms, per-term scale and bias, and the surface normal from photometric stereo beside them. PTM 1.2 files convert on the way in, in both their LRGB and RGB layouts. CHI's .rti layout is behind a registration wall and its only open description is GPL source. That format is not opened, and the survey says so.
The relighting is a branch of the same fragment pass every other layer uses. A relit raster reads every coefficient band of a tile, up to fifty-one bands for a third-order harmonic fit with its normals, so the pipeline variant is declared at that width for such a raster. It stays at eight for everything else. Four modes: relit, Malzbender's specular enhancement, diffuse gain (the polynomial's curvature scaled about its own maximum), and the normal as a colour. The light and the mode are saved in the project.
Checked on a synthetic panel A 512 × 384 engraved panel, a spiral groove and a cup mark under fifty lights from 20° to 70°, was fitted in every basis and rendered from seven lights. Both bases relight the groove as relief from every direction. The overhead view is flat. Specular enhancement adds its sheen, diffuse gain deepens the groove, and the two normals views agree. On a forty-light test capture the worst normal is within 2.62° in every basis, with mean luminance errors of 1.67 levels of 255 for the polynomial, 1.10 for second-order harmonics and 0.45 for third. The same harness found that the fit had solved in 0…255 while the shader relit on 0…1, and that a harmonic fit's normal bands were clamping onto its last coefficients. Neither showed in a parity test.
DecorrelationFaint pigment
Three bands are rotated through the eigenvectors of their correlation matrix, each component is stretched to the same spread, and the rotation is undone. The colour axes stay where they were, and the correlation between them is gone. That is JPL's ASTER AST06 algorithm, built from Alley's Algorithm Theoretical Basis Document with the ATBD's own values as the sheet's defaults. It is also the enhancement rock-art recorders know from DStretch.
DStretch's named enhancements are the same stretch in a different colour space. The space is the whole difference. The plugin's matrices for its variants are not published. The sheet instead offers the three published spaces under their own names: RGB, YUV (BT.601) and CIE L*a*b* with a declared white. It states what the variants do as an output geometry. After whitening, the spread along one hue's chroma axis and along lightness can be emphasised, with the hue on an ordinary wheel and four starting points (Even, Reds, Yellows, Dark & light). The output is red, green and blue at the target mean and spread, 127.5 and 50 by default, uncorrelated, in Float32. The full report of means, matrices and eigenvectors goes in the file's metadata and in the Statistics inspector. The values have no physical units, and the sheet says so.
The preview is the composite shader. The sheet fits the statistics once per change of bands or space on a decimated read. It recomposes the map for every other control and pushes one uniform. The map stays live to pan and zoom, and Run writes what the preview showed. On a Great Mural photograph the faint red figures come up hard against a cyan rock at Reds ×2, and the run finished in 138 ms. A JPEG stores its chroma at half resolution per 16 × 16 macroblock, and the stretch multiplies that by tens. A JPEG source therefore comes out blocky in colour. DStretch's own handout says to shoot RAW for the same reason.
Part 4
Towed-sensor surveys of the soil: the logger file recognised and cleaned stage by stage, inverted to conductivity against depth, drawn as a volume, and carried on to soil pits, substrate units and a factor layer for the land inventory. Gamma spectrometry and magnetometry share the shape and are anticipated at the reader.
ProximalBelow the surface
Point a logger export at Hachure and it recognises the instrument, works out the coordinate format, names each coil with the effective depth its separation gives, and produces three georeferenced products in one window: the measured points, an interpolated surface per channel, and an inverted conductivity-against-depth stack.
Every stage's effect is worth seeing before you commit to it, so the panel lays the pipeline out as a stack of stages. Every filter is a row that switches off, each with its own numbers on show: a motion filter with a speed ceiling in metres a second and a stationary threshold in metres, headland turns flagged. The pipeline re-runs on any change. Excluded records stay drawn in dark, and you can see where a filter bites. Stages run in order: parse and project, acquisition geometry, motion filter, range filter, ferrous interference, along-track despike, rolling mean, GNSS latency, sensor offset, instrument drift, temperature standardisation to 25 °C, calibration against reference profiles.
The file itself says which instrument wrote it, and the panel reads that. Each channel is named with the effective depth its coil separation gives, so VCP0.71 reads as 0.54 m with no conversion left in your head. Every forward model needs the coil height above ground, and most exports omit it. It is filled from the published typical for the recognised instrument, and its label says the figure is a published typical. Where the coordinate format has to be inferred, the panel states the inference and the evidence for it: values exceed ±90°, integer parts are four digits wide, values carry a hemisphere letter.
The inverted profile is a volume, so it is drawn as one: ray-marched, draped on the terrain, with the coil depths labelled down both axes and two section blades you drag in to cut the block open. Probe it and the readout gives easting, northing and depth, and says below the depth of investigation when that is where you are pointing. People misjudge layer thickness on an exaggerated view, and an unlabelled one actively misleads. The exaggeration factor stays on screen, both figures: the depth stretch and the terrain's own. Furniture that borrowed a colour from the transfer function would read as data. The chrome stays achromatic throughout. The block stops where the data does, clipped at the depth of investigation. A line says the half-space below the deepest boundary is an assumption of homogeneity and is left undrawn.
A misfit says the model reproduces the readings. It says nothing about whether a quite different model would have done equally well, and for EMI one very often would. Sounding Posterior answers that second question. Sampling the posterior under a single sounding gives the width of each layer's credible interval. Past a factor of ten, the data do not resolve that layer at all. Substrate Units then clusters the whole inverted column. It segments first so that the units come out spatially coherent. Ranking them against the handbook's coding turns them into an inventory factor layer. Plan Soil Pits grids, inverts and zones the survey in one act. It sites the pits as a ranked list by purpose. A budget cut from the bottom still leaves a usable set of each role.
Part 5
The parts every way of working shares: the layer tree and the project file, the Organiser that lists what imagery you have, the one Processing menu and the jobs it runs, the on-device assistant, and what the whole thing costs the machine while it works and while it waits.
LayersProjects & the Organiser
Every raster, vector overlay, polygon and annotation in a window is a row in one drag-reorderable tree, with groups, and an opacity and a blend mode per row. The base raster is a member of the stack like any other. The whole arrangement, several projects included, saves as a project file and reopens as it was.
Layers that cannot share a grid are not piled together. They group into projects by coordinate reference system, each labelled with its CRS. A NZTM survey and a UTM scene sit in separate groups until you reproject one. “Why will these not overlay?” becomes a question you answer by looking. A layer in another CRS is still drawn in place. The file on the target grid is only needed when something has to be written there.
A multi-band stack splits into one layer per band. Single-band layers on one grid recombine into a composite by reference, ordered red, green, blue, near-infrared and then by wavelength. The import uses the same rule, and two routes to one stack cannot disagree about which slot is red. A raster is recognised as an elevation model from its own evidence. It is labelled with a question mark where the file never said so, and you can state the answer either way on its row. A band split out of an image inherits the image's own disqualification.
Every other door into the app takes one selection at a time, so choosing between forty deliveries meant knowing what was in them already. The Organiser (⌥⌘O) lists the folders you keep imagery in, your Workspace and any you bookmark. Each row has a thumbnail in the viewer's own band choice, a name, and the handful of facts that decide which scene you want: satellite, level, date, format, grid, bands, CRS, pixel size, size on disk. A delivery is one row read from its manifest, and loose band files regroup into one row per grid. Every value says where it came from. A filename is a hint and a manifest is a statement. A value taken from a filename wears the amber badge. Double-click opens the scene through the same door as anywhere else, preflight sheet included. Rows and thumbnails are cached between launches under a byte cap set in Settings.
The longer tasks, a proximal survey through to pit locations on the GPS or a property's carbon-forestry baseline, are a dozen steps across several panels. A reference page answers one step at a time. GuideRail (⇧⌘G) is a window of ten authored rails. It shows a shelf of cards, each carrying a miniature of its progress. The rail itself is amber pegs on a horizontal traverse with the current station ringed. Every step names its real menu location. Ticked steps fold away, and future steps are stated but sealed. The current step is the first unticked one, and ticking ahead cannot skip work. Ticks persist between launches.
ProcessingHow work runs
Jobs do not block the viewer or change the source. Results arrive as new layers with their own provenance. Any whole-image job checks a memory ceiling before reading a pixel. An over-large job fails in a second, with the required and available figures on screen and an offer to run anyway. Paging for twenty minutes would have ended the same way.
The processing tools are one toolbar item with a submenu per category, each category keeping its glyph. When a command is greyed out the menu says why: Slope reads “is not an elevation model” against the layer it was asked about, Rank Substrate Units reads “run Substrate Units… first, then select its output”, and a capability that is declared but unbuilt reads “not built yet”. A category whose jobs consume a processing region states the region every such job will use. That region is the union of the polygons you selected and any vector layer flagged as a region.
Long jobs report progress and cancel cooperatively. The Jobs inspector lists what has run, how long it took, and traces of the cores, disk and GPU it used while it ran. Results are written to temporary files and opened as layers. That is what makes the menu feel immediate. Closing a window therefore lists any derived layer you have not saved, with a format for each, and offers Save, Don't Save or Cancel. The formats are all scientific containers: GeoTIFF, Cloud-Optimised GeoTIFF, KEA and ERDAS Imagine.
A question box over a journal of this session's questions and answers. Ask what wavelength Sentinel-2's B04 sits at, which bands make a colour-infrared composite of the scene that is open, what NDRE is computed from on this sensor, or where the pan-sharpening command lives and what its methods differ on. It runs on device. The questions and answers are working notes about somebody's imagery, and a log that outlived the session would be a store of them nobody asked for. The journal lives only as long as the window.
A wavelength wrong by 8 nm looks exactly like one that is right. A plausible menu path misleads more than no answer would. The assistant is therefore not allowed to answer from recollection. Two lookups back it: the sensor catalogue, for exact band wavelengths, widths, ground sample distances, spectral roles and index formulas; and a written guide to the interface, for where a control is and what it does. The model is instructed to quote what it was handed. When the catalogue does not hold something, it says so and lists what it does hold. Seeing the facts behind an answer is what turns a number you would otherwise have to check into one you can use. Every answer is shown with the catalogue rows it was built from underneath it.
It is handed a value describing the open scene's metadata: sensor, acquisition, bands and CRS. That value has nowhere to put a pixel, so the assistant could not read your data even if it were asked to. Where Apple Intelligence is unavailable on the machine, the panel says which reason applies.
ThroughputTime to a result
Each figure below is a whole job on a real scene, timed from open through read, compute, compress and write, with nothing prepared beforehand and held outside the clock. Where a rate is given it is megabytes of image data a second: source samples at their own width. That is what the algorithm reads. Bytes off disk would move with the codec. All of it was measured on one machine, a MacBook Pro with an M5 Pro, 18 cores and 64 GB of unified memory, in a release build. Another machine, another scene or another build will land somewhere else. Read the figures as a sense of scale.
Unsupervised classification
326MB/s
ISODATA over 553 megapixels and five bands on the Metal backend, end to end in 8.5 s: fit, assign every pixel, write the class raster and its attribute table. K-Means 376 MB/s, Gaussian mixture 330 MB/s. Every method gained 1.5 to 1.8× in September once GDAL's own decode pool reached the whole-band read the fit makes.
Seventeen-tile aerial mosaic
124MB/s
Seventeen 8000 × 12000 four-band tiles at 0.3 m onto one 32,000 × 60,000 grid: 7.68 billion samples planned, composited and written in 62.1 s.
Pan-sharpen, guide fitted per band
15.2s
A six-band Sentinel-2 20 m stack onto its four 10 m bands, at 5.2 cores. It ran in 30.6 s at 2.5 cores until the one-core stretch on the Jobs panel was traced to the VRT read and the decode pool was carried through to a VRT's sources. A single guide band: 4.35 s.
The products a VAT needs
1.7s
Hillshade, slope, positive openness and sky-view factor over a 34.6-megapixel 1 m LiDAR sheet, the horizon marches on the GPU. A relief re-shade of the same sheet after moving the sun: 1.11 s.
Against published mosaicking times There is no directly comparable published figure, so the mosaic rate is a sense of scale. The nearest recent work, Nie, Cui & Wan in Remote Sensing 2023, mosaics 48 Landsat-8 scenes, 55.28 GB across two UTM zones, on a Spark cluster of five blade servers: six-core Xeons, 32 GB each, 24 executor cores in total, 16 GB of Spark worker memory and 2 GB per executor. Their speed comparisons are against their own MPI and Spark baselines. ENVI appears in that paper as the quality reference, mosaicked for RMSE and SSIM.
Their throughput is volume divided by “the running time of the mosaicking algorithm”. The paper does not say whether blocking, HDFS ingest and the UTM to EPSG:4326 reprojection sit inside that time. The reprojection is described as done before the experiment, so probably not. Any rate taken from it is then a partial-pipeline number. The figure above is the other kind, and the write bounds it. Compositing finishes far ahead of a writer that is single-threaded by design, and the mosaic reaches only 1.27 of eighteen cores. The two times do not measure the same pipeline. The comparison can show the hardware published work has needed for this job. It cannot support a ratio.
Whole-image jobs stream in bounded blocks, so a raster larger than RAM is a longer job. Before any of that starts, the job checks a memory ceiling you set. An over-large run fails in a second with the required and available figures on screen. Every read opens on GDAL's own thread pool. On a 553-megapixel ZSTD scene that took a single decode pass from 4.30 s to 0.53 s at 11.8 cores in a release build. GDAL datasets are not thread-safe, and reads take one GDAL handle per worker. Tiled output is what makes out-of-order block writes safe. A decoded tile is written once, into memory the GPU reads directly. The old shape copied it into a fresh texture. A 105-tile viewport refill went from 7.8 ms to 1.0 ms when that copy left.
Every material job writes its own provenance into the result: the operation, the equation, the coefficients and which file the measurement belongs to. A topographic correction reports how much of the scene the DEM covered. A co-registration reports RMSE and peak ratio before and after. A DEM of Difference reports its level of detection. Results arrive as new layers and never overwrite a source.
The application is meant to stay open all day beside other work, so what it costs while idle was audited in September and measured before anything changed. With a key window and the mouse resting on it, the map view had been rebuilding every polygon path and vector transform 120 times a second. It now rebuilds its overlays only when something they read has changed. The pointer's position is one of the things they read. Flicker draws a frame only when its phase flips. The terrain and volume views pause their display links when their window is covered. Memory pressure is answered. On a warning every window releases the caches it can rebuild, and GDAL's block cache is held down until the pressure clears. The launch-time sweep of stale temporary files runs off the main thread. Nothing opts out of App Nap. One change was measured and left alone. Running jobs at utility priority would keep them off the performance cores. The same pan-sharpen took 13.5 s there against 4.7 s at the priority it keeps.
Inspector ▸ Info ▸ System reports the GPU and its Metal version, unified and GPU memory, the processing ceiling you set, and the live streaming state: tile size, resident tiles, tile-texture memory, which pyramid level is being drawn and how many source pixels that level is putting into each tile pixel. Beside it sit the display facts that change what you are seeing: screen resolution, backing scale, drawable size, refresh rate, render mode and EDR headroom.
Why is this scene soft? Because the pyramid level in use is decimating sixteen source pixels into each tile pixel. Zooming further will fetch the finer level. Why did that job refuse? Because the processing ceiling is set to 48 of 64 GB and the job wanted more. The panel shows that against the figure it was measured with. It is also the first place to look when a raster streams slowly: resident tiles climbing while tile-texture memory sits at the cache ceiling is a different problem from decode never finishing.
Band assignment, stretch, index maths, blend modes, relighting and relief shading are evaluated on the GPU at full resolution. Changing what you are looking at is never a job. There is no render to wait through, no downsampled proxy to work on, and no reason to commit to a band combination before you have tried three. One render pass per frame draws every layer. A parameter change is a uniform-buffer write. That is what the GPU is for here. It keeps examining a 30,000-pixel scene from ever becoming the slow part of the day.
Underneath, GDAL 3.13 provides format breadth and PROJ the coordinate maths. Both are vendored from source, pinned by version and checksum, and built for Apple silicon with a curated driver set. Their resources are embedded, and there is nothing to install alongside. One target touches GDAL's C API and no raw handle leaves it. Every call site checks the error state and throws a typed error. The whole package builds in Swift 6 with complete concurrency checking. The test suite stands at 4,266 tests across eleven targets. That figure equals the number of declared tests, and it can be checked.
CreditsStanding on
A licence list maintained by hand drifts, so the audit below is generated from the manifest of archives merged at build time. It re-runs whenever a version pin changes.
GPL code linked
0
No GPL anywhere in the binary.
LGPL linked statically
0
The one LGPL component in the process is Apple's system libiconv, loaded from the OS like any other Mac app.
Proprietary SDKs
0
The driver set is curated by licence. That rules out ECW, MrSID, FileGDB and Kakadu.
Third-party Swift packages
0
Everything builds on Apple frameworks, GDAL and PROJ. Holding to those three keeps this list short.
The KEA format is an HDF5-backed raster format from Landcare Research New Zealand and Aberystwyth University, by Sam Gillingham and Peter Bunting. It carries raster attribute tables and arbitrary band metadata that a GeoTIFF handles awkwardly or not at all. That is why it is one of the containers Hachure offers when you save a derived layer.
Data, and what its licence asks for Toitū Te Whenua Land Information New Zealand: aerial imagery, elevation, and the Topo50 1:50,000 map-sheet index and topographic tiles, all licensed CC BY 4.0. That licence requires attribution, so it appears in the app beneath the map that draws it, and here. Natural Earth (1:110 m and 1:10 m physical and cultural vectors, via nvkelso/natural-earth-vector) is public domain and backs the world map in the import picker. Apple MapKit provides the overview basemap where no national topographic service covers the ground.
Imagery used to build this page comes from the European Space Agency and the European Commission (Copernicus Sentinel-2, 2025), the U.S. Geological Survey and NASA (Landsat 4 and Landsat 8), Airbus Defence and Space (SPOT 6), and LINZ (aerial photography and LiDAR). The multi-coil electromagnetic-induction survey is an open example dataset in the channel convention EMagPy uses (McLachlan, Blanchy & Binley, 2020), which the proximal reader follows. The terrain recipes were transcribed from the Relief Visualization Toolbox's published sources (ZRC SAZU).
Apple frameworks do the rest of the work: Metal and MetalFX for rendering, MPSGraph for GPU Fourier transforms, Accelerate and vDSP for the CPU filters and the RTI fit, Swift Charts for the spectral profile and the time series, Core Location and MapKit for the overview, Image I/O for rendered export, CryptoKit for source-file digests, and Foundation Models for the on-device assistant. The project links no third-party Swift package. That constraint is why this list is as short as it is.
ReferencesWhat the methods come from
Where a panel offers a method, the method has a paper behind it and the code says which. These are the principal sources. The repository's own notes carry the rest, including the assessments of methods that were read and deliberately not built.
Imagery on this page is rendered from the project's own test data: Sentinel-2 L2A and Landsat 4 / 8 scenes over north-west Nelson and Golden Bay, New Zealand aerial photography and LiDAR published by Land Information New Zealand under CC BY 4.0, a SPOT 6 multispectral product, and an open multi-coil EMI survey. Each figure states its sensor, bands, ground sample distance and date.