IO — Quick Demo#
Load any electron microscopy file with one line. IO.file() returns an IOResult that every widget accepts directly.
[1]:
try:
%load_ext autoreload
%autoreload 2
%env ANYWIDGET_HMR=1
except Exception:
pass
env: ANYWIDGET_HMR=1
[2]:
import numpy as np
import tempfile, pathlib
from quantem.widget import IO, Show2D, Show3D
Single file#
[3]:
# Create a synthetic HRTEM image and save as .npy
rng = np.random.default_rng(42)
size = 256
y, x = np.mgrid[:size, :size]
img = np.zeros((size, size), dtype=np.float32)
for freq, angle in [(0.08, 0.0), (0.06, np.pi / 3), (0.10, np.pi / 6)]:
img += np.cos(2 * np.pi * freq * (x * np.cos(angle) + y * np.sin(angle)))
r = np.sqrt((x - size // 2)**2 + (y - size // 2)**2)
img *= 1.0 / (1 + np.exp(-0.05 * (size // 3 - r)))
img += rng.normal(0, 0.3, (size, size)).astype(np.float32)
tmp = tempfile.mkdtemp()
npy_path = pathlib.Path(tmp) / "hrtem.npy"
np.save(npy_path, img)
result = IO.file(npy_path)
print(result)
Show2D(result, title="HRTEM (from .npy)", cmap="gray")
IOResult
shape: 256 x 256
dtype: float32
title: hrtem
[3]:
Multiple files → stack#
[4]:
# Save a focal series as separate .npy files
paths = []
for i in range(5):
defocus = (i - 2) * 0.5
frame = img * np.cos(defocus * r * 0.02).astype(np.float32)
frame += rng.normal(0, 0.2, (size, size)).astype(np.float32)
p = pathlib.Path(tmp) / f"focal_{i:03d}.npy"
np.save(p, frame)
paths.append(p)
result = IO.file(paths)
print(result)
Show3D(result, title="Focal Series")
IOResult
shape: 5 x 256 x 256
dtype: float32
title: tmpnu_giu2w
labels: ['focal_000', 'focal_001', 'focal_002', ...] (5 total)
[4]:
Folder → stack#
[5]:
# Save PNGs to a folder, then load the whole folder
from PIL import Image
png_dir = pathlib.Path(tmp) / "png_series"
png_dir.mkdir(exist_ok=True)
for i in range(4):
frame = img + rng.normal(0, 0.4, (size, size)).astype(np.float32)
arr_u8 = np.clip((frame - frame.min()) / (frame.max() - frame.min()) * 255, 0, 255).astype(np.uint8)
Image.fromarray(arr_u8).save(png_dir / f"frame_{i:03d}.png")
result = IO.folder(png_dir, file_type="png")
print(result)
Show3D(result, title="PNG Folder")
IOResult
shape: 4 x 256 x 256
dtype: float32
title: png_series
labels: ['frame_000', 'frame_001', 'frame_002', 'frame_003']
[5]:
IOResult duck typing#
IOResult forwards NumPy methods — use .sum(), .mean(), .shape, etc. directly.
[6]:
result = IO.folder(png_dir, file_type="png")
print(f"shape: {result.shape}")
print(f"mean: {result.mean():.2f}")
print(f"dtype: {result.dtype}")
# Collapse stack to mean projection
mean_proj = result.mean(axis=0)
Show2D(mean_proj, title="Mean Projection")
shape: (4, 256, 256)
mean: 124.10
dtype: float32
[6]:
Supported formats#
[7]:
IO.supported_formats()
[7]:
['ali',
'app5',
'asw',
'bcf',
'blo',
'bmp',
'csv',
'de5',
'dens',
'dib',
'dm3',
'dm4',
'eds',
'elid',
'emd',
'emi',
'ems',
'emsa',
'gif',
'h5',
'hdf5',
'hspy',
'img',
'jpe',
'jpeg',
'jpg',
'map',
'mas',
'mib',
'mrc',
'mrcz',
'msa',
'msp',
'nc',
'npy',
'npz',
'nxs',
'pbm',
'pcx',
'pgm',
'png',
'ppm',
'pro',
'prz',
'pts',
'rpl',
'ser',
'spc',
'spd',
'spi',
'spx',
'sur',
'tif',
'tiff',
'tvf',
'tvips',
'unf',
'wdf',
'xbm',
'xml',
'zspy']