CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-ncempy

A comprehensive collection of algorithms and routines for electron microscopy data analysis and simulation.

Pending
Overview
Eval results
Files

eds-tomography.mddocs/

EDS Tomography

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.

Capabilities

Characteristic X-ray Emission

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

def GetElamFluorescenceLines(element, emission_type='Ka'):
    """
    Get fluorescence lines from Elam database for specified element.
    
    Parameters:
    - element: str, chemical element symbol (e.g., 'Fe', 'Cu')
    - emission_type: str, X-ray emission type ('Ka', 'Kb', 'La', 'Lb', 'Ma')
    
    Returns:
    dict: Dictionary containing:
        - 'energies': numpy.ndarray, emission line energies (keV)
        - 'intensities': numpy.ndarray, relative intensities
        - 'transitions': list, transition labels
    """

def GetFluorescenceLineEnergy(element, transition):
    """
    Get specific fluorescence line energy for element and transition.
    
    Parameters:
    - element: str, chemical element symbol
    - transition: str, specific transition (e.g., 'Ka1', 'Kb1')
    
    Returns:
    float: Emission line energy in keV
    """

def GetWeightedSum(spectra, weights):
    """
    Calculate weighted sum of spectral data.
    
    Parameters:
    - spectra: numpy.ndarray, spectral data array
    - weights: numpy.ndarray, weighting factors
    
    Returns:
    numpy.ndarray: Weighted sum spectrum
    """

Bruker System Integration

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

def GetTiltsFromBrukerSequence(sequence_file):
    """
    Extract tilt angles from Bruker sequence file.
    
    Parameters:
    - sequence_file: str, path to Bruker sequence file
    
    Returns:
    numpy.ndarray: Array of tilt angles in degrees
    """

def GetSpatialDimension(bruker_data):
    """
    Get spatial dimension information from Bruker data.
    
    Parameters:
    - bruker_data: dict, Bruker data structure
    
    Returns:
    dict: Spatial calibration information including:
        - 'pixel_size': tuple, (x_size, y_size) in physical units
        - 'units': str, spatial units
        - 'dimensions': tuple, (width, height) in pixels
    """

def GetEnergyDimension(bruker_data):
    """
    Get energy dimension calibration from Bruker data.
    
    Parameters:
    - bruker_data: dict, Bruker data structure
    
    Returns:
    dict: Energy calibration information including:
        - 'energy_scale': numpy.ndarray, energy values for each channel
        - 'energy_offset': float, energy offset (keV)
        - 'energy_gain': float, energy per channel (keV/channel)
        - 'num_channels': int, number of energy channels
    """

def ExtractRawSignalsFromBrukerSequence(sequence_file, output_path):
    """
    Extract raw EDS signals from Bruker sequence file.
    
    Parameters:
    - sequence_file: str, path to Bruker sequence file
    - output_path: str, directory for extracted signals
    
    Returns:
    dict: Extraction results including:
        - 'num_projections': int, number of tilt projections
        - 'signal_files': list, paths to extracted signal files
        - 'metadata': dict, acquisition metadata
    """

Data Preprocessing

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

def BinEDSSpatialDimensions(eds_data, bin_factor):
    """
    Bin EDS spatial dimensions to reduce data size and improve SNR.
    
    Parameters:
    - eds_data: numpy.ndarray, 4D EDS data (tilts, y, x, energy)
    - bin_factor: int or tuple, binning factor for spatial dimensions
    
    Returns:
    numpy.ndarray: Spatially binned EDS data
    """

def ExtractSignalsFromEMD(emd_file, element_list, energy_windows=None):
    """
    Extract elemental signals from EMD EDS data file.
    
    Parameters:
    - emd_file: str, path to EMD file containing EDS data
    - element_list: list, chemical elements to extract
    - energy_windows: dict, custom energy windows for each element
    
    Returns:
    dict: Dictionary with element names as keys and signal arrays as values
    """

def NormalizeSignals(signal_data, method='dose'):
    """
    Normalize EDS signal intensities across projections.
    
    Parameters:
    - signal_data: numpy.ndarray, 3D signal data (tilts, y, x)
    - method: str, normalization method ('dose', 'total_counts', 'background')
    
    Returns:
    numpy.ndarray: Normalized signal data
    """

def GetNormalizationCurve(signal_data, reference_region=None):
    """
    Calculate normalization curve for intensity correction.
    
    Parameters:
    - signal_data: numpy.ndarray, signal data to analyze
    - reference_region: tuple, (y_slice, x_slice) for reference region
    
    Returns:
    numpy.ndarray: Normalization factors for each projection
    """

def ReadImageJTranslations(translation_file):
    """
    Read translation data from ImageJ alignment results.
    
    Parameters:
    - translation_file: str, path to ImageJ translation file
    
    Returns:
    numpy.ndarray: Translation vectors (N, 2) for (x, y) shifts
    """

def ReadTomVizTranslations(translation_file):
    """
    Read translation data from TomViz alignment results.
    
    Parameters:
    - translation_file: str, path to TomViz translation file
    
    Returns:
    numpy.ndarray: Translation vectors (N, 2) for (x, y) shifts
    """

