or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

algorithms.mdcommand-line.mdeds-tomography.mdevaluation.mdfile-io.mdindex.mdvisualization.md

eds-tomography.mddocs/

0

# EDS Tomography

1

2

Specialized functionality for energy-dispersive X-ray spectroscopy (EDS) tomography including preprocessing, reconstruction interface with GENFIRE, postprocessing tools, and characteristic X-ray emission analysis for quantitative elemental mapping.

3

4

## Capabilities

5

6

### Characteristic X-ray Emission

7

8

Functions for analyzing characteristic X-ray emission lines and fluorescence data using the Elam database.

9

10

```python { .api }

11

def GetElamFluorescenceLines(element, emission_type='Ka'):

12

"""

13

Get fluorescence lines from Elam database for specified element.

14

15

Parameters:

16

- element: str, chemical element symbol (e.g., 'Fe', 'Cu')

17

- emission_type: str, X-ray emission type ('Ka', 'Kb', 'La', 'Lb', 'Ma')

18

19

Returns:

20

dict: Dictionary containing:

21

- 'energies': numpy.ndarray, emission line energies (keV)

22

- 'intensities': numpy.ndarray, relative intensities

23

- 'transitions': list, transition labels

24

"""

25

26

def GetFluorescenceLineEnergy(element, transition):

27

"""

28

Get specific fluorescence line energy for element and transition.

29

30

Parameters:

31

- element: str, chemical element symbol

32

- transition: str, specific transition (e.g., 'Ka1', 'Kb1')

33

34

Returns:

35

float: Emission line energy in keV

36

"""

37

38

def GetWeightedSum(spectra, weights):

39

"""

40

Calculate weighted sum of spectral data.

41

42

Parameters:

43

- spectra: numpy.ndarray, spectral data array

44

- weights: numpy.ndarray, weighting factors

45

46

Returns:

47

numpy.ndarray: Weighted sum spectrum

48

"""

49

```

50

51

### Bruker System Integration

52

53

Functions for working with Bruker EDS system data including tilt series and spatial/energy calibration.

54

55

```python { .api }

56

def GetTiltsFromBrukerSequence(sequence_file):

57

"""

58

Extract tilt angles from Bruker sequence file.

59

60

Parameters:

61

- sequence_file: str, path to Bruker sequence file

62

63

Returns:

64

numpy.ndarray: Array of tilt angles in degrees

65

"""

66

67

def GetSpatialDimension(bruker_data):

68

"""

69

Get spatial dimension information from Bruker data.

70

71

Parameters:

72

- bruker_data: dict, Bruker data structure

73

74

Returns:

75

dict: Spatial calibration information including:

76

- 'pixel_size': tuple, (x_size, y_size) in physical units

77

- 'units': str, spatial units

78

- 'dimensions': tuple, (width, height) in pixels

79

"""

80

81

def GetEnergyDimension(bruker_data):

82

"""

83

Get energy dimension calibration from Bruker data.

84

85

Parameters:

86

- bruker_data: dict, Bruker data structure

87

88

Returns:

89

dict: Energy calibration information including:

90

- 'energy_scale': numpy.ndarray, energy values for each channel

91

- 'energy_offset': float, energy offset (keV)

92

- 'energy_gain': float, energy per channel (keV/channel)

93

- 'num_channels': int, number of energy channels

94

"""

95

96

def ExtractRawSignalsFromBrukerSequence(sequence_file, output_path):

97

"""

98

Extract raw EDS signals from Bruker sequence file.

99

100

Parameters:

101

- sequence_file: str, path to Bruker sequence file

102

- output_path: str, directory for extracted signals

103

104

Returns:

105

dict: Extraction results including:

106

- 'num_projections': int, number of tilt projections

107

- 'signal_files': list, paths to extracted signal files

108

- 'metadata': dict, acquisition metadata

109

"""

110

```

111

112

### Data Preprocessing

113

114

Comprehensive preprocessing functions for EDS tomography data preparation including spatial binning, normalization, and alignment.

115

116

