# Gap Analysis¶

This example explains the procedure that is necessary to analyse a gap (e.g.
a superconducting gap) from an ARPES spectrum with `arpys`

.

Throughout the example we will assume that we have a file ‘spectrum.p’
containing the ARPES spectrum and ‘gold.p’ with the corresponding gold
reference data, and that they have been loaded with
`load_data()`

and saved as `D`

and `G`

respectively.
Also, the `dataloading`

and `postprocessing`

modules have been loaded:

```
from arpys import dl,pp
```

## 1. Adjust Fermi level¶

First off, we need to precisely determine the Fermi level (which can vary
across angular channels).
This is done by fitting a Fermi-Dirac distribution convoluted by a Gaussian
to simulate the instrument resolution to each EDC.
Often it helps to add some additional linear components to the fit function,
as is done in `fermi_fit_func()`

.

### 1.1 Fermi fit¶

This process is automated in `fig_gold_array()`

(the more convenient method of using `fit_gold()`

relies on a specific organization of the data within `G`

and is therefore
less recommended).
If we know that the energies lie along `G.xscale`

and the shape of
`G.data`

is `(1, n_angles, n_energies)`

we would do:

```
levels, sigmas, slopes, offsets, functions = pp.fit_gold_array(G.data[0],
G.xscale, ef, T)
```

where `ef`

is a starting guess for the Fermi level and `T`

is the
temperature at which the spectrum was taken.

Note

If the shape of `G.data`

differs from the above, we would need to
reorganize it first. Ultimately,
`fit_gold_array()`

expects a 2d array of shape
`(n_angles, n_energies)`

.

Confer the documentation of `fit_gold_array()`

for
explanation of its output.
You will mostly need the `levels`

only, but all the other output is useful
for checking whether the fit worked reasonably.

Note

You may notice that the execution of the above command may take some
time.
This is because there are `n_angles`

fitting procedures that need
to be carried out.
If you have confirmed that the fitting worked reasonably well, it is
therefore a good idea to store the result in some form, and just load it
in again, whenever needed, instead of always carrying out the fit.
One way of achieving this is by using `pickle`

:

```
import pickle
with open('my_file_to_store_gold_fit_results.p', 'wb') as f :
pickle.dump(levels, f)
```

The `levels`

can then be loaded by:

```
with open('my_file_to_store_gold_fit_results.p', 'rb') as f :
levels = pickle.load(f)
```

Of course you can store more than just the levels.
This is a nice way of storing arbitrary python objects (however, some
objects cannot be *pickled*, like for example the `functions`

).

`arpys`

provides two convenience functions to save you some typing:
`dump()`

and `load_pickle()`

.

### 1.2 Smoothing¶

Since the `levels`

are usually quite noisy, it is recommended to apply some
operation to get a *nicer* curve. One way is to smoothen it (e.g. using
`arpys.postprocessing.smooth()`

) or to fit a polynomial to the `levels`

.
The following figure shows what this could look like.

### 1.3 Applying to data¶

Once we have our levels, we can use them to *straighten* our Fermi level in
the spectrum.
If we just want to plot the data, we can apply the `levels`

continuously,
with the helper function `adjust_fermi_level()`

,
which returns an energy mesh of shape `(n_energies, n_angles)`

that can be
given to the `pcolormesh()`

function.

However, if we are interested in further analysis (which we are in this
example), we need to apply the energy shifts discretely, in pixel units (the
follwoing assumes the same structure of `D`

as we had for `G`

before and
`levels`

is the smoothened result of section 1.2 Smoothing):

```
pixel_shifts = pp.get_pixel_shifts(G.xscale, levels)
data, cutoff = pp.apply_pixel_shifts(D.data[0], pixel_shifts)
```

## 2. Finding \(k_\mathrm{F}\)¶

As a next step, in order to extract the EDCs at \(k_\mathrm{F}\), we need
to find it (them, actually, as there is one to the left and one to the right
in this example) by fitting Lorentzians to the MDC at \(E_\mathrm{F}\).
Useful functions in that context are
`indexof()`

to get the index of the Fermi energy,
`lorentzian()`

and of course scipy’s
`scipy.optimize.curve_fit()`

.

Note

At this point you can of course work in pixel, angular or k coordinates,
your choice.
Be reminded of `arpys.postprocessing.angle_to_k()`

for the conversion
to k space.

The details of the fit can be left up to you. It can be helpful to try fitting only the relevant region along k, as can be seen in the figure, where the fit only considered the region where the black lines are drawn.

## 3. EDC extraction and processing¶

Now that we know \(k_\mathrm{F}\), we can extract the EDCs from the data (as indicated in the figure above), subtract background and symmetrize.

### 3.1 Background subtraction¶

Of course, different situations may require different treatments of the background. Here are two common possibilities:

- Extract an EDC in a band-free region of the data, possibly smoothen it and use that as the background.
`subtract_bg_matt()`

. A simple and intuitive method that has proven useful.

### 3.2 Symmetrization¶

Finally, you can use `arpys.postprocessing.symmetrize_linear()`

to
symmetrize the EDC around \(E_\mathrm{F}\):

```
sym_edc, sym_energy = pp.symmetrize_linear(edc, ef_index, energies)
```