Image and acquisition I/O#
Use quantem.gpu.io for 4D-STEM acquisitions and quantem.widget image readers
for survey images. The QuantEM.GPU I/O guide owns the detector
storage, supported formats, metadata, backend, and exactness contracts.
For a walkthrough of uint8/uint16, memory estimates and the image readers,
start with IO/GPU; GPU selection and cleanup are in
Memory management.
Open an acquisition and inspect a pattern#
from quantem.gpu import detector, io
from quantem.widget import Show2D, Show4DSTEM
data = io.load("scan_master.h5")
Show4DSTEM(data)
data is a quantem.gpu.io.Dataset4dstemGPU, ANS encoded on the CUDA device or
the Apple GPU at native detector sampling and count dtype: a 512 x 512 x 192 x 192
uint16 scan, 18 GiB as a dense array, occupies about 0.1 to 2 GiB. Keep it open
while viewers or calculations use its encoded buffers. Array-style selection
decodes only the selected region into a Torch tensor on the acquisition’s GPU;
it does not unpack the complete acquisition:
Show2D(data[10, 12])
Expression |
Selection |
|---|---|
|
One diffraction pattern |
|
A rectangular scan patch |
|
A detector crop at one position |
|
One detector pixel across the scan |
|
Scientific calibration and source metadata |
Show2D([detector.bf(data), detector.adf(data)], labels=["BF", "ADF"])
io.save("scan.qem", data)
Call data.close() after the last use. Scripted jobs can use
with io.load(path) as data: for automatic cleanup. A list of paths loads as a
list of encoded acquisitions, one per file; Show4DSTEM(io.load(paths)) opens
them as a comparison grid labelled by file, and Show4DSTEM(series[1]) opens
one of them. io.load(path, backend="cuda", device=1) selects a CUDA device; a
Mac loads onto MPS. See load for the function reference and the GPU
guide for multi-device storage policies.
Read a scan region#
Reconstruction, denoise and ROI workflows read the rectangular scan region they
need. read decodes that region into a Torch tensor on the acquisition’s GPU:
with io.load("scan_master.h5") as data:
patch_t = data.read(scan_region=(160, 293, 234, 367)) # row_start, row_stop, col_start, col_stop
print(patch_t.shape) # torch.Size([133, 133, 192, 192])
Stops are exclusive, and detector_region= bounds the detector pixels the same
way. For a drift-corrected time series, derive scan_region from the shared
specimen ROI, the frame shift and a small scan halo, then sample the final ROI
from the local patch. The detector counts remain raw; drift stays as
scan-position metadata.
Discover acquisitions#
from quantem.gpu import io
from quantem.widget import Show4DSTEM
files = io.discover("/data/session")
Show4DSTEM(io.load(files[0]))
io.discover(path, scan_shape=(512, 512)) keeps only matching acquisitions when
a folder mixes scan sizes. io.inspect(path) reads readiness and calibration
headers without decoding measurements. Use Show4DSTEM.from_folder(path) for a
live acquisition viewer.
For named sample data, see Tutorial datasets. The IO/GPU notebook demonstrates a real Gold image session.
Read images and image stacks#
from quantem.widget import Show2D, Show3D, read_image, read_images, read_image_stack
image = read_image("overview.tif")
Show2D(image)
images = read_images("survey_images", workers=8)
Show2D(images)
stack = read_image_stack("frames", file_type="tif", workers=8)
Show3D(stack)
These format readers run on the host. Calibrated image inputs retain their sampling for viewer scale bars. This path is for individual images and image sequences, not compressed 4D-STEM detector acquisitions.
Image function reference#
- quantem.widget.read_image(path: str | Path) Dataset2d | RgbImage#
Return a single image from disk (grayscale or true-color RGB).
One reader for every survey-image format the lab produces:
.npy- raw array, no calibration..emd- Velox HAADF (image underData/Image/<hash>/Datawith a JSON metadata blob carrying the pixel size); falls back to the largest 2D dataset for non-Velox EMD layouts (e.g. adata/drift/dataseries)..tif/.tiff/.png/.jpg/.bmp/.gif- via Pillow. Color PNG/JPEG/TIFF keep RGB (RgbImagewith shape(H, W, 3)); they are not converted to a single gray channel. Pass the result toShow2DorShow3Dto display true color..dm3/.dm4- Gatan, via ncempy.
Grayscale results are
Dataset2d. Color results areRgbImage(duck-types the.array/.name/.samplingsurface Show2D already unwraps). A multi-frame container is reduced to its first frame.Examples
>>> from quantem.widget import Show2D, io >>> Show2D(io.read_image("figure_rgb.png")) # true color, not gray
- quantem.widget.read_images(folder: str | Path, *, workers: int = 1, progress: bool = False) list[Dataset2d]#
Read every image in a folder into a list of
Dataset2d.The folder analog of
read_image()for a mixed set of survey images - different formats and different sizes that cannot stack into one cube (useread_image_stack()for a folder of same-size frames). Files are sorted by name; every supported extension is read, anything else is skipped. Lets a gallery be one line:Show2D([d.array for d in io.read_images(folder)]).- Parameters:
folder (str or Path) – Folder containing supported 2D image files.
workers (int, default 1) – Thread count for reading many files. Use
workers=8for large folders of independent EMD/TIFF/PNG survey images.progress (bool, default False) – Show a tqdm bar while reading.
- quantem.widget.read_image_stack(path: str | Path, *, file_type: str | None = None, pattern: str | None = None, workers: int = 8, progress: bool = True) Dataset3d#
Decode a folder of image frames into a
Dataset3din parallel.A directory of PNG/TIFF/EMD/DM/NPY frames - an in-situ time series, a tilt series, a reconstruction sweep - is read with a thread pool into one contiguous
(N, H, W)float32 array, then wrapped soShow3D(read_image_stack(dir))scrubs the frames with no extra arguments. Frames are sorted naturally (frame_2beforeframe_10). Decode is threaded because PIL/tifffile release the GIL during the C decode, so N threads give near-linear speedup until I/O or memory bandwidth saturates; ~8 workers is optimal on most disks. When the first frame is a calibrated format (EMD/DM), its pixel sampling and units carry onto the stack’s spatial axes soShow3Ddraws a physical scale bar.- Parameters:
path (str or Path) – Folder containing the image frames.
file_type (str, optional) – Extension filter (e.g.
"png","tif"). When omitted every common image extension in the folder is taken.pattern (str, optional) – Glob within the folder (e.g.
"frame_*.png"); overridesfile_type.workers (int, default 8) – Thread count for parallel decompression.
progress (bool, default True) – Show a tqdm bar while decoding.
- Returns:
Shape
(N, H, W), dtype float32. Sampling defaults to pixels since a bare image folder carries no calibration.- Return type:
Dataset3d