```python { .api }

117

def BinEDSSpatialDimensions(eds_data, bin_factor):

118

"""

119

Bin EDS spatial dimensions to reduce data size and improve SNR.

120

121

Parameters:

122

- eds_data: numpy.ndarray, 4D EDS data (tilts, y, x, energy)

123

- bin_factor: int or tuple, binning factor for spatial dimensions

124

125

Returns:

126

numpy.ndarray: Spatially binned EDS data

127

"""

128

129

def ExtractSignalsFromEMD(emd_file, element_list, energy_windows=None):

130

"""

131

Extract elemental signals from EMD EDS data file.

132

133

Parameters:

134

- emd_file: str, path to EMD file containing EDS data

135

- element_list: list, chemical elements to extract

136

- energy_windows: dict, custom energy windows for each element

137

138

Returns:

139

dict: Dictionary with element names as keys and signal arrays as values

140

"""

141

142

def NormalizeSignals(signal_data, method='dose'):

143

"""

144

Normalize EDS signal intensities across projections.

145

146

Parameters:

147

- signal_data: numpy.ndarray, 3D signal data (tilts, y, x)

148

- method: str, normalization method ('dose', 'total_counts', 'background')

149

150

Returns:

151

numpy.ndarray: Normalized signal data

152

"""

153

154

def GetNormalizationCurve(signal_data, reference_region=None):

155

"""

156

Calculate normalization curve for intensity correction.

157

158

Parameters:

159

- signal_data: numpy.ndarray, signal data to analyze

160

- reference_region: tuple, (y_slice, x_slice) for reference region

161

162

Returns:

163

numpy.ndarray: Normalization factors for each projection

164

"""

165

166

def ReadImageJTranslations(translation_file):

167

"""

168

Read translation data from ImageJ alignment results.

169

170

Parameters:

171

- translation_file: str, path to ImageJ translation file

172

173

Returns:

174

numpy.ndarray: Translation vectors (N, 2) for (x, y) shifts

175

"""

176

177

def ReadTomVizTranslations(translation_file):

178

"""

179

Read translation data from TomViz alignment results.

180

181

Parameters:

182

- translation_file: str, path to TomViz translation file

183

184

Returns:

185

numpy.ndarray: Translation vectors (N, 2) for (x, y) shifts

186

"""

187

188

def ApplyTranslations(signal_data, translations):

189

"""

190

Apply translation corrections to signal data.

191

192

Parameters:

193

- signal_data: numpy.ndarray, 3D signal data (tilts, y, x)

194

- translations: numpy.ndarray, translation vectors from alignment

195

196

Returns:

197

numpy.ndarray: Translation-corrected signal data

198

"""

199

```

200

201

### File I/O for Reconstruction

202

203

Functions for interfacing with tomographic reconstruction software and managing intermediate data files.

204

205

```python { .api }

206

def WriteSignalsToTIFFs(signal_data, output_dir, element_name):

207

"""

208

Write signal projections to TIFF files for external processing.

209

210

Parameters:

211

- signal_data: numpy.ndarray, 3D signal data (tilts, y, x)

212

- output_dir: str, output directory path

213

- element_name: str, element identifier for file naming

214

215

Returns:

216

list: Paths to written TIFF files

217

"""

218

219

def ReadSignalsFromTIFFs(tiff_dir, pattern='*.tiff'):

220

"""

221

Read signal projections from TIFF files.

222

223

Parameters:

224

- tiff_dir: str, directory containing TIFF files

225

- pattern: str, file pattern for matching TIFF files

226

227

Returns:

228

numpy.ndarray: 3D signal data array (tilts, y, x)

229

"""

230

231

def WriteMetaDataFiles(metadata, output_dir):

232

"""

233

Write metadata files for reconstruction software.

234

235

Parameters:

236

- metadata: dict, reconstruction metadata including angles, pixel sizes

237

- output_dir: str, output directory path

238

"""

239

240

def ReadMetaDataFiles(metadata_dir):

241

"""

242

Read metadata files from reconstruction directory.

243

244

Parameters:

245

- metadata_dir: str, directory containing metadata files

246

247

Returns:

248

dict: Reconstruction metadata

249

"""

250

251

def WriteSignalsToGENFIRE(signal_data, angles, output_file, **kwargs):

252

"""

253

Write signals in GENFIRE-compatible format for reconstruction.

254

255

Parameters:

256

- signal_data: numpy.ndarray, 3D signal data (tilts, y, x)

257

- angles: numpy.ndarray, tilt angles in degrees

258

- output_file: str, output file path

259

- **kwargs: additional GENFIRE parameters

260

"""

261

```

262

263

### Postprocessing

264

265

Functions for processing reconstruction results and extracting quantitative information.

266

267