def ApplyTranslations(signal_data, translations):
    """
    Apply translation corrections to signal data.
    
    Parameters:
    - signal_data: numpy.ndarray, 3D signal data (tilts, y, x)
    - translations: numpy.ndarray, translation vectors from alignment
    
    Returns:
    numpy.ndarray: Translation-corrected signal data
    """

File I/O for Reconstruction

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

def WriteSignalsToTIFFs(signal_data, output_dir, element_name):
    """
    Write signal projections to TIFF files for external processing.
    
    Parameters:
    - signal_data: numpy.ndarray, 3D signal data (tilts, y, x)
    - output_dir: str, output directory path
    - element_name: str, element identifier for file naming
    
    Returns:
    list: Paths to written TIFF files
    """

def ReadSignalsFromTIFFs(tiff_dir, pattern='*.tiff'):
    """
    Read signal projections from TIFF files.
    
    Parameters:
    - tiff_dir: str, directory containing TIFF files
    - pattern: str, file pattern for matching TIFF files
    
    Returns:
    numpy.ndarray: 3D signal data array (tilts, y, x)
    """

def WriteMetaDataFiles(metadata, output_dir):
    """
    Write metadata files for reconstruction software.
    
    Parameters:
    - metadata: dict, reconstruction metadata including angles, pixel sizes
    - output_dir: str, output directory path
    """

def ReadMetaDataFiles(metadata_dir):
    """
    Read metadata files from reconstruction directory.
    
    Parameters:
    - metadata_dir: str, directory containing metadata files
    
    Returns:
    dict: Reconstruction metadata
    """

def WriteSignalsToGENFIRE(signal_data, angles, output_file, **kwargs):
    """
    Write signals in GENFIRE-compatible format for reconstruction.
    
    Parameters:
    - signal_data: numpy.ndarray, 3D signal data (tilts, y, x)
    - angles: numpy.ndarray, tilt angles in degrees
    - output_file: str, output file path
    - **kwargs: additional GENFIRE parameters
    """

Postprocessing

Functions for processing reconstruction results and extracting quantitative information.

def ReadGENFIRESignals(results_file):
    """
    Read GENFIRE reconstruction results.
    
    Parameters:
    - results_file: str, path to GENFIRE results file
    
    Returns:
    dict: Dictionary containing:
        - 'reconstruction': numpy.ndarray, 3D reconstructed volume
        - 'error_metrics': dict, reconstruction quality metrics
        - 'parameters': dict, reconstruction parameters used
    """

def SquareCropSignal(signal_data, crop_size=None):
    """
    Square crop signal data around center.
    
    Parameters:
    - signal_data: numpy.ndarray, input signal data
    - crop_size: int, size of square crop region
    
    Returns:
    numpy.ndarray: Square-cropped signal data
    """

Usage Examples

Complete EDS Tomography Workflow

import ncempy.edstomo as eds
import numpy as np

# 1. Extract signals from Bruker data
sequence_file = 'eds_tilt_series.bcf'
raw_signals = eds.ExtractRawSignalsFromBrukerSequence(sequence_file, './raw_data/')

# 2. Load and preprocess EDS data
emd_file = 'eds_data.emd'
elements = ['Fe', 'O', 'Ti']
signals = eds.ExtractSignalsFromEMD(emd_file, elements)

# 3. Bin spatially to improve SNR
for element in elements:
    signals[element] = eds.BinEDSSpatialDimensions(signals[element], bin_factor=2)

# 4. Normalize signals
for element in elements:
    signals[element] = eds.NormalizeSignals(signals[element], method='dose')

# 5. Apply alignment corrections if available
translations = eds.ReadImageJTranslations('alignment_results.txt')
for element in elements:
    signals[element] = eds.ApplyTranslations(signals[element], translations)

# 6. Prepare for reconstruction
tilt_angles = eds.GetTiltsFromBrukerSequence(sequence_file)
for element in elements:
    eds.WriteSignalsToGENFIRE(signals[element], tilt_angles, 
                             f'genfire_input_{element}.h5')

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

Characteristic X-ray Analysis

import ncempy.edstomo as eds
import matplotlib.pyplot as plt

# Analyze characteristic X-rays for iron
iron_lines = eds.GetElamFluorescenceLines('Fe', 'Ka')
print(f"Iron Ka lines: {iron_lines['transitions']}")
print(f"Energies: {iron_lines['energies']} keV")

# Get specific line energy
ka1_energy = eds.GetFluorescenceLineEnergy('Fe', 'Ka1')
print(f"Fe Ka1 energy: {ka1_energy:.3f} keV")

# Plot characteristic X-ray spectrum
plt.figure(figsize=(10, 6))
for i, (energy, intensity, transition) in enumerate(zip(
    iron_lines['energies'], iron_lines['intensities'], iron_lines['transitions'])):
    plt.vlines(energy, 0, intensity, colors='red', alpha=0.7)
    plt.text(energy, intensity + 0.1, transition, rotation=90, ha='center')

