Migrating from EasySpin 5 to EasySpin 6

EasySpin 6 is significantly improved over EasySpin 5, but also introduces a series of breaking, backwards-incompatible changes (for a complete list, see the release notes). This means that some scripts built for EasySpin 5.x need to be adapted to run with EasySpin 6.

This user guide focuses on how EasySpin 5 scripts need to be modified to run with EasySpin 6. It does not introduce the many new features of EasySpin 6 or discuss any of the many bug fixes.

The major changes include the following topics:

EasySpin 5 runs on releases R2007b and newer. EasySpin 6 supports MATLAB releases starting from R2021b, but might run on older releases as well.

Single-crystal simulations

The field Exp.CrystalOrientation has been replaced by Exp.SampleFrame, and the Euler angle definition has been inverted.

Exp.CrystalOrientation = [5 10 -48]*pi/180;  % EasySpin 5
Exp.SampleFrame = [48 -10 -5]*pi/180;        % EasySpin 6

In EasySpin 6, the Euler angles in Exp.SampleFrame describe the transformation from the laboratory frame to the sample/crystal frame, and not vice versa as it used to be for Exp.CrystalOrientation.

The crystal frame is now more generally called the sample frame, since it also applies to non-crystal samples such as oriented films. See the documentation on frames for details.

An additional change is that in order to run a single-crystal simulation, you have to provide at least either the molecular frame orientation in Exp.MolFrame (i.e. the orientation of the spin center within the crystal) or the crystal space group in Exp.CrystalSymmetry, or both. Just providing Exp.SampleFrame is not sufficient.

Exp.MolFrame = [0 45 0]*pi/180;   % from sample frame to molecular frame
Exp.CrystalSymmetry = 'P4mm';     % crystal space group

Finally, there is the new field Exp.SampleRotation, which provides a simple interface for rotating a sample. All you need to do is provide the rotation axis (defined in the lab frame) and the rotation angle(s).

Exp.SampleRotation = {'x',45*pi/180};  % rotation by 45 degrees around the lab x axis
Exp.SampleRotation = {'x',(0:30:180)*pi/180};  % a series of rotations
Exp.SampleRotation = {[1 1 0],45*pi/180};  % rotation around the lab axis [1 1 0]

The EasySpin 5 function rotatecrystal, which was provided for this, is no longer available. EasySpin 6 provides rotateframe.

Powder averaging

In EasySpin 5, the grid size for a powder simulation was specified using Opt.nKnots. In EasySpin 6, this field has been renamed to Opt.GridSize. The content of the field is unchanged.

Opt.nKnots = 10;    % EasySpin 5
Opt.GridSize = 10;  % EasySpin 6

Opt.nKnots = [10 3];    % EasySpin 5
Opt.GridSize = [10 3];  % EasySpin 6

Also, the field name for the grid symmetry has changed from Opt.Symmetry to Opt.GridSymmetry:

Opt.Symmetry = 'Ci';      % EasySpin 5
Opt.GridSymmetry = 'Ci';  % EasySpin 6

See the documentation for pepper and other simulation functions for details.

Subspectra

In EasySpin 6, you can obtain the subspectra of individual transitions or orientations using Opt.separate:

Opt.separate = '';              % total spectrum
Opt.separate = 'components';    % subspectra of all sample components
Opt.separate = 'transitions';   % subspectra of all EPR transitions (powders only)
Opt.separate = 'sites';         % subspectra for all crystal sites
Opt.separate = 'orientations';  % subspectra for all crystal orientations

The field Opt.Output from EasySpin 5 is no longer supported.

See the documentation for pepper and other simulation functions for details.

Least-squares fitting

The interface to esfit has changed completely, with the goal of making the function more flexible and broadly applicable. See the userguide for least-squares fitting and the reference page for more details.

Two major changes are (i) the data is now provided as the first input and the model function as second, and (ii) the inputs to the EasySpin functions are grouped together in cell arrays:

esfit('pepper',spc,Sys0,varySys,Exp);     % EasySpin 5
esfit(spc,@pepper,{Sys0,Exp},{varySys});  % EasySpin 6

With EasySpin 6, you can also vary and fit experimental parameters (e.g. the microwave phase). This was not possible with EasySpin 5:

varyExp.mwPhase = pi/4;
esfit(spc,@pepper,{Sys0,Exp0},{varySys,varyExp});

You can provide lower and upper bounds for the parameters, instead of a symmetric range around the starting values.

esfit(spc,@pepper,{Sys0,Exp},{varySys});           # symmetric range
esfit(spc,@pepper,{Sys0,Exp},{loSys},{upSys});     # lower and upper bounds

You can use esfit for fitting arbitrary user-defined (non-EasySpin) models that depend on an array of parameters. Here is a partial example for a stretched exponential:

model = @(p) p(1)*exp(-(t/p(2)).^p(3));  % model function
esfit(data,model,par0,parlo,parup);

The output has changed as well. If called with an output, esfit returns a structure containing information about the fitted parameters, the goodness-of-fit, the uncertainty, the fitted model, etc.

fit = esfit(data,model,par0,parlo,parhi)
    fit = 
    struct with fields:
  
                pfit: [3×1 double]
              pnames: {3×1 cell}
           pfit_full: [3×1 double]
             argsfit: []
                pstd: [3×1 double]
                ci95: [3×2 double]
                 cov: [3×3 double]
                corr: [3×3 double]
             p_start: [3×1 double]
              fitraw: [1001×1 double]
                 fit: [1001×1 double]
               scale: 1
            baseline: [1001×1 double]
                mask: [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ÿ ]
           residuals: [1001×1 double]
                 ssr: 2.1874e-07
                rmsd: 1.4782e-05
      bestfithistory: [1×1 struct]

