Import
import { createScientificLibrary, renderScientificPlane } from 'purejsimage/scientific'
import { gsfReader } from 'purejsimage/scientific/readers/gsf'Minimal Node.js example
import { createScientificLibrary, renderScientificPlane } from 'purejsimage/scientific'
import { createScientificPathContext } from 'purejsimage/scientific/node'
import { gsfReader } from 'purejsimage/scientific/readers/gsf'
const science = createScientificLibrary({ readers: [gsfReader] })
const document = await science.open(await createScientificPathContext('surface.gsf'))
const dataset = await document.openDataset(document.datasets[0].id)
const display = await renderScientificPlane(dataset, {
plane: { displayAxes: ['x', 'y'], fixedIndices: [] },
range: { mode: 'dataset' },
palette: 'viridis',
relief: { azimuth: 315, elevation: 45, strength: 0.5 },
})
for await (const pixels of display.pixels) console.log(pixels.data)Minimal browser example
import { createScientificLibrary } from 'purejsimage/scientific'
import { createScientificFileContext } from 'purejsimage/scientific/browser'
import { gsfReader } from 'purejsimage/scientific/readers/gsf'
const input = document.querySelector<HTMLInputElement>('#surface')
const file = input?.files?.[0]
if (!file) throw new Error('Choose a GSF file')
const science = createScientificLibrary({ readers: [gsfReader] })
const document = await science.open(createScientificFileContext(file))
const dataset = await document.openDataset(document.datasets[0].id)
for await (const block of dataset.readPlane({ displayAxes: ['x', 'y'], fixedIndices: [] })) {
console.log(dataset.descriptor.sampleType) // float32
}Supported features
| Feature | Support |
|---|---|
| Gwyddion Simple Field 1.0 | Read and write |
| Samples | Little-endian float32 |
| Physical metadata | X/Y extent, offsets, units, title |
| Unknown header fields | Retained |
| Regions | Bounded row reads |
Dataset mapping
XRes and YRes become labeled spatial axes x and y. XReal / XRes and YReal / YRes become their physical steps. ZUnits becomes the scalar component unit. Samples remain float32.
Bounded reads
The small text header is read first. Region reads calculate each selected row offset and return bounded RasterBlock values. The writer accepts the complete sample array because writing requires the complete output.
Display rendering
renderScientificPlane() maps the quantitative values into RGB display blocks. Percentiles use bounded approximate sampling. Relief is display hillshading, not a quantitative surface-slope measurement. The current relief calculation uses sample coordinates and does not apply physical X/Y spacing.
Unsupported features
Multiple fields, alternate sample types, compressed wrappers, charting, contour plots, and AFM analysis are not implemented. Extra trailing bytes and malformed headers reject.