Polygon masking

Use a polygon mask to retain measured intensity inside a selected momentum-space region. This example starts with a converted three-dimensional data array and uses the first Brillouin zone as the boundary.

Python

Select the constant energy surface. Then calculate the ordered zone vertices from the real-space lattice and apply the polygon mask:

import numpy as np

import erlab
import erlab.analysis as era

binding_energy = -0.2
energy_width = 0.02
lattice_constant = 6.97

constant_energy_map = data.qsel(
    eV=binding_energy,
    eV_width=energy_width,
)
real_space_basis = lattice_constant * np.array(
    [
        [1.0, 0.0],
        [-0.5, np.sqrt(3) / 2],
    ]
)
first_bz_vertices = erlab.lattice.get_2d_vertices(
    real_space_basis,
    reciprocal=False,
    rotate=30.0,
)
masked_map = era.mask.mask_with_polygon(
    constant_energy_map,
    first_bz_vertices,
    dims=("kx", "ky"),
)

Plot the source map and masked result with common color limits. Close the vertex list only for drawing the boundary. erlab.analysis.mask.mask_with_polygon() closes the mask polygon automatically:

import matplotlib.pyplot as plt
import erlab.plotting as eplt

closed_vertices = np.vstack([first_bz_vertices, first_bz_vertices[0]])
_, axes = plt.subplots(
    1,
    2,
    figsize=(6.4, 3.0),
    layout="compressed",
    sharex=True,
    sharey=True,
)
for ax, map_data in zip(
    axes,
    (constant_energy_map, masked_map),
    strict=True,
):
    eplt.plot_array(
        map_data,
        ax=ax,
        cmap="Greys",
        gamma=0.5,
        aspect="equal",
    )
axes[0].plot(
    closed_vertices[:, 0],
    closed_vertices[:, 1],
    color="tab:red",
)
eplt.unify_clim(axes)
eplt.clean_labels(axes)
eplt.set_titles(axes, ["First Brillouin zone", "Masked data"])

(Source code)

Repeated-zone constant energy surface with the first Brillouin-zone boundary beside the intensity retained inside that zone

The 30° rotation aligns the Γ–M direction with \(k_x\) for this model. Points outside the first Brillouin zone become missing values. Use invert=True to mask the zone instead. Use drop=True to remove coordinate labels for rows and columns that contain no retained values. See Brillouin zone overlay for other zone overlays.

Figure Composer

Start with the same three-dimensional data array, binding energy, energy width, and lattice constant used in the Python procedure. Figure Composer does not calculate a polygon mask. Create the derived array in ImageTool before you assemble the figure.

ImageTool calculation

  1. Open data in a managed ImageTool.

  2. Choose Edit ‣ Select Data…. For eV, select qsel, enter -0.2, enable Width, and enter 0.02. Set Result Placement to Open Child Window.

  3. Calculate first_bz_vertices with the lattice calculation in the Python section.

  4. In the constant-energy-map child, right-click the image and choose Add Polygon ROI.

  5. Right-click the ROI and choose Edit ROI…. Enter the calculated vertices in the kx and ky columns in their listed order. Turn on Closed.

  6. Right-click the ROI and choose Mask Data with ROI.

  7. Leave Invert Mask and Drop Masked Values off. Set Result Placement to Open Child Window, and create the masked map.

For other polygon boundaries, move the ROI handles or enter different coordinates. See Masking data with a polygonal ROI for the mask controls and result behavior.

Figure assembly

  1. In the constant-energy-map ImageTool, right-click the image and choose New Figure.

  2. Set Layout to a \(1 \times 2\) grid. Target the existing Image Plot step to the left axes. Set Gamma to 0.5 and Aspect to equal.

  3. In the masked-map child, right-click the image and choose Append to Figure. Select the same figure and the right axes. Set the new Image Plot step to the same gamma and aspect.

The single polygon boundary does not have an editable Figure Composer step.

Planned Figure Composer support

Figure Composer does not yet have an editable step for this plotting operation. Structured support is planned. Until then, add a Python step to the recipe and use the code in this section.

  1. Add a Python step after the left image. Review this code, then enter it in Code:

import numpy as np

import erlab

lattice_constant = 6.97
real_space_basis = lattice_constant * np.array(
    [
        [1.0, 0.0],
        [-0.5, np.sqrt(3) / 2],
    ]
)
first_bz_vertices = erlab.lattice.get_2d_vertices(
    real_space_basis,
    reciprocal=False,
    rotate=30.0,
)
closed_vertices = np.vstack([first_bz_vertices, first_bz_vertices[0]])
axs[0, 0].plot(
    closed_vertices[:, 0],
    closed_vertices[:, 1],
    color="tab:red",
)
  1. Add an ERLab Method step for unify_clim and target both axes.

  2. Add an ERLab Method step for clean_labels and target both axes.

  3. Add an ERLab Method step for set_titles and target both axes. Enter First Brillouin zone and Masked data on separate lines in Text.