Some options have changed as well. Instead of FitOpt.Scaling, use FitOpt.AutoScale. For details, see the documentation for esfit.

Hamiltonian functions

All functions that return hamiltonians have been renamed. The full hamiltonian function sham is now called ham.

B0 = [0;0;350];    % magnetic field, mT
H = sham(Sys,B0);  % EasySpin 5
H = ham(Sys,B0);   % EasySpin 6

Functions that return specific terms have been renamed to all start with ham_: ham_ez for electron Zeeman interaction, ham_nz for nuclear Zeeman interaction, ham_zf for zero-field interaction, ham_hf for hyperfine interaction, ham_nq for nuclear quadrupole interaction, ham_ee for electron-electron interaction, ham_nn for nucleus-nucleus interaction, ham_oz for orbital Zeeman interaction, ham_so for spin-orbit coupling, ham_cf for crystal field terms,

Here are a few examples:

% Hyperfine
Hhf = hfine(Sys);   % EasySpin 5
Hhf = ham_hf(Sys);  % EasySpin 6

% Zero=field interaction
Hzf = zfield(Sys);    % EasySpin 5
Hzf = ham_zf(Sys);    % EasySpin 6

% Electron-electron interaction
Hee = eeint(Sys);    % EasySpin 5
Hee = ham_ee(Sys);   % EasySpin 6

If called without a magnetic field, the Zeeman functions ham_ez and ham_nz (as well as ham) now return the three components of the magnetic dipole moment:

[H0,mux,muy,muz] = ham(Sys);
[mue_x,mue_y,mue_z] = ham_ez(Sys);

In EasySpin 5, the functions returned the negative of the magnetic dipole moment components.

Spin-polarized systems

In EasySpin 5, spin-polarized systems (like photoexcited triplets) were partially supported. Input for the spin populations was via Exp.Temperature. In EasySpin 6, support for spin-polarized systems has been substantially extended, and the spin population input is now via Sys.initState. See the user guide for details.

Here is an example of a spin triplet populated via inter-system crossing:

Exp.Temperature = [0.2 0.3 0.5];        % EasySpin 5
Sys.initState = {[0.2 0.3 0.5],'xyz'};  % EasySpin 6
Pulse EPR simulations

The pulse EPR simulation function saffron has been extended significantly. It now supports general pulse sequences, including shaped pulses, detection windows, frequency sweeps, and more. Therefore, many input parameters in the Exp and Opt structures are new. EasySpin 5 inputs are still supported to some degree.

Here is an example of the extensions. The field Exp.Sequence previously allowed only a few pre-defined pulse sequence. In EasySpin 6, it allows you to specify user-defined pulse sequences, including shaped pulses.

Exp.Sequence = {p90, tau, p180, tau};  % user-defined pulse sequence

For details see the user guides (part 1 and part 2) as well as the reference page for saffron and the examples.

Also, the output has changed. For two-dimensional experiments, saffron now returns the axes as a single output in a cell array and not as two separate outputs.

[t1,t2,data] = saffron(Sys,Exp,Opt);    % EasySpin 5
[t12,data] = saffron(Sys,Exp,Opt);      % t12 = {t1,t2}  % EasySpin 6
Electron-electron couplings

The field Sys.eeD, used in EasySpin 5 to specify dipolar coupling tensors between electron spins, is now renamed to Sys.dip.

Sys.eeD = [1 1 -2]*40;    % EasySpin 5
Sys.dip = [1 1 -2]*40;    % EasySpin 6
Spherical grids

sphgrid, the function that constructs spherical grids, now returns all grid information (angles, vectors, weights, etc.) in a single structure.

grid = sphgrid('D2h',10)
    grid = 
    struct with fields:
  
       Symmetry: 'D2h'
       GridSize: 3
      closedPhi: 1
       nOctants: 1
         maxPhi: 1.5708
            phi: [0 0 1.5708 0 0.7854 1.5708]
          theta: [0 0.7854 0.7854 1.5708 1.5708 1.5708]
           vecs: [3×6 double]
        weights: [0.9566 3.4004 3.4004 1.2022 2.4045 1.2022]

sphtri, the function that provides a grid triangulation, has been removed. Its functionality is now integrated into sphgrid:

[grid,tri] = sphgrid('Ci',5);  % returns triangulation as second output
Microwave mode and polarization

The two fields Exp.Mode and Exp.mwPolarization have been merged into a single field, Exp.mwMode.

For resonator experiments, use:

Exp.Mode = 'parallel';    % EasySpin 5
Exp.mwMode = 'parallel';  % EasySpin 6

For beam experiments, Exp.mwMode takes the same two-element cell array as Exp.Mode, but the second element can be set to 'unpolarized' etc, which previously required Exp.mwPolarization:

Exp.Mode = {k,alpha};    % EasySpin 5
Exp.mwMode = {k,alpha};  % EasySpin 6

Exp.Mode = {k,0};   % EasySpin 5
Exp.mwPolarization = 'unpolarized';  % EasySpin 5

Exp.mwMode = {k,'unpolarized'};  % EasySpin 6

Other changes