```python { .api }

268

def ReadGENFIRESignals(results_file):

269

"""

270

Read GENFIRE reconstruction results.

271

272

Parameters:

273

- results_file: str, path to GENFIRE results file

274

275

Returns:

276

dict: Dictionary containing:

277

- 'reconstruction': numpy.ndarray, 3D reconstructed volume

278

- 'error_metrics': dict, reconstruction quality metrics

279

- 'parameters': dict, reconstruction parameters used

280

"""

281

282

def SquareCropSignal(signal_data, crop_size=None):

283

"""

284

Square crop signal data around center.

285

286

Parameters:

287

- signal_data: numpy.ndarray, input signal data

288

- crop_size: int, size of square crop region

289

290

Returns:

291

numpy.ndarray: Square-cropped signal data

292

"""

293

```

294

295

## Usage Examples

296

297

### Complete EDS Tomography Workflow

298

299

```python

300

import ncempy.edstomo as eds

301

import numpy as np

302

303

# 1. Extract signals from Bruker data

304

sequence_file = 'eds_tilt_series.bcf'

305

raw_signals = eds.ExtractRawSignalsFromBrukerSequence(sequence_file, './raw_data/')

306

307

# 2. Load and preprocess EDS data

308

emd_file = 'eds_data.emd'

309

elements = ['Fe', 'O', 'Ti']

310

signals = eds.ExtractSignalsFromEMD(emd_file, elements)

311

312

# 3. Bin spatially to improve SNR

313

for element in elements:

314

signals[element] = eds.BinEDSSpatialDimensions(signals[element], bin_factor=2)

315

316

# 4. Normalize signals

317

for element in elements:

318

signals[element] = eds.NormalizeSignals(signals[element], method='dose')

319

320

# 5. Apply alignment corrections if available

321

translations = eds.ReadImageJTranslations('alignment_results.txt')

322

for element in elements:

323

signals[element] = eds.ApplyTranslations(signals[element], translations)

324

325

# 6. Prepare for reconstruction

326

tilt_angles = eds.GetTiltsFromBrukerSequence(sequence_file)

327

for element in elements:

328

eds.WriteSignalsToGENFIRE(signals[element], tilt_angles,

329

f'genfire_input_{element}.h5')

330

331

print(f"Preprocessed {len(elements)} elements for reconstruction")

332

print(f"Tilt series: {len(tilt_angles)} projections from {tilt_angles.min():.1f}° to {tilt_angles.max():.1f}°")

333

```

334

335

### Characteristic X-ray Analysis

336

337

```python

338

import ncempy.edstomo as eds

339

import matplotlib.pyplot as plt

340

341

# Analyze characteristic X-rays for iron

342

iron_lines = eds.GetElamFluorescenceLines('Fe', 'Ka')

343

print(f"Iron Ka lines: {iron_lines['transitions']}")

344

print(f"Energies: {iron_lines['energies']} keV")

345

346

# Get specific line energy

347

ka1_energy = eds.GetFluorescenceLineEnergy('Fe', 'Ka1')

348

print(f"Fe Ka1 energy: {ka1_energy:.3f} keV")

349

350

# Plot characteristic X-ray spectrum

351

plt.figure(figsize=(10, 6))

352

for i, (energy, intensity, transition) in enumerate(zip(

353

iron_lines['energies'], iron_lines['intensities'], iron_lines['transitions'])):

354

plt.vlines(energy, 0, intensity, colors='red', alpha=0.7)

355

plt.text(energy, intensity + 0.1, transition, rotation=90, ha='center')

356

357

plt.xlabel('Energy (keV)')

358

plt.ylabel('Relative Intensity')

359

plt.title('Iron Ka Characteristic X-ray Lines')

360

plt.grid(True, alpha=0.3)

361

plt.show()

362

```

363

364

### Multi-Element Signal Extraction

365

366

```python

367

import ncempy.edstomo as eds

368

import matplotlib.pyplot as plt

369

370

# Define elements and energy windows

371

elements = ['Fe', 'Ti', 'O', 'C']

372

energy_windows = {

373

'Fe': (6.2, 6.6), # Fe Ka region

374

'Ti': (4.4, 4.7), # Ti Ka region

375

'O': (0.4, 0.7), # O Ka region

376

'C': (0.2, 0.4) # C Ka region

377

}

378

379

# Extract signals from EDS data

380

eds_file = 'multielement_eds.emd'

381

signals = eds.ExtractSignalsFromEMD(eds_file, elements, energy_windows)

382

383

# Display signal maps for first projection

384

fig, axes = plt.subplots(2, 2, figsize=(12, 10))

385

axes = axes.flatten()

386

387

for i, element in enumerate(elements):

388

signal_map = signals[element][0] # First projection

389

im = axes[i].imshow(signal_map, cmap='hot')

390

axes[i].set_title(f'{element} Signal Map')

391

plt.colorbar(im, ax=axes[i])

392

393

plt.tight_layout()

394

plt.show()

395

396

# Print signal statistics

397

for element in elements:

398

signal = signals[element]

399

print(f"{element}: {signal.shape[0]} projections, "

400

f"total counts = {signal.sum():.0f}")

401

```

