Source code for ncempy.edstomo.bruker

import sys, os, shutil
from collections import OrderedDict
import glob2 as glob
import numpy as np
import hyperspy.api as hs
from ncempy.io.emd import fileEMD

[docs]def GetTiltsFromBrukerSequence(Directory=None): ''' Find the set of Bruker bcf files and figure out their tilts based on filenames. There should be a set of bcf files in a directory with names: ... -10.bcf, -5.bcf, 0.bcf, 5.bcf ... The number represents the stage tilt of that stack. The angles do not matter but the names must be coded as above. They will be automatically read and sorted. Parameters: Directory (str): Name of directory containing the bcf files. Returns: (list of floats): A list of tilt angles. ''' Bcfs = glob.glob(os.path.join(Directory, '*.bcf')) NewBcfs = [] for i in Bcfs: _ , FileName = os.path.split(i) NewBcfs.append(FileName) Tilts = list(map(lambda s: float(s[:-4]), NewBcfs)) Tilts.sort() return Tilts
[docs]def GetSpatialDimension(Dim): ''' Return a spatial value in meters. ''' unit = Dim.units if unit == 'nm': scalefac = 1e-9 elif unit == 'µm': scalefac = 1e-6 elif unit == 'mm': scalefac = 1e-3 elif unit == 'cm': scalefac = 1e-2 else: print('Unrecognized spatial dimension unit in Bruker file: ' + unit) scalefac = 1 Axis = Dim.index2value(range(Dim.size)) return Axis * scalefac
[docs]def GetEnergyDimension(Dim): ''' Return an energy value in eV. ''' unit = Dim.units if str(unit) == 'eV': scalefac = 1 elif str(unit) == str('keV'): scalefac = 1e3 elif unit == 'MeV': scalefac = 1e6 else: print('Unrecognized energy dimension unit in Bruker file: ' + unit) scalefac = 1 Axis = Dim.index2value(range(Dim.size)) return Axis * scalefac
[docs]def ExtractRawSignalsFromBrukerSequence(InputDirectory=None, OutputEMD=None): ''' Read in a set of Bruker bcf files containing EDS acquisitions and write an EMD file with the data. Parameters: InputDirectory (str): Name of directory containing the bcf files. OutputEMD (str): Name of the output file (may include a path). Returns: None. ''' # Find all the bcf files first. Tilts = GetTiltsFromBrukerSequence(Directory=InputDirectory) Tilts = np.array(Tilts) # We need some filename if none was given to us. if OutputEMD is None: OutputEMD = 'test.emd' print('Extracting Signals:') for i, t in enumerate(Tilts): # Load the bruker file for this tilt. fname = os.path.join(InputDirectory, str(int(t))+'.bcf') x = hs.load(fname) # Only the first time, we need to calculate the sizes of all the arrays we are going to make. if 'HAADFsize_m' not in locals(): # HAADF's have x,y dimensions. HAADFsize_m = GetSpatialDimension(x[0].axes_manager['width']) HAADFsize_n = GetSpatialDimension(x[0].axes_manager['height']) HAADFDim = (len(Tilts), len(HAADFsize_m), len(HAADFsize_n)) print('HAADF has dimensions ' + str(HAADFDim)) # EDS cubes have x,y, energy dimensions. EDSsize_m = GetSpatialDimension(x[1].axes_manager['width']) EDSsize_n = GetSpatialDimension(x[1].axes_manager['height']) EDSsize_e = GetEnergyDimension(x[1].axes_manager['Energy']) EDSDim = (len(Tilts), len(EDSsize_m), len(EDSsize_n), len(EDSsize_e)) print('EDS has dimensions ' + str(EDSDim)) HAADF = np.zeros(HAADFDim) EDS = np.zeros(EDSDim, dtype='float32') BeamEnergy = x[0].metadata['Acquisition_instrument']['TEM']['beam_energy']*1000 # eV EnergyResolutionMnKa = x[1].metadata['Acquisition_instrument']['TEM']['Detector']['EDS']['energy_resolution_MnKa'] # eV DetectorTiltAngle = x[1].metadata['Acquisition_instrument']['TEM']['Detector']['EDS']['elevation_angle'] # degrees RealTime = x[1].metadata['Acquisition_instrument']['TEM']['Detector']['EDS']['real_time'] # seconds print(str(fname)) HAADF[i,:,:] = x[0].data.astype("float32") EDS[i,:,:,:] = x[1].data.astype("float32") # open nonexisting file for writing if os.path.isfile(OutputEMD): os.remove(OutputEMD) EMD = fileEMD(OutputEMD) data = HAADF dims = ( (Tilts, 'angle', '[deg]'), (HAADFsize_m, 'x', '[m]'), (HAADFsize_n, 'y', '[m]')) print('Writing HAADF tilt stack.') EMD.put_emdgroup('HAADF_TiltStack', data, dims) data = EDS dims = ( (Tilts, 'angle', '[deg]'), (EDSsize_m, 'x', '[m]'), (EDSsize_n, 'y', '[m]'), (EDSsize_e, 'E', '[eV]')) print('Writing EDS tilt stack.') EMD.put_emdgroup('EDS_TiltStack', data, dims) EMD.microscope.attrs['BeamVoltage[eV]'] = BeamEnergy EMD.microscope.attrs['MnKaResolution[eV]'] = EnergyResolutionMnKa EMD.microscope.attrs['DetectorTiltAngle[deg]'] = DetectorTiltAngle EMD.microscope.attrs['RealTime[s]'] = RealTime * len(Tilts) EMD.put_comment('File created.') del EMD print('Created file ' + OutputEMD)