{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "# Basic Data Exploration" ] }, { "cell_type": "code", "execution_count": null, "id": "1", "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import arpes\n", "from arpes.io import example_data\n", "\n", "f = example_data.cut" ] }, { "cell_type": "code", "execution_count": null, "id": "2", "metadata": {}, "outputs": [], "source": [ "f.S.plot()" ] }, { "cell_type": "markdown", "id": "3", "metadata": {}, "source": [ "Although we can plot the spectrum off of a `Dataset`, which might contain additional attributes like the photocurrent, beam current, temperature, or wall-clock time, by using `.S.plot()`, we can also get the spectrum attribute from the full data:" ] }, { "cell_type": "code", "execution_count": null, "id": "4", "metadata": {}, "outputs": [], "source": [ "f.spectrum" ] }, { "cell_type": "markdown", "id": "5", "metadata": {}, "source": [ "## Selecting Data" ] }, { "cell_type": "markdown", "id": "6", "metadata": {}, "source": [ "Typically, we will not want to use the full spectrometer window. Instead we will want to focus on a particular energy or momentum range, such as the region just above, below, or around the chemical potential, or at the energy distribution curves (EDCs) around a particular significant momentum. Data selections can be performed either on `Dataset`s or `DataArray`s. In the former case, it has the effect of selecting on a particular dimension or set of dimensions for each attribute that has those dimensions.\n", "\n", "In general, we do not need to know the indices of the region we want to select: we can use the physically meaningful coordinates. As an example, to get the band structure from our data `f` between the ground reference of the spectrometer (the chemical potential) and a point 200 millivolts below, we can use `.sel`." ] }, { "cell_type": "code", "execution_count": null, "id": "7", "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax = f.sel(eV=slice(-0.2, 0)).S.plot(ax=ax)\n", "fig.set_figheight(4)\n", "fig.tight_layout()\n", "fig" ] }, { "cell_type": "markdown", "id": "8", "metadata": {}, "source": [ "`.sel` accepts any number of dimensions specified by a `slice`. The arguments to the slice provide a low and high cutoff respectively.\n", "\n", "We can also select just a single point along an axis by passing a value instead of a slice. In general we will want to be safe and pass the `method='nearest'` argument, in order to ensure that if the exact value we requested is not included, we will get the nearest pixel." ] }, { "cell_type": "code", "execution_count": null, "id": "9", "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "# get the EDC nearly at the gamma point\n", "fig.set_figheight(4)\n", "ax = f.sel(phi=0.4, method=\"nearest\").S.plot(ax=ax)\n", "fig" ] }, { "cell_type": "markdown", "id": "10", "metadata": {}, "source": [ "Of course, we can select over a wider window for better statistics, so long as we average or sum out the angle axis after selecting." ] }, { "cell_type": "code", "execution_count": null, "id": "11", "metadata": {}, "outputs": [], "source": [ "# get the EDC nearly at the gamma point\n", "fig, ax = plt.subplots()\n", "fig.set_figheight(4)\n", "ax = f.sel(phi=slice(0.38, 0.42)).sum(\"phi\").S.plot()\n", "fig" ] }, { "cell_type": "markdown", "id": "12", "metadata": {}, "source": [ "### Selecting with array indices\n", "\n", "In instances where you would like to subselect by an index (ranging above from 0 to 239), as opposed to the physically significant coordinate value, we can use `.isel` instead." ] }, { "cell_type": "code", "execution_count": null, "id": "13", "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "fig.set_figheight(4)\n", "ax = f.isel(phi=40).S.plot(ax=ax)\n", "fig" ] }, { "cell_type": "markdown", "id": "14", "metadata": {}, "source": [ "### Open ended selections\n", "\n", "Selections can be made open ended on one or both sides by passing `None`. In the follow example, the inclusion of `None` will cause the selection to continue to the end of the data on the high end, i.e pixels 40 to 240 on the 'phi' axis." ] }, { "cell_type": "code", "execution_count": null, "id": "15", "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "fig.set_figheight(4)\n", "ax = f.isel(phi=slice(40, None)).S.plot(ax=ax)\n", "fig" ] }, { "cell_type": "markdown", "id": "16", "metadata": {}, "source": [ "## Summing and Averaging\n", "\n", "We saw above an example of taking a binned EDC by selecting a narrow angular region and taking the sum over that axis. We can also request means or sums over multiple axes with `.mean` and `.sum`." ] }, { "cell_type": "code", "execution_count": null, "id": "17", "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "fig.set_figheight(4)\n", "ax = f.mean(\"eV\", keep_attrs=True).S.plot(ax=ax)\n", "fig" ] }, { "cell_type": "code", "execution_count": null, "id": "18", "metadata": {}, "outputs": [], "source": [ "# to get the value as a plain float instead of a scalar dataset\n", "# use `.mean([\"eV\", \"phi\"]).item()` instead\n", "f.spectrum.mean([\"eV\", \"phi\"], keep_attrs=True)" ] }, { "cell_type": "markdown", "id": "19", "metadata": {}, "source": [ "**Caveat**: Summing an axis will remove all attributes unless the `keep_attrs=True` parameter is included in the call to `.sum`. Forgetting to do this where it is necessary can cause issues down the line for analysis that requires access to the attributes, such as in converting to momentum space, where the photon energy and coordinate offset for normal emission are stored as attributes." ] }, { "cell_type": "markdown", "id": "20", "metadata": {}, "source": [ "## Transposing\n", "\n", "To transpose axes, you can use `.transpose` or `.T`. In `xarray` and therefore in PyARPES, you interact with data using named dimensions. As a result, transposing is rarely necessary except to set axis order when plotting." ] }, { "cell_type": "code", "execution_count": null, "id": "21", "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "fig.set_figheight(4)\n", "ax = f.transpose(\"eV\", \"phi\").S.plot(ax=ax) # equivalently, f.T.S.plot() or f.transpose(\"eV\", ...)\n", "fig" ] }, { "cell_type": "markdown", "id": "22", "metadata": {}, "source": [ "## Interactive Data Browsing\n", "\n", "Facilities are included for doing interactive data exploration and analysis both directly in Jupyter, by using holoview via Bokeh. To learn more about interactive analysis, please read the interactive analysis section of the documentation." ] }, { "cell_type": "code", "execution_count": null, "id": "23", "metadata": {}, "outputs": [], "source": [ "f.spectrum.S.show()" ] }, { "cell_type": "markdown", "id": "24", "metadata": {}, "source": [ "## Learning more about data manipulation\n", "\n", "PyARPES uses the excellent [xarray](https://xarray.pydata.org) to provide a rich \"Wave\"-like data model. For non-spectroscopy related\n", "analysis tasks, you should read their documentation." ] }, { "cell_type": "markdown", "id": "25", "metadata": {}, "source": [ "### PyARPES philosophy on interactive tools\n", "\n", "Instead of one large interactive application where you perform analysis, PyARPES has many small interactive utilities which are built for a single purpose. From Ver 4.0.1 (pragmatically, from 4.0), the Qt based interactive tools are deprecated. Thus, the following tools cannot be used:\n", "\n", "1. A data browser: `arpes.plotting.qt_tool`\n", "2. A momentum offset browser: `arpes.plotting.qt_ktool.ktool`\n", "3. A tool for path selection: `arpes.plotting.basic_tools.path_tool`\n", "4. A tool for mask selection: `arpes.plotting.basic_tools.mask_tool`\n", "5. A tool to show a slice on a BZ recorded by the spectrometer or scan: `arpes.plotting.bz_tool.bz_tool`\n", "\n", "and others.\n", "\n", "Instead, holoviews based tools are prepared as necessary.\n", "\n", "1. For checking the intensity at the specific position: `arpes.plotting.profile_view`\n", "2. For interactive smoothing:\n", " ```python\n", " import arpes.plotting.SmoothingApp\n", " app = SmoothingApp(data)\n", " app.panel()\n", " ```\n", " \n", "3. For interactive differentiatal procedures (Maximum curvature, Minimum Gradient, Derivative):\n", " ```python\n", " import arpes.plotting.DifferentiateApp\n", " app = DifferentiateApp(data)\n", " app.panel()\n", " ```\n", " \n", "5. For interactive combine.concat_along_phi to Tailoring two ARPES data:\n", " ```python\n", " import arpes.plotting.TaylorApp\n", " app = TaylorApp(data)\n", " app.panel()\n", " ```\n", "\n", "6. To check the fitting results: `arpes.plotting.fit_inspection`\n", "\n", "PyARPES prefers simpler specific tools because it makes them easier to write and maintain, and because PyARPES prefers you do as much analysis via the notebook as possible. This makes for better, more reproducible science. That's why I have dropped Qt-based UI tools." ] }, { "cell_type": "markdown", "id": "26", "metadata": {}, "source": [ "## Exercises\n", "\n", "### Learning more about `xarray`\n", "\n", "1. Skim the [data structures guide](https://xarray.pydata.org/en/stable/user-guide/data-structures.html) at the `xarray` docs.\n", "2. Open a PyARPES Jupyter cell and print one of the piece of example data with `from arpes.io import example_data; example_data.cut` or similar. Make sure you can understand the correspondence between the [data structures guide](https://xarray.pydata.org/en/stable/user-guide/data-structures.html) and ARPES idioms.\n", "\n", "\n", "### Practicing data selection\n", "\n", "1. What happens if you select a range backward?\n", "2. What happens to attributes and coordinates when you select a single value or range?\n", "\n", "### Practicing interactive browsing\n", "1. Try using `profile_view` to find the projection of the gamma point in `example_data.map`? \n", "\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.11" } }, "nbformat": 4, "nbformat_minor": 5 }