402

403

### Data Preprocessing Pipeline

404

405

```python

406

import ncempy.edstomo as eds

407

import numpy as np

408

409

# Load raw EDS data

410

raw_data = load_eds_data() # Shape: (tilts, y, x, energy)

411

412

# 1. Spatial binning

413

binned_data = eds.BinEDSSpatialDimensions(raw_data, bin_factor=(2, 2))

414

print(f"Binned from {raw_data.shape} to {binned_data.shape}")

415

416

# 2. Extract elemental signals

417

elements = ['Fe', 'Ni', 'Cr']

418

signals = {}

419

for element in elements:

420

# Get characteristic energy for element

421

ka_energy = eds.GetFluorescenceLineEnergy(element, 'Ka1')

422

423

# Extract signal in energy window around Ka line

424

energy_window = (ka_energy - 0.2, ka_energy + 0.2)

425

signals[element] = extract_signal_window(binned_data, energy_window)

426

427

# 3. Normalize signals

428

normalization_curves = {}

429

for element in elements:

430

normalization_curves[element] = eds.GetNormalizationCurve(signals[element])

431

signals[element] = eds.NormalizeSignals(signals[element])

432

433

# 4. Apply alignment if available

434

if alignment_file_exists:

435

translations = eds.ReadImageJTranslations('alignment.txt')

436

for element in elements:

437

signals[element] = eds.ApplyTranslations(signals[element], translations)

438

439

# 5. Write preprocessed data

440

for element in elements:

441

eds.WriteSignalsToTIFFs(signals[element], './preprocessed/', element)

442

443

print("Preprocessing complete")

444

```

445

446

### Reconstruction Interface

447

448

```python

449

import ncempy.edstomo as eds

450

import subprocess

451

452

# Prepare data for GENFIRE reconstruction

453

element = 'Fe'

454

signal_data = preprocessed_signals[element]

455

tilt_angles = np.array([-60, -45, -30, -15, 0, 15, 30, 45, 60])

456

457

# Write GENFIRE input file

458

genfire_file = f'genfire_input_{element}.h5'

459

eds.WriteSignalsToGENFIRE(signal_data, tilt_angles, genfire_file,

460

iterations=50, oversample=3)

461

462

# Write metadata files

463

metadata = {

464

'angles': tilt_angles,

465

'pixel_size': 0.5, # nm

466

'element': element

467

}

468

eds.WriteMetaDataFiles(metadata, './reconstruction/')

469

470

print(f"GENFIRE input prepared: {genfire_file}")

471

print(f"Ready for reconstruction with {len(tilt_angles)} projections")

472

473

# After GENFIRE reconstruction completes...

474

results = eds.ReadGENFIRESignals('genfire_results.h5')

475

reconstruction = results['reconstruction']

476

477

print(f"Reconstruction shape: {reconstruction.shape}")

478

print(f"Reconstruction quality metrics: {results['error_metrics']}")

479

480

# Postprocess reconstruction

481

cropped_recon = eds.SquareCropSignal(reconstruction, crop_size=256)

482

```

483

484

### Batch Processing Multiple Elements

485

486

```python

487

import ncempy.edstomo as eds

488

import os

489

490

# Process multiple elements in batch

491

elements = ['Fe', 'Ni', 'Cr', 'Ti']

492

input_dir = './raw_eds_data/'

493

output_dir = './processed_signals/'

494

495

os.makedirs(output_dir, exist_ok=True)

496

497

for element in elements:

498

print(f"Processing {element}...")

499

500

# Load element-specific data

501

element_file = os.path.join(input_dir, f'{element}_eds.emd')

502

if os.path.exists(element_file):

503

signals = eds.ExtractSignalsFromEMD(element_file, [element])

504

505

# Preprocess

506

signals[element] = eds.NormalizeSignals(signals[element])

507

508

# Save processed signals

509

output_file = os.path.join(output_dir, f'{element}_processed.tiff')

510

eds.WriteSignalsToTIFFs(signals[element], output_dir, element)

511

512

print(f" Processed {signals[element].shape[0]} projections")

513

else:

514

print(f" Skipping {element} - file not found")

515

516

print("Batch processing complete")

517

```