plt.xlabel('Energy (keV)')
plt.ylabel('Relative Intensity')
plt.title('Iron Ka Characteristic X-ray Lines')
plt.grid(True, alpha=0.3)
plt.show()

Multi-Element Signal Extraction

import ncempy.edstomo as eds
import matplotlib.pyplot as plt

# Define elements and energy windows
elements = ['Fe', 'Ti', 'O', 'C']
energy_windows = {
    'Fe': (6.2, 6.6),  # Fe Ka region
    'Ti': (4.4, 4.7),  # Ti Ka region  
    'O': (0.4, 0.7),   # O Ka region
    'C': (0.2, 0.4)    # C Ka region
}

# Extract signals from EDS data
eds_file = 'multielement_eds.emd'
signals = eds.ExtractSignalsFromEMD(eds_file, elements, energy_windows)

# Display signal maps for first projection
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
axes = axes.flatten()

for i, element in enumerate(elements):
    signal_map = signals[element][0]  # First projection
    im = axes[i].imshow(signal_map, cmap='hot')
    axes[i].set_title(f'{element} Signal Map')
    plt.colorbar(im, ax=axes[i])

plt.tight_layout()
plt.show()

# Print signal statistics
for element in elements:
    signal = signals[element]
    print(f"{element}: {signal.shape[0]} projections, "
          f"total counts = {signal.sum():.0f}")

Data Preprocessing Pipeline

import ncempy.edstomo as eds
import numpy as np

# Load raw EDS data
raw_data = load_eds_data()  # Shape: (tilts, y, x, energy)

# 1. Spatial binning
binned_data = eds.BinEDSSpatialDimensions(raw_data, bin_factor=(2, 2))
print(f"Binned from {raw_data.shape} to {binned_data.shape}")

# 2. Extract elemental signals
elements = ['Fe', 'Ni', 'Cr']
signals = {}
for element in elements:
    # Get characteristic energy for element
    ka_energy = eds.GetFluorescenceLineEnergy(element, 'Ka1')
    
    # Extract signal in energy window around Ka line
    energy_window = (ka_energy - 0.2, ka_energy + 0.2)
    signals[element] = extract_signal_window(binned_data, energy_window)

# 3. Normalize signals
normalization_curves = {}
for element in elements:
    normalization_curves[element] = eds.GetNormalizationCurve(signals[element])
    signals[element] = eds.NormalizeSignals(signals[element])

# 4. Apply alignment if available  
if alignment_file_exists:
    translations = eds.ReadImageJTranslations('alignment.txt')
    for element in elements:
        signals[element] = eds.ApplyTranslations(signals[element], translations)

# 5. Write preprocessed data
for element in elements:
    eds.WriteSignalsToTIFFs(signals[element], './preprocessed/', element)

print("Preprocessing complete")

Reconstruction Interface

import ncempy.edstomo as eds
import subprocess

# Prepare data for GENFIRE reconstruction
element = 'Fe'
signal_data = preprocessed_signals[element]
tilt_angles = np.array([-60, -45, -30, -15, 0, 15, 30, 45, 60])

# Write GENFIRE input file
genfire_file = f'genfire_input_{element}.h5'
eds.WriteSignalsToGENFIRE(signal_data, tilt_angles, genfire_file,
                         iterations=50, oversample=3)

# Write metadata files
metadata = {
    'angles': tilt_angles,
    'pixel_size': 0.5,  # nm
    'element': element
}
eds.WriteMetaDataFiles(metadata, './reconstruction/')

print(f"GENFIRE input prepared: {genfire_file}")
print(f"Ready for reconstruction with {len(tilt_angles)} projections")

# After GENFIRE reconstruction completes...
results = eds.ReadGENFIRESignals('genfire_results.h5')
reconstruction = results['reconstruction']

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

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

Batch Processing Multiple Elements

import ncempy.edstomo as eds
import os

# Process multiple elements in batch
elements = ['Fe', 'Ni', 'Cr', 'Ti']
input_dir = './raw_eds_data/'
output_dir = './processed_signals/'

os.makedirs(output_dir, exist_ok=True)

for element in elements:
    print(f"Processing {element}...")
    
    # Load element-specific data
    element_file = os.path.join(input_dir, f'{element}_eds.emd')
    if os.path.exists(element_file):
        signals = eds.ExtractSignalsFromEMD(element_file, [element])
        
        # Preprocess
        signals[element] = eds.NormalizeSignals(signals[element])
        
        # Save processed signals
        output_file = os.path.join(output_dir, f'{element}_processed.tiff')
        eds.WriteSignalsToTIFFs(signals[element], output_dir, element)
        
        print(f"  Processed {signals[element].shape[0]} projections")
    else:
        print(f"  Skipping {element} - file not found")

print("Batch processing complete")

Install with Tessl CLI

npx tessl i tessl/pypi-ncempy

docs

algorithms.md

command-line.md

eds-tomography.md

evaluation.md

file-io.md

index.md

visualization.md